Staging: wlan-ng: Eliminate a boatload of tertiaryAP-only code.
[firefly-linux-kernel-4.4.55.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 "version.h"
65
66
67 #include <linux/version.h>
68
69 #include <linux/if_arp.h>
70 #include <linux/module.h>
71 #include <linux/kernel.h>
72 #include <linux/wait.h>
73 #include <linux/sched.h>
74 #include <linux/types.h>
75 #include <linux/slab.h>
76 #include <linux/wireless.h>
77 #include <linux/netdevice.h>
78 #include <linux/delay.h>
79 #include <asm/io.h>
80 #include <asm/byteorder.h>
81 #include <linux/random.h>
82 #include <linux/usb.h>
83
84 #include "wlan_compat.h"
85
86 /*================================================================*/
87 /* Project Includes */
88
89 #include "p80211types.h"
90 #include "p80211hdr.h"
91 #include "p80211mgmt.h"
92 #include "p80211conv.h"
93 #include "p80211msg.h"
94 #include "p80211netdev.h"
95 #include "p80211metadef.h"
96 #include "p80211metastruct.h"
97 #include "hfa384x.h"
98 #include "prism2mgmt.h"
99
100 /*================================================================*/
101 /* Local Constants */
102
103
104 /*================================================================*/
105 /* Local Macros */
106
107 /* Converts 802.11 format rate specifications to prism2 */
108 #define p80211rate_to_p2bit(n)  ((((n)&~BIT7) == 2) ? BIT0 : \
109                                  (((n)&~BIT7) == 4) ? BIT1 : \
110                                  (((n)&~BIT7) == 11) ? BIT2 : \
111                                  (((n)&~BIT7) == 22) ? BIT3 : 0)
112
113 /*================================================================*/
114 /* Local Types */
115
116
117 /*================================================================*/
118 /* Local Static Definitions */
119
120
121 /*================================================================*/
122 /* Local Function Declarations */
123
124
125 /*================================================================*/
126 /* Function Definitions */
127
128
129 /*----------------------------------------------------------------
130 * prism2mgmt_powermgmt
131 *
132 * Set the power management state of this station's MAC.
133 *
134 * Arguments:
135 *       wlandev         wlan device structure
136 *       msgp            ptr to msg buffer
137 *
138 * Returns:
139 *       0       success and done
140 *       <0      success, but we're waiting for something to finish.
141 *       >0      an error occurred while handling the message.
142 * Side effects:
143 *
144 * Call context:
145 *       process thread  (usually)
146 *       interrupt
147 ----------------------------------------------------------------*/
148 int prism2mgmt_powermgmt(wlandevice_t *wlandev, void *msgp)
149 {
150         int                     result = 0;
151         hfa384x_t               *hw = wlandev->priv;
152         p80211msg_dot11req_powermgmt_t  *msg = msgp;
153
154         DBFENTER;
155
156         if (!hw->ap) {
157
158                 /*** STATION ***/
159
160                 /*
161                  * Set CNFPMENABLED (on or off)
162                  * Set CNFMULTICASTRX (if PM on, otherwise clear)
163                  * Spout a notice stating that SleepDuration and
164                  * HoldoverDuration and PMEPS also have an impact.
165                  */
166                 /* Powermgmt is currently unsupported for STA */
167                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
168                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
169         } else {
170
171                 /*** ACCESS POINT ***/
172
173                 /* Powermgmt is never supported for AP */
174                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
175                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
176         }
177
178         DBFEXIT;
179         return result;
180 }
181
182
183 /*----------------------------------------------------------------
184 * prism2mgmt_scan
185 *
186 * Initiate a scan for BSSs.
187 *
188 * This function corresponds to MLME-scan.request and part of
189 * MLME-scan.confirm.  As far as I can tell in the standard, there
190 * are no restrictions on when a scan.request may be issued.  We have
191 * to handle in whatever state the driver/MAC happen to be.
192 *
193 * Arguments:
194 *       wlandev         wlan device structure
195 *       msgp            ptr to msg buffer
196 *
197 * Returns:
198 *       0       success and done
199 *       <0      success, but we're waiting for something to finish.
200 *       >0      an error occurred while handling the message.
201 * Side effects:
202 *
203 * Call context:
204 *       process thread  (usually)
205 *       interrupt
206 ----------------------------------------------------------------*/
207 int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp)
208 {
209         int                     result = 0;
210         hfa384x_t               *hw = wlandev->priv;
211         p80211msg_dot11req_scan_t       *msg = msgp;
212         UINT16                  roamingmode, word;
213         int                     i, timeout;
214         int                     istmpenable = 0;
215
216         hfa384x_HostScanRequest_data_t  scanreq;
217
218         DBFENTER;
219
220         if (hw->ap) {
221                 WLAN_LOG_ERROR("Prism2 in AP mode cannot perform scans.\n");
222                 result = 1;
223                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
224                 goto exit;
225         }
226
227         /* gatekeeper check */
228         if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
229                                      hw->ident_sta_fw.minor,
230                                      hw->ident_sta_fw.variant) <
231             HFA384x_FIRMWARE_VERSION(1,3,2)) {
232                 WLAN_LOG_ERROR("HostScan not supported with current firmware (<1.3.2).\n");
233                 result = 1;
234                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
235                 goto exit;
236         }
237
238         memset(&scanreq, 0, sizeof(scanreq));
239
240         /* save current roaming mode */
241         result = hfa384x_drvr_getconfig16(hw,
242                         HFA384x_RID_CNFROAMINGMODE, &roamingmode);
243         if ( result ) {
244                 WLAN_LOG_ERROR("getconfig(ROAMMODE) failed. result=%d\n",
245                                 result);
246                 msg->resultcode.data =
247                         P80211ENUM_resultcode_implementation_failure;
248                 goto exit;
249         }
250
251         /* drop into mode 3 for the scan */
252         result = hfa384x_drvr_setconfig16(hw,
253                         HFA384x_RID_CNFROAMINGMODE,
254                         HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
255         if ( result ) {
256                 WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n",
257                                 result);
258                 msg->resultcode.data =
259                         P80211ENUM_resultcode_implementation_failure;
260                 goto exit;
261         }
262
263         /* active or passive? */
264         if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
265                                      hw->ident_sta_fw.minor,
266                                      hw->ident_sta_fw.variant) >
267             HFA384x_FIRMWARE_VERSION(1,5,0)) {
268                 if (msg->scantype.data != P80211ENUM_scantype_active) {
269                         word = host2hfa384x_16(msg->maxchanneltime.data);
270                 } else {
271                         word = 0;
272                 }
273                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL, word);
274                 if ( result ) {
275                         WLAN_LOG_WARNING("Passive scan not supported with "
276                                           "current firmware.  (<1.5.1)\n");
277                 }
278         }
279
280         /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
281         word = HFA384x_RATEBIT_2;
282         scanreq.txRate = host2hfa384x_16(word);
283
284         /* set up the channel list */
285         word = 0;
286         for (i = 0; i < msg->channellist.data.len; i++) {
287                 UINT8 channel = msg->channellist.data.data[i];
288                 if (channel > 14) continue;
289                 /* channel 1 is BIT0 ... channel 14 is BIT13 */
290                 word |= (1 << (channel-1));
291         }
292         scanreq.channelList = host2hfa384x_16(word);
293
294         /* set up the ssid, if present. */
295         scanreq.ssid.len = host2hfa384x_16(msg->ssid.data.len);
296         memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
297
298         /* Enable the MAC port if it's not already enabled  */
299         result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
300         if ( result ) {
301                 WLAN_LOG_ERROR("getconfig(PORTSTATUS) failed. "
302                                 "result=%d\n", result);
303                 msg->resultcode.data =
304                         P80211ENUM_resultcode_implementation_failure;
305                 goto exit;
306         }
307         if (word == HFA384x_PORTSTATUS_DISABLED) {
308                 UINT16 wordbuf[17];
309
310                 result = hfa384x_drvr_setconfig16(hw,
311                         HFA384x_RID_CNFROAMINGMODE,
312                         HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
313                 if ( result ) {
314                         WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n", result);
315                         msg->resultcode.data =
316                                 P80211ENUM_resultcode_implementation_failure;
317                         goto exit;
318                 }
319                 /* Construct a bogus SSID and assign it to OwnSSID and
320                  * DesiredSSID
321                  */
322                 wordbuf[0] = host2hfa384x_16(WLAN_SSID_MAXLEN);
323                 get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
324                 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
325                                 wordbuf, HFA384x_RID_CNFOWNSSID_LEN);
326                 if ( result ) {
327                         WLAN_LOG_ERROR("Failed to set OwnSSID.\n");
328                         msg->resultcode.data =
329                                 P80211ENUM_resultcode_implementation_failure;
330                         goto exit;
331                 }
332                 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID,
333                                 wordbuf, HFA384x_RID_CNFDESIREDSSID_LEN);
334                 if ( result ) {
335                         WLAN_LOG_ERROR("Failed to set DesiredSSID.\n");
336                         msg->resultcode.data =
337                                 P80211ENUM_resultcode_implementation_failure;
338                         goto exit;
339                 }
340                 /* bsstype */
341                 result = hfa384x_drvr_setconfig16(hw,
342                                 HFA384x_RID_CNFPORTTYPE,
343                                 HFA384x_PORTTYPE_IBSS);
344                 if ( result ) {
345                         WLAN_LOG_ERROR("Failed to set CNFPORTTYPE.\n");
346                         msg->resultcode.data =
347                                 P80211ENUM_resultcode_implementation_failure;
348                         goto exit;
349                 }
350                 /* ibss options */
351                 result = hfa384x_drvr_setconfig16(hw,
352                                 HFA384x_RID_CREATEIBSS,
353                                 HFA384x_CREATEIBSS_JOINCREATEIBSS);
354                 if ( result ) {
355                         WLAN_LOG_ERROR("Failed to set CREATEIBSS.\n");
356                         msg->resultcode.data =
357                                 P80211ENUM_resultcode_implementation_failure;
358                         goto exit;
359                 }
360                 result = hfa384x_drvr_enable(hw, 0);
361                 if ( result ) {
362                         WLAN_LOG_ERROR("drvr_enable(0) failed. "
363                                         "result=%d\n", result);
364                         msg->resultcode.data =
365                         P80211ENUM_resultcode_implementation_failure;
366                         goto exit;
367                 }
368                 istmpenable = 1;
369         }
370
371         /* Figure out our timeout first Kus, then HZ */
372         timeout = msg->channellist.data.len * msg->maxchanneltime.data;
373         timeout = (timeout * HZ)/1000;
374
375         /* Issue the scan request */
376         hw->scanflag = 0;
377
378         WLAN_HEX_DUMP(5,"hscanreq", &scanreq, sizeof(scanreq));
379
380         result = hfa384x_drvr_setconfig( hw,
381                         HFA384x_RID_HOSTSCAN, &scanreq,
382                         sizeof(hfa384x_HostScanRequest_data_t));
383         if ( result ) {
384                 WLAN_LOG_ERROR("setconfig(SCANREQUEST) failed. result=%d\n",
385                                 result);
386                 msg->resultcode.data =
387                         P80211ENUM_resultcode_implementation_failure;
388                 goto exit;
389         }
390
391         /* sleep until info frame arrives */
392         wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
393
394         msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
395         if (hw->scanflag == -1)
396                 hw->scanflag = 0;
397
398         msg->numbss.data = hw->scanflag;
399
400         hw->scanflag = 0;
401
402         /* Disable port if we temporarily enabled it. */
403         if (istmpenable) {
404                 result = hfa384x_drvr_disable(hw, 0);
405                 if ( result ) {
406                         WLAN_LOG_ERROR("drvr_disable(0) failed. "
407                                         "result=%d\n", result);
408                         msg->resultcode.data =
409                         P80211ENUM_resultcode_implementation_failure;
410                         goto exit;
411                 }
412         }
413
414         /* restore original roaming mode */
415         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
416                                           roamingmode);
417         if ( result ) {
418                 WLAN_LOG_ERROR("setconfig(ROAMMODE) failed. result=%d\n",
419                                 result);
420                 msg->resultcode.data =
421                         P80211ENUM_resultcode_implementation_failure;
422                 goto exit;
423         }
424
425         result = 0;
426         msg->resultcode.data = P80211ENUM_resultcode_success;
427
428  exit:
429         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
430
431         DBFEXIT;
432         return result;
433 }
434
435
436 /*----------------------------------------------------------------
437 * prism2mgmt_scan_results
438 *
439 * Retrieve the BSS description for one of the BSSs identified in
440 * a scan.
441 *
442 * Arguments:
443 *       wlandev         wlan device structure
444 *       msgp            ptr to msg buffer
445 *
446 * Returns:
447 *       0       success and done
448 *       <0      success, but we're waiting for something to finish.
449 *       >0      an error occurred while handling the message.
450 * Side effects:
451 *
452 * Call context:
453 *       process thread  (usually)
454 *       interrupt
455 ----------------------------------------------------------------*/
456 int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
457 {
458         int                     result = 0;
459         p80211msg_dot11req_scan_results_t       *req;
460         hfa384x_t               *hw = wlandev->priv;
461         hfa384x_HScanResultSub_t *item = NULL;
462
463         int count;
464
465         DBFENTER;
466
467         req = (p80211msg_dot11req_scan_results_t *) msgp;
468
469         req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
470
471         if (hw->ap) {
472                 result = 1;
473                 req->resultcode.data = P80211ENUM_resultcode_not_supported;
474                 goto exit;
475         }
476
477         if (! hw->scanresults) {
478                 WLAN_LOG_ERROR("dot11req_scan_results can only be used after a successful dot11req_scan.\n");
479                 result = 2;
480                 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
481                 goto exit;
482         }
483
484         count = (hw->scanresults->framelen - 3) / 32;
485         if (count > 32)  count = 32;
486
487         if (req->bssindex.data >= count) {
488                 WLAN_LOG_DEBUG(0, "requested index (%d) out of range (%d)\n",
489                                 req->bssindex.data, count);
490                 result = 2;
491                 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
492                 goto exit;
493         }
494
495         item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]);
496         /* signal and noise */
497         req->signal.status = P80211ENUM_msgitem_status_data_ok;
498         req->noise.status = P80211ENUM_msgitem_status_data_ok;
499         req->signal.data = hfa384x2host_16(item->sl);
500         req->noise.data = hfa384x2host_16(item->anl);
501
502         /* BSSID */
503         req->bssid.status = P80211ENUM_msgitem_status_data_ok;
504         req->bssid.data.len = WLAN_BSSID_LEN;
505         memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
506
507         /* SSID */
508         req->ssid.status = P80211ENUM_msgitem_status_data_ok;
509         req->ssid.data.len = hfa384x2host_16(item->ssid.len);
510         memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
511
512         /* supported rates */
513         for (count = 0; count < 10 ; count++)
514                 if (item->supprates[count] == 0)
515                         break;
516
517 #define REQBASICRATE(N) \
518         if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \
519                 req->basicrate ## N .data = item->supprates[(N)-1]; \
520                 req->basicrate ## N .status = P80211ENUM_msgitem_status_data_ok; \
521         }
522
523         REQBASICRATE(1);
524         REQBASICRATE(2);
525         REQBASICRATE(3);
526         REQBASICRATE(4);
527         REQBASICRATE(5);
528         REQBASICRATE(6);
529         REQBASICRATE(7);
530         REQBASICRATE(8);
531
532 #define REQSUPPRATE(N) \
533         if (count >= N) { \
534                 req->supprate ## N .data = item->supprates[(N)-1]; \
535                 req->supprate ## N .status = P80211ENUM_msgitem_status_data_ok; \
536         }
537
538         REQSUPPRATE(1);
539         REQSUPPRATE(2);
540         REQSUPPRATE(3);
541         REQSUPPRATE(4);
542         REQSUPPRATE(5);
543         REQSUPPRATE(6);
544         REQSUPPRATE(7);
545         REQSUPPRATE(8);
546
547         /* beacon period */
548         req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
549         req->beaconperiod.data = hfa384x2host_16(item->bcnint);
550
551         /* timestamps */
552         req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
553         req->timestamp.data = jiffies;
554         req->localtime.status = P80211ENUM_msgitem_status_data_ok;
555         req->localtime.data = jiffies;
556
557         /* atim window */
558         req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
559         req->ibssatimwindow.data = hfa384x2host_16(item->atim);
560
561         /* Channel */
562         req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
563         req->dschannel.data = hfa384x2host_16(item->chid);
564
565         /* capinfo bits */
566         count = hfa384x2host_16(item->capinfo);
567
568         /* privacy flag */
569         req->privacy.status = P80211ENUM_msgitem_status_data_ok;
570         req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
571
572         /* cfpollable */
573         req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
574         req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
575
576         /* cfpollreq */
577         req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
578         req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
579
580         /* bsstype */
581         req->bsstype.status =  P80211ENUM_msgitem_status_data_ok;
582         req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
583                 P80211ENUM_bsstype_infrastructure :
584                 P80211ENUM_bsstype_independent;
585
586         // item->proberesp_rate
587 /*
588         req->fhdwelltime
589         req->fhhopset
590         req->fhhoppattern
591         req->fhhopindex
592         req->cfpdurremaining
593 */
594
595         result = 0;
596         req->resultcode.data = P80211ENUM_resultcode_success;
597
598  exit:
599         DBFEXIT;
600         return result;
601 }
602
603
604 /*----------------------------------------------------------------
605 * prism2mgmt_join
606 *
607 * Join a BSS whose BSS description was previously obtained with
608 * a scan.
609 *
610 * Arguments:
611 *       wlandev         wlan device structure
612 *       msgp            ptr to msg buffer
613 *
614 * Returns:
615 *       0       success and done
616 *       <0      success, but we're waiting for something to finish.
617 *       >0      an error occurred while handling the message.
618 * Side effects:
619 *
620 * Call context:
621 *       process thread  (usually)
622 *       interrupt
623 ----------------------------------------------------------------*/
624 int prism2mgmt_join(wlandevice_t *wlandev, void *msgp)
625 {
626         int                     result = 0;
627         hfa384x_t               *hw = wlandev->priv;
628         p80211msg_dot11req_join_t       *msg = msgp;
629         DBFENTER;
630
631         if (!hw->ap) {
632
633                 /*** STATION ***/
634
635                 /* TODO: Implement after scan */
636                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
637                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
638         } else {
639
640                 /*** ACCESS POINT ***/
641
642                 /* Never supported by APs */
643                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
644                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
645         }
646
647         DBFEXIT;
648         return result;
649 }
650
651
652 /*----------------------------------------------------------------
653 * prism2mgmt_p2_join
654 *
655 * Join a specific BSS
656 *
657 * Arguments:
658 *       wlandev         wlan device structure
659 *       msgp            ptr to msg buffer
660 *
661 * Returns:
662 *       0       success and done
663 *       <0      success, but we're waiting for something to finish.
664 *       >0      an error occurred while handling the message.
665 * Side effects:
666 *
667 * Call context:
668 *       process thread  (usually)
669 *       interrupt
670 ----------------------------------------------------------------*/
671 int prism2mgmt_p2_join(wlandevice_t *wlandev, void *msgp)
672 {
673         int                     result = 0;
674         hfa384x_t               *hw = wlandev->priv;
675         p80211msg_p2req_join_t  *msg = msgp;
676         UINT16                  reg;
677         p80211pstrd_t           *pstr;
678         UINT8                   bytebuf[256];
679         hfa384x_bytestr_t       *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
680         hfa384x_JoinRequest_data_t      joinreq;
681         DBFENTER;
682
683         if (!hw->ap) {
684
685                 wlandev->macmode = WLAN_MACMODE_NONE;
686
687                 /*** STATION ***/
688                 /* Set the PortType */
689                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
690                 msg->resultcode.data = P80211ENUM_resultcode_success;
691
692                 /* ess port */
693                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 1);
694                 if ( result ) {
695                         WLAN_LOG_ERROR("Failed to set Port Type\n");
696                         goto failed;
697                 }
698
699                 /* Set the auth type */
700                 if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) {
701                         reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
702                 } else {
703                         reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
704                 }
705                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
706                 if ( result ) {
707                         WLAN_LOG_ERROR("Failed to set Authentication\n");
708                         goto failed;
709                 }
710
711                 /* Turn off all roaming */
712                 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE, 3);
713                 if ( result ) {
714                         WLAN_LOG_ERROR("Failed to Turn off Roaming\n");
715                         goto failed;
716                 }
717
718                 /* Basic rates */
719                 reg = 0;
720                 if ( msg->basicrate1.status == P80211ENUM_msgitem_status_data_ok ) {
721                         reg = p80211rate_to_p2bit(msg->basicrate1.data);
722                 }
723                 if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) {
724                         reg |= p80211rate_to_p2bit(msg->basicrate2.data);
725                 }
726                 if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) {
727                         reg |= p80211rate_to_p2bit(msg->basicrate3.data);
728                 }
729                 if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) {
730                         reg |= p80211rate_to_p2bit(msg->basicrate4.data);
731                 }
732                 if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) {
733                         reg |= p80211rate_to_p2bit(msg->basicrate5.data);
734                 }
735                 if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) {
736                         reg |= p80211rate_to_p2bit(msg->basicrate6.data);
737                 }
738                 if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) {
739                         reg |= p80211rate_to_p2bit(msg->basicrate7.data);
740                 }
741                 if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) {
742                         reg |= p80211rate_to_p2bit(msg->basicrate8.data);
743                 }
744                 if( reg == 0)
745                          reg = 0x03;
746                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, reg);
747                 if ( result ) {
748                         WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", reg);
749                         goto failed;
750                 }
751
752                 /* Operational rates (supprates and txratecontrol) */
753                 reg = 0;
754                 if ( msg->operationalrate1.status == P80211ENUM_msgitem_status_data_ok ) {
755                         reg = p80211rate_to_p2bit(msg->operationalrate1.data);
756                 }
757                 if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) {
758                         reg |= p80211rate_to_p2bit(msg->operationalrate2.data);
759                 }
760                 if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) {
761                         reg |= p80211rate_to_p2bit(msg->operationalrate3.data);
762                 }
763                 if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) {
764                         reg |= p80211rate_to_p2bit(msg->operationalrate4.data);
765                 }
766                 if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) {
767                         reg |= p80211rate_to_p2bit(msg->operationalrate5.data);
768                 }
769                 if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) {
770                         reg |= p80211rate_to_p2bit(msg->operationalrate6.data);
771                 }
772                 if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) {
773                         reg |= p80211rate_to_p2bit(msg->operationalrate7.data);
774                 }
775                 if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) {
776                         reg |= p80211rate_to_p2bit(msg->operationalrate8.data);
777                 }
778                 if( reg == 0)
779                          reg = 0x0f;
780                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, reg);
781                 if ( result ) {
782                         WLAN_LOG_ERROR("Failed to set supprates=%d.\n", reg);
783                         goto failed;
784                 }
785
786                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, reg);
787                 if ( result ) {
788                         WLAN_LOG_ERROR("Failed to set txrates=%d.\n", reg);
789                         goto failed;
790                 }
791
792                 /* Set the ssid */
793                 memset(bytebuf, 0, 256);
794                 pstr = (p80211pstrd_t*)&(msg->ssid.data);
795                 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
796                 result = hfa384x_drvr_setconfig(
797                         hw, HFA384x_RID_CNFDESIREDSSID,
798                         bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
799                 if ( result ) {
800                         WLAN_LOG_ERROR("Failed to set SSID\n");
801                         goto failed;
802                 }
803
804                 /* Enable the Port */
805                 result = hfa384x_cmd_enable(hw, 0);
806                 if ( result ) {
807                         WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result);
808                         goto failed;
809                 }
810
811                 /* Fill in the join request */
812                 joinreq.channel = msg->channel.data;
813                 memcpy( joinreq.bssid, ((unsigned char *) &msg->bssid.data) + 1, WLAN_BSSID_LEN);
814                 hw->joinreq = joinreq;
815                 hw->join_ap = 1;
816
817                 /* Send the join request */
818                 result = hfa384x_drvr_setconfig( hw,
819                         HFA384x_RID_JOINREQUEST,
820                         &joinreq, HFA384x_RID_JOINREQUEST_LEN);
821                 if(result != 0) {
822                         WLAN_LOG_ERROR("Join request failed, result=%d.\n", result);
823                         goto failed;
824                 }
825
826         } else {
827
828                 /*** ACCESS POINT ***/
829
830                 /* Never supported by APs */
831                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
832                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
833         }
834
835         goto done;
836 failed:
837         WLAN_LOG_DEBUG(1, "Failed to set a config option, result=%d\n", result);
838         msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
839
840 done:
841         result = 0;
842
843         DBFEXIT;
844         return result;
845 }
846
847
848 /*----------------------------------------------------------------
849 * prism2mgmt_authenticate
850 *
851 * Station should be begin an authentication exchange.
852 *
853 * Arguments:
854 *       wlandev         wlan device structure
855 *       msgp            ptr to msg buffer
856 *
857 * Returns:
858 *       0       success and done
859 *       <0      success, but we're waiting for something to finish.
860 *       >0      an error occurred while handling the message.
861 * Side effects:
862 *
863 * Call context:
864 *       process thread  (usually)
865 *       interrupt
866 ----------------------------------------------------------------*/
867 int prism2mgmt_authenticate(wlandevice_t *wlandev, void *msgp)
868 {
869         int                     result = 0;
870         hfa384x_t               *hw = wlandev->priv;
871         p80211msg_dot11req_authenticate_t       *msg = msgp;
872         DBFENTER;
873
874         if (!hw->ap) {
875
876                 /*** STATION ***/
877
878                 /* TODO: Decide how we're going to handle this one w/ Prism2 */
879                 /*       It could be entertaining since Prism2 doesn't have  */
880                 /*       an explicit way to control this */
881                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
882                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
883         } else {
884
885                 /*** ACCESS POINT ***/
886
887                 /* Never supported by APs */
888                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
889                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
890         }
891
892         DBFEXIT;
893         return result;
894 }
895
896
897 /*----------------------------------------------------------------
898 * prism2mgmt_deauthenticate
899 *
900 * Send a deauthenticate notification.
901 *
902 * Arguments:
903 *       wlandev         wlan device structure
904 *       msgp            ptr to msg buffer
905 *
906 * Returns:
907 *       0       success and done
908 *       <0      success, but we're waiting for something to finish.
909 *       >0      an error occurred while handling the message.
910 * Side effects:
911 *
912 * Call context:
913 *       process thread  (usually)
914 *       interrupt
915 ----------------------------------------------------------------*/
916 int prism2mgmt_deauthenticate(wlandevice_t *wlandev, void *msgp)
917 {
918         int                     result = 0;
919         hfa384x_t               *hw = wlandev->priv;
920         p80211msg_dot11req_deauthenticate_t     *msg = msgp;
921         DBFENTER;
922
923         if (!hw->ap) {
924
925                 /*** STATION ***/
926
927                 /* TODO: Decide how we're going to handle this one w/ Prism2 */
928                 /*       It could be entertaining since Prism2 doesn't have  */
929                 /*       an explicit way to control this */
930                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
931                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
932         } else {
933
934                 /*** ACCESS POINT ***/
935                 hfa384x_drvr_handover(hw, msg->peerstaaddress.data.data);
936                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
937                 msg->resultcode.data = P80211ENUM_resultcode_success;
938         }
939
940         DBFEXIT;
941         return result;
942 }
943
944
945 /*----------------------------------------------------------------
946 * prism2mgmt_associate
947 *
948 * Associate with an ESS.
949 *
950 * Arguments:
951 *       wlandev         wlan device structure
952 *       msgp            ptr to msg buffer
953 *
954 * Returns:
955 *       0       success and done
956 *       <0      success, but we're waiting for something to finish.
957 *       >0      an error occurred while handling the message.
958 * Side effects:
959 *
960 * Call context:
961 *       process thread  (usually)
962 *       interrupt
963 ----------------------------------------------------------------*/
964 int prism2mgmt_associate(wlandevice_t *wlandev, void *msgp)
965 {
966         hfa384x_t               *hw = wlandev->priv;
967         int                     result = 0;
968         p80211msg_dot11req_associate_t  *msg = msgp;
969         DBFENTER;
970
971         if (!hw->ap) {
972
973                 /*** STATION ***/
974
975 #if 0
976                 /* Set the TxRates */
977                 reg = 0x000f;
978                 hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, reg);
979 #endif
980
981                 /* Set the PortType */
982                 /* ess port */
983                 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 1);
984
985                 /* Enable the Port */
986                 hfa384x_drvr_enable(hw, 0);
987
988                 /* Set the resultcode */
989                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
990                 msg->resultcode.data = P80211ENUM_resultcode_success;
991
992         } else {
993
994                 /*** ACCESS POINT ***/
995
996                 /* Never supported on AP */
997                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
998                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
999         }
1000
1001         DBFEXIT;
1002         return result;
1003 }
1004
1005
1006 /*----------------------------------------------------------------
1007 * prism2mgmt_reassociate
1008 *
1009 * Renew association because of a BSS change.
1010 *
1011 * Arguments:
1012 *       wlandev         wlan device structure
1013 *       msgp            ptr to msg buffer
1014 *
1015 * Returns:
1016 *       0       success and done
1017 *       <0      success, but we're waiting for something to finish.
1018 *       >0      an error occurred while handling the message.
1019 * Side effects:
1020 *
1021 * Call context:
1022 *       process thread  (usually)
1023 *       interrupt
1024 ----------------------------------------------------------------*/
1025 int prism2mgmt_reassociate(wlandevice_t *wlandev, void *msgp)
1026 {
1027         int                     result = 0;
1028         hfa384x_t               *hw = wlandev->priv;
1029         p80211msg_dot11req_reassociate_t        *msg = msgp;
1030         DBFENTER;
1031
1032         if (!hw->ap) {
1033
1034                 /*** STATION ***/
1035
1036                 /* TODO: Not supported yet...not sure how we're going to do it */
1037                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1038                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
1039         } else {
1040
1041                 /*** ACCESS POINT ***/
1042
1043                 /* Never supported on AP */
1044                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1045                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
1046         }
1047
1048         DBFEXIT;
1049         return result;
1050 }
1051
1052
1053 /*----------------------------------------------------------------
1054 * prism2mgmt_disassociate
1055 *
1056 * Send a disassociation notification.
1057 *
1058 * Arguments:
1059 *       wlandev         wlan device structure
1060 *       msgp            ptr to msg buffer
1061 *
1062 * Returns:
1063 *       0       success and done
1064 *       <0      success, but we're waiting for something to finish.
1065 *       >0      an error occurred while handling the message.
1066 * Side effects:
1067 *
1068 * Call context:
1069 *       process thread  (usually)
1070 *       interrupt
1071 ----------------------------------------------------------------*/
1072 int prism2mgmt_disassociate(wlandevice_t *wlandev, void *msgp)
1073 {
1074         int                     result = 0;
1075         hfa384x_t               *hw = wlandev->priv;
1076         p80211msg_dot11req_disassociate_t       *msg = msgp;
1077         DBFENTER;
1078
1079         if (!hw->ap) {
1080
1081                 /*** STATION ***/
1082
1083                 /* TODO: Not supported yet...not sure how to do it */
1084                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1085                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
1086         } else {
1087
1088                 /*** ACCESS POINT ***/
1089                 hfa384x_drvr_handover(hw, msg->peerstaaddress.data.data);
1090                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1091                 msg->resultcode.data = P80211ENUM_resultcode_success;
1092         }
1093
1094         DBFEXIT;
1095         return result;
1096 }
1097
1098
1099 /*----------------------------------------------------------------
1100 * prism2mgmt_reset
1101 *
1102 * Reset the MAC and MSD.  The p80211 layer has it's own handling
1103 * that should be done before and after this function.
1104 * Procedure:
1105 *   - disable system interrupts ??
1106 *   - disable MAC interrupts
1107 *   - restore system interrupts
1108 *   - issue the MAC initialize command
1109 *   - clear any MSD level state (including timers, queued events,
1110 *     etc.).  Note that if we're removing timer'd/queue events, we may
1111 *     need to have remained in the system interrupt disabled state.
1112 *     We should be left in the same state that we're in following
1113 *     driver initialization.
1114 *
1115 * Arguments:
1116 *       wlandev         wlan device structure
1117 *       msgp            ptr to msg buffer, MAY BE NULL! for a driver local
1118 *                       call.
1119 *
1120 * Returns:
1121 *       0       success and done
1122 *       <0      success, but we're waiting for something to finish.
1123 *       >0      an error occurred while handling the message.
1124 * Side effects:
1125 *
1126 * Call context:
1127 *       process thread, commonly wlanctl, but might be rmmod/pci_close.
1128 ----------------------------------------------------------------*/
1129 int prism2mgmt_reset(wlandevice_t *wlandev, void *msgp)
1130 {
1131         int                     result = 0;
1132         hfa384x_t               *hw = wlandev->priv;
1133         p80211msg_dot11req_reset_t      *msg = msgp;
1134         DBFENTER;
1135
1136         /*
1137          * This is supported on both AP and STA and it's not allowed
1138          * to fail.
1139          */
1140         if ( msgp ) {
1141                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1142                 msg->resultcode.data = P80211ENUM_resultcode_success;
1143                 WLAN_LOG_INFO("dot11req_reset: the macaddress and "
1144                         "setdefaultmib arguments are currently unsupported.\n");
1145         }
1146
1147         /*
1148          * If we got this far, the MSD must be in the MSDRUNNING state
1149          * therefore, we must stop and then restart the hw/MAC combo.
1150          */
1151         hfa384x_drvr_stop(hw);
1152         result = hfa384x_drvr_start(hw);
1153         if (result != 0) {
1154                 WLAN_LOG_ERROR("dot11req_reset: Initialize command failed,"
1155                                 " bad things will happen from here.\n");
1156                 return 0;
1157         }
1158
1159         DBFEXIT;
1160         return 0;
1161 }
1162
1163
1164 /*----------------------------------------------------------------
1165 * prism2mgmt_start
1166 *
1167 * Start a BSS.  Any station can do this for IBSS, only AP for ESS.
1168 *
1169 * Arguments:
1170 *       wlandev         wlan device structure
1171 *       msgp            ptr to msg buffer
1172 *
1173 * Returns:
1174 *       0       success and done
1175 *       <0      success, but we're waiting for something to finish.
1176 *       >0      an error occurred while handling the message.
1177 * Side effects:
1178 *
1179 * Call context:
1180 *       process thread  (usually)
1181 *       interrupt
1182 ----------------------------------------------------------------*/
1183 int prism2mgmt_start(wlandevice_t *wlandev, void *msgp)
1184 {
1185         int                     result = 0;
1186         hfa384x_t               *hw = wlandev->priv;
1187         p80211msg_dot11req_start_t      *msg = msgp;
1188
1189         p80211pstrd_t           *pstr;
1190         UINT8                   bytebuf[80];
1191         hfa384x_bytestr_t       *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
1192         hfa384x_PCFInfo_data_t  *pcfinfo = (hfa384x_PCFInfo_data_t*)bytebuf;
1193         UINT16                  word;
1194         DBFENTER;
1195
1196         wlandev->macmode = WLAN_MACMODE_NONE;
1197
1198         /* Set the SSID */
1199         memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
1200
1201         if (!hw->ap) {
1202                 /*** ADHOC IBSS ***/
1203                 /* see if current f/w is less than 8c3 */
1204                 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
1205                                              hw->ident_sta_fw.minor,
1206                                              hw->ident_sta_fw.variant) <
1207                     HFA384x_FIRMWARE_VERSION(0,8,3)) {
1208                         /* Ad-Hoc not quite supported on Prism2 */
1209                         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1210                         msg->resultcode.data = P80211ENUM_resultcode_not_supported;
1211                         goto done;
1212                 }
1213
1214                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1215
1216                 /*** STATION ***/
1217                 /* Set the REQUIRED config items */
1218                 /* SSID */
1219                 pstr = (p80211pstrd_t*)&(msg->ssid.data);
1220                 prism2mgmt_pstr2bytestr(p2bytestr, pstr);
1221                 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
1222                                 bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
1223                 if ( result ) {
1224                         WLAN_LOG_ERROR("Failed to set CnfOwnSSID\n");
1225                         goto failed;
1226                 }
1227                 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID,
1228                                 bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
1229                 if ( result ) {
1230                         WLAN_LOG_ERROR("Failed to set CnfDesiredSSID\n");
1231                         goto failed;
1232                 }
1233
1234                 /* bsstype - we use the default in the ap firmware */
1235                 /* IBSS port */
1236                 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
1237
1238                 /* beacon period */
1239                 word = msg->beaconperiod.data;
1240                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNINT, word);
1241                 if ( result ) {
1242                         WLAN_LOG_ERROR("Failed to set beacon period=%d.\n", word);
1243                         goto failed;
1244                 }
1245
1246                 /* dschannel */
1247                 word = msg->dschannel.data;
1248                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
1249                 if ( result ) {
1250                         WLAN_LOG_ERROR("Failed to set channel=%d.\n", word);
1251                         goto failed;
1252                 }
1253                 /* Basic rates */
1254                 word = p80211rate_to_p2bit(msg->basicrate1.data);
1255                 if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) {
1256                         word |= p80211rate_to_p2bit(msg->basicrate2.data);
1257                 }
1258                 if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) {
1259                         word |= p80211rate_to_p2bit(msg->basicrate3.data);
1260                 }
1261                 if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) {
1262                         word |= p80211rate_to_p2bit(msg->basicrate4.data);
1263                 }
1264                 if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) {
1265                         word |= p80211rate_to_p2bit(msg->basicrate5.data);
1266                 }
1267                 if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) {
1268                         word |= p80211rate_to_p2bit(msg->basicrate6.data);
1269                 }
1270                 if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) {
1271                         word |= p80211rate_to_p2bit(msg->basicrate7.data);
1272                 }
1273                 if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) {
1274                         word |= p80211rate_to_p2bit(msg->basicrate8.data);
1275                 }
1276                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
1277                 if ( result ) {
1278                         WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", word);
1279                         goto failed;
1280                 }
1281
1282                 /* Operational rates (supprates and txratecontrol) */
1283                 word = p80211rate_to_p2bit(msg->operationalrate1.data);
1284                 if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) {
1285                         word |= p80211rate_to_p2bit(msg->operationalrate2.data);
1286                 }
1287                 if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) {
1288                         word |= p80211rate_to_p2bit(msg->operationalrate3.data);
1289                 }
1290                 if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) {
1291                         word |= p80211rate_to_p2bit(msg->operationalrate4.data);
1292                 }
1293                 if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) {
1294                         word |= p80211rate_to_p2bit(msg->operationalrate5.data);
1295                 }
1296                 if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) {
1297                         word |= p80211rate_to_p2bit(msg->operationalrate6.data);
1298                 }
1299                 if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) {
1300                         word |= p80211rate_to_p2bit(msg->operationalrate7.data);
1301                 }
1302                 if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) {
1303                         word |= p80211rate_to_p2bit(msg->operationalrate8.data);
1304                 }
1305                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
1306                 if ( result ) {
1307                         WLAN_LOG_ERROR("Failed to set supprates=%d.\n", word);
1308                         goto failed;
1309                 }
1310
1311                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
1312                 if ( result ) {
1313                         WLAN_LOG_ERROR("Failed to set txrates=%d.\n", word);
1314                         goto failed;
1315                 }
1316
1317                 /* Set the macmode so the frame setup code knows what to do */
1318                 if ( msg->bsstype.data == P80211ENUM_bsstype_independent ) {
1319                         wlandev->macmode = WLAN_MACMODE_IBSS_STA;
1320                         /* lets extend the data length a bit */
1321                         hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
1322                 }
1323
1324                 /* Enable the Port */
1325                 result = hfa384x_drvr_enable(hw, 0);
1326                 if ( result ) {
1327                         WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result);
1328                         goto failed;
1329                 }
1330
1331                 msg->resultcode.data = P80211ENUM_resultcode_success;
1332
1333                 goto done;
1334         }
1335
1336         /*** ACCESS POINT ***/
1337
1338         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1339
1340         /* Validate the command, if BSStype=infra is the tertiary loaded? */
1341         if ( msg->bsstype.data == P80211ENUM_bsstype_independent ) {
1342                 WLAN_LOG_ERROR("AP driver cannot create IBSS.\n");
1343                 goto failed;
1344         } else if ( hw->cap_sup_sta.id != 5) {
1345                 WLAN_LOG_ERROR("AP driver failed to detect AP firmware.\n");
1346                 goto failed;
1347         }
1348
1349         /* Set the REQUIRED config items */
1350         /* SSID */
1351         pstr = (p80211pstrd_t*)&(msg->ssid.data);
1352         prism2mgmt_pstr2bytestr(p2bytestr, pstr);
1353         result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
1354                                 bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
1355         if ( result ) {
1356                 WLAN_LOG_ERROR("Failed to set SSID, result=0x%04x\n", result);
1357                 goto failed;
1358         }
1359
1360         /* bsstype - we use the default in the ap firmware */
1361
1362         /* beacon period */
1363         word = msg->beaconperiod.data;
1364         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNINT, word);
1365         if ( result ) {
1366                 WLAN_LOG_ERROR("Failed to set beacon period=%d.\n", word);
1367                 goto failed;
1368         }
1369
1370         /* dschannel */
1371         word = msg->dschannel.data;
1372         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
1373         if ( result ) {
1374                 WLAN_LOG_ERROR("Failed to set channel=%d.\n", word);
1375                 goto failed;
1376         }
1377         /* Basic rates */
1378         word = p80211rate_to_p2bit(msg->basicrate1.data);
1379         if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) {
1380                 word |= p80211rate_to_p2bit(msg->basicrate2.data);
1381         }
1382         if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) {
1383                 word |= p80211rate_to_p2bit(msg->basicrate3.data);
1384         }
1385         if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) {
1386                 word |= p80211rate_to_p2bit(msg->basicrate4.data);
1387         }
1388         if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) {
1389                 word |= p80211rate_to_p2bit(msg->basicrate5.data);
1390         }
1391         if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) {
1392                 word |= p80211rate_to_p2bit(msg->basicrate6.data);
1393         }
1394         if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) {
1395                 word |= p80211rate_to_p2bit(msg->basicrate7.data);
1396         }
1397         if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) {
1398                 word |= p80211rate_to_p2bit(msg->basicrate8.data);
1399         }
1400         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
1401         if ( result ) {
1402                 WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", word);
1403                 goto failed;
1404         }
1405
1406         /* Operational rates (supprates and txratecontrol) */
1407         word = p80211rate_to_p2bit(msg->operationalrate1.data);
1408         if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) {
1409                 word |= p80211rate_to_p2bit(msg->operationalrate2.data);
1410         }
1411         if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) {
1412                 word |= p80211rate_to_p2bit(msg->operationalrate3.data);
1413         }
1414         if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) {
1415                 word |= p80211rate_to_p2bit(msg->operationalrate4.data);
1416         }
1417         if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) {
1418                 word |= p80211rate_to_p2bit(msg->operationalrate5.data);
1419         }
1420         if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) {
1421                 word |= p80211rate_to_p2bit(msg->operationalrate6.data);
1422         }
1423         if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) {
1424                 word |= p80211rate_to_p2bit(msg->operationalrate7.data);
1425         }
1426         if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) {
1427                 word |= p80211rate_to_p2bit(msg->operationalrate8.data);
1428         }
1429         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
1430         if ( result ) {
1431                 WLAN_LOG_ERROR("Failed to set supprates=%d.\n", word);
1432                 goto failed;
1433         }
1434         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL0, word);
1435         if ( result ) {
1436                 WLAN_LOG_ERROR("Failed to set txrates=%d.\n", word);
1437                 goto failed;
1438         }
1439
1440         /* ibssatimwindow */
1441         if (msg->ibssatimwindow.status == P80211ENUM_msgitem_status_data_ok) {
1442                 WLAN_LOG_INFO("prism2mgmt_start: atimwindow not used in "
1443                                "Infrastructure mode, ignored.\n");
1444         }
1445
1446         /* DTIM period */
1447         word = msg->dtimperiod.data;
1448         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNDTIMPER, word);
1449         if ( result ) {
1450                 WLAN_LOG_ERROR("Failed to set dtim period=%d.\n", word);
1451                 goto failed;
1452         }
1453
1454         /* probedelay */
1455         if (msg->probedelay.status == P80211ENUM_msgitem_status_data_ok) {
1456                 WLAN_LOG_INFO("prism2mgmt_start: probedelay not "
1457                                "supported in prism2, ignored.\n");
1458         }
1459
1460         /* cfpollable, cfpollreq, cfpperiod, cfpmaxduration */
1461         if (msg->cfpollable.data == P80211ENUM_truth_true &&
1462             msg->cfpollreq.data == P80211ENUM_truth_true ) {
1463                 WLAN_LOG_ERROR("cfpollable=cfpollreq=true is illegal.\n");
1464                 result = -1;
1465                 goto failed;
1466         }
1467
1468         /* read the PCFInfo and update */
1469         result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFAPPCFINFO,
1470                                         pcfinfo, HFA384x_RID_CNFAPPCFINFO_LEN);
1471         if ( result ) {
1472                 WLAN_LOG_INFO("prism2mgmt_start: read(pcfinfo) failed, "
1473                                 "assume it's "
1474                                 "not supported, pcf settings ignored.\n");
1475                 goto pcf_skip;
1476         }
1477         if ((msg->cfpollable.data == P80211ENUM_truth_false &&
1478              msg->cfpollreq.data == P80211ENUM_truth_false) ) {
1479                 pcfinfo->MediumOccupancyLimit = 0;
1480                 pcfinfo->CFPPeriod = 0;
1481                 pcfinfo->CFPMaxDuration = 0;
1482                 pcfinfo->CFPFlags &= host2hfa384x_16((UINT16)~BIT0);
1483
1484                 if ( msg->cfpperiod.status == P80211ENUM_msgitem_status_data_ok ||
1485                      msg->cfpmaxduration.status == P80211ENUM_msgitem_status_data_ok ) {
1486                         WLAN_LOG_WARNING(
1487                                 "Setting cfpperiod or cfpmaxduration when "
1488                                 "cfpollable and cfreq are false is pointless.\n");
1489                 }
1490         }
1491         if ((msg->cfpollable.data == P80211ENUM_truth_true ||
1492              msg->cfpollreq.data == P80211ENUM_truth_true) ) {
1493                 if ( msg->cfpollable.data == P80211ENUM_truth_true) {
1494                         pcfinfo->CFPFlags |= host2hfa384x_16((UINT16)BIT0);
1495                 }
1496
1497                 if ( msg->cfpperiod.status == P80211ENUM_msgitem_status_data_ok) {
1498                         pcfinfo->CFPPeriod = msg->cfpperiod.data;
1499                         pcfinfo->CFPPeriod = host2hfa384x_16(pcfinfo->CFPPeriod);
1500                 }
1501
1502                 if ( msg->cfpmaxduration.status == P80211ENUM_msgitem_status_data_ok) {
1503                         pcfinfo->CFPMaxDuration = msg->cfpmaxduration.data;
1504                         pcfinfo->CFPMaxDuration = host2hfa384x_16(pcfinfo->CFPMaxDuration);
1505                         pcfinfo->MediumOccupancyLimit = pcfinfo->CFPMaxDuration;
1506                 }
1507         }
1508         result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFAPPCFINFO,
1509                                         pcfinfo, HFA384x_RID_CNFAPPCFINFO_LEN);
1510         if ( result ) {
1511                 WLAN_LOG_ERROR("write(pcfinfo) failed.\n");
1512                 goto failed;
1513         }
1514
1515 pcf_skip:
1516         /* Set the macmode so the frame setup code knows what to do */
1517         if ( msg->bsstype.data == P80211ENUM_bsstype_infrastructure ) {
1518                 wlandev->macmode = WLAN_MACMODE_ESS_AP;
1519                 /* lets extend the data length a bit */
1520                 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
1521         }
1522
1523         /* Set the BSSID to the same as our MAC */
1524         memcpy( wlandev->bssid, wlandev->netdev->dev_addr, WLAN_BSSID_LEN);
1525
1526         /* Enable the Port */
1527         result = hfa384x_drvr_enable(hw, 0);
1528         if ( result ) {
1529                 WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result);
1530                 goto failed;
1531         }
1532
1533         msg->resultcode.data = P80211ENUM_resultcode_success;
1534
1535         goto done;
1536 failed:
1537         WLAN_LOG_DEBUG(1, "Failed to set a config option, result=%d\n", result);
1538         msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1539
1540 done:
1541         result = 0;
1542
1543         DBFEXIT;
1544         return result;
1545 }
1546
1547
1548 /*----------------------------------------------------------------
1549 * prism2mgmt_enable
1550 *
1551 * Start a BSS.  Any station can do this for IBSS, only AP for ESS.
1552 *
1553 * Arguments:
1554 *       wlandev         wlan device structure
1555 *       msgp            ptr to msg buffer
1556 *
1557 * Returns:
1558 *       0       success and done
1559 *       <0      success, but we're waiting for something to finish.
1560 *       >0      an error occurred while handling the message.
1561 * Side effects:
1562 *
1563 * Call context:
1564 *       process thread  (usually)
1565 *       interrupt
1566 ----------------------------------------------------------------*/
1567 int prism2mgmt_enable(wlandevice_t *wlandev, void *msgp)
1568 {
1569         int                     result = 0;
1570         hfa384x_t               *hw = wlandev->priv;
1571         p80211msg_p2req_enable_t        *msg = msgp;
1572         DBFENTER;
1573
1574         if (!hw->ap) {
1575
1576                 /*** STATION ***/
1577
1578                 /* Ad-Hoc not quite supported on Prism2 */
1579                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1580                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
1581                 goto done;
1582         }
1583
1584         /*** ACCESS POINT ***/
1585
1586         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1587
1588         /* Is the tertiary loaded? */
1589         if ( hw->cap_sup_sta.id != 5) {
1590                 WLAN_LOG_ERROR("AP driver failed to detect AP firmware.\n");
1591                 goto failed;
1592         }
1593
1594         /* Set the macmode so the frame setup code knows what to do */
1595         wlandev->macmode = WLAN_MACMODE_ESS_AP;
1596
1597         /* Set the BSSID to the same as our MAC */
1598         memcpy( wlandev->bssid, wlandev->netdev->dev_addr, WLAN_BSSID_LEN);
1599
1600         /* Enable the Port */
1601         result = hfa384x_drvr_enable(hw, 0);
1602         if ( result ) {
1603                 WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result);
1604                 goto failed;
1605         }
1606
1607         msg->resultcode.data = P80211ENUM_resultcode_success;
1608
1609         goto done;
1610 failed:
1611         msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1612
1613 done:
1614         result = 0;
1615
1616         DBFEXIT;
1617         return result;
1618 }
1619
1620
1621 /*----------------------------------------------------------------
1622 * prism2mgmt_readpda
1623 *
1624 * Collect the PDA data and put it in the message.
1625 *
1626 * Arguments:
1627 *       wlandev         wlan device structure
1628 *       msgp            ptr to msg buffer
1629 *
1630 * Returns:
1631 *       0       success and done
1632 *       <0      success, but we're waiting for something to finish.
1633 *       >0      an error occurred while handling the message.
1634 * Side effects:
1635 *
1636 * Call context:
1637 *       process thread  (usually)
1638 ----------------------------------------------------------------*/
1639 int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp)
1640 {
1641         hfa384x_t               *hw = wlandev->priv;
1642         p80211msg_p2req_readpda_t       *msg = msgp;
1643         int                             result;
1644         DBFENTER;
1645
1646         /* We only support collecting the PDA when in the FWLOAD
1647          * state.
1648          */
1649         if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
1650                 WLAN_LOG_ERROR(
1651                         "PDA may only be read "
1652                         "in the fwload state.\n");
1653                 msg->resultcode.data =
1654                         P80211ENUM_resultcode_implementation_failure;
1655                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1656         } else {
1657                 /*  Call drvr_readpda(), it handles the auxport enable
1658                  *  and validating the returned PDA.
1659                  */
1660                 result = hfa384x_drvr_readpda(
1661                         hw,
1662                         msg->pda.data,
1663                         HFA384x_PDA_LEN_MAX);
1664                 if (result) {
1665                         WLAN_LOG_ERROR(
1666                                 "hfa384x_drvr_readpda() failed, "
1667                                 "result=%d\n",
1668                                 result);
1669
1670                         msg->resultcode.data =
1671                                 P80211ENUM_resultcode_implementation_failure;
1672                         msg->resultcode.status =
1673                                 P80211ENUM_msgitem_status_data_ok;
1674                         DBFEXIT;
1675                         return 0;
1676                 }
1677                 msg->pda.status = P80211ENUM_msgitem_status_data_ok;
1678                 msg->resultcode.data = P80211ENUM_resultcode_success;
1679                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1680         }
1681
1682         DBFEXIT;
1683         return 0;
1684 }
1685
1686 /*----------------------------------------------------------------
1687 * prism2mgmt_readcis
1688 *
1689 * Collect the CIS data and put it in the message.
1690 *
1691 * Arguments:
1692 *       wlandev         wlan device structure
1693 *       msgp            ptr to msg buffer
1694 *
1695 * Returns:
1696 *       0       success and done
1697 *       <0      success, but we're waiting for something to finish.
1698 *       >0      an error occurred while handling the message.
1699 * Side effects:
1700 *
1701 * Call context:
1702 *       process thread  (usually)
1703 ----------------------------------------------------------------*/
1704 int prism2mgmt_readcis(wlandevice_t *wlandev, void *msgp)
1705 {
1706         int                     result;
1707         hfa384x_t               *hw = wlandev->priv;
1708         p80211msg_p2req_readcis_t       *msg = msgp;
1709
1710         DBFENTER;
1711
1712         memset(msg->cis.data, 0, sizeof(msg->cis.data));
1713
1714         result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CIS,
1715                                         msg->cis.data, HFA384x_RID_CIS_LEN);
1716         if ( result ) {
1717                 WLAN_LOG_INFO("prism2mgmt_readcis: read(cis) failed.\n");
1718                 msg->cis.status = P80211ENUM_msgitem_status_no_value;
1719                 msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
1720
1721                 }
1722         else {
1723                 msg->cis.status = P80211ENUM_msgitem_status_data_ok;
1724                 msg->resultcode.data = P80211ENUM_resultcode_success;
1725                 }
1726
1727         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1728
1729         DBFEXIT;
1730         return 0;
1731 }
1732
1733 /*----------------------------------------------------------------
1734 * prism2mgmt_auxport_state
1735 *
1736 * Enables/Disables the card's auxiliary port.  Should be called
1737 * before and after a sequence of auxport_read()/auxport_write()
1738 * calls.
1739 *
1740 * Arguments:
1741 *       wlandev         wlan device structure
1742 *       msgp            ptr to msg buffer
1743 *
1744 * Returns:
1745 *       0       success and done
1746 *       <0      success, but we're waiting for something to finish.
1747 *       >0      an error occurred while handling the message.
1748 * Side effects:
1749 *
1750 * Call context:
1751 *       process thread  (usually)
1752 ----------------------------------------------------------------*/
1753 int prism2mgmt_auxport_state(wlandevice_t *wlandev, void *msgp)
1754 {
1755         p80211msg_p2req_auxport_state_t *msg = msgp;
1756
1757         DBFENTER;
1758
1759         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1760         msg->resultcode.data = P80211ENUM_resultcode_not_supported;
1761
1762         DBFEXIT;
1763         return 0;
1764 }
1765
1766
1767 /*----------------------------------------------------------------
1768 * prism2mgmt_auxport_read
1769 *
1770 * Copies data from the card using the auxport.  The auxport must
1771 * have previously been enabled.  Note: this is not the way to
1772 * do downloads, see the [ram|flash]dl functions.
1773 *
1774 * Arguments:
1775 *       wlandev         wlan device structure
1776 *       msgp            ptr to msg buffer
1777 *
1778 * Returns:
1779 *       0       success and done
1780 *       <0      success, but we're waiting for something to finish.
1781 *       >0      an error occurred while handling the message.
1782 * Side effects:
1783 *
1784 * Call context:
1785 *       process thread  (usually)
1786 ----------------------------------------------------------------*/
1787 int prism2mgmt_auxport_read(wlandevice_t *wlandev, void *msgp)
1788 {
1789         DBFENTER;
1790
1791         WLAN_LOG_ERROR("prism2mgmt_auxport_read: Not supported on USB.\n");
1792
1793         DBFEXIT;
1794         return 0;
1795 }
1796
1797
1798 /*----------------------------------------------------------------
1799 * prism2mgmt_auxport_write
1800 *
1801 * Copies data to the card using the auxport.  The auxport must
1802 * have previously been enabled.  Note: this is not the way to
1803 * do downloads, see the [ram|flash]dl functions.
1804 *
1805 * Arguments:
1806 *       wlandev         wlan device structure
1807 *       msgp            ptr to msg buffer
1808 *
1809 * Returns:
1810 *       0       success and done
1811 *       <0      success, but we're waiting for something to finish.
1812 *       >0      an error occurred while handling the message.
1813 * Side effects:
1814 *
1815 * Call context:
1816 *       process thread  (usually)
1817 ----------------------------------------------------------------*/
1818 int prism2mgmt_auxport_write(wlandevice_t *wlandev, void *msgp)
1819 {
1820         DBFENTER;
1821         WLAN_LOG_ERROR("prism2mgmt_auxport_read: Not supported on USB.\n");
1822         DBFEXIT;
1823         return 0;
1824 }
1825
1826 /*----------------------------------------------------------------
1827 * prism2mgmt_low_level
1828 *
1829 * Puts the card into the desired test mode.
1830 *
1831 * Arguments:
1832 *       wlandev         wlan device structure
1833 *       msgp            ptr to msg buffer
1834 *
1835 * Returns:
1836 *       0       success and done
1837 *       <0      success, but we're waiting for something to finish.
1838 *       >0      an error occurred while handling the message.
1839 * Side effects:
1840 *
1841 * Call context:
1842 *       process thread  (usually)
1843 ----------------------------------------------------------------*/
1844 int prism2mgmt_low_level(wlandevice_t *wlandev, void *msgp)
1845 {
1846         hfa384x_t               *hw = wlandev->priv;
1847         p80211msg_p2req_low_level_t     *msg = msgp;
1848         hfa384x_metacmd_t cmd;
1849         DBFENTER;
1850
1851         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1852
1853         /* call some routine to execute the test command */
1854         cmd.cmd = (UINT16) msg->command.data;
1855         cmd.parm0 = (UINT16) msg->param0.data;
1856         cmd.parm1 = (UINT16) msg->param1.data;
1857         cmd.parm2 = (UINT16) msg->param2.data;
1858
1859         hfa384x_drvr_low_level(hw,&cmd);
1860
1861         msg->resp0.data = (UINT32) cmd.result.resp0;
1862         msg->resp1.data = (UINT32) cmd.result.resp1;
1863         msg->resp2.data = (UINT32) cmd.result.resp2;
1864
1865         msg->resultcode.data = P80211ENUM_resultcode_success;
1866
1867         DBFEXIT;
1868         return 0;
1869 }
1870
1871 /*----------------------------------------------------------------
1872 * prism2mgmt_test_command
1873 *
1874 * Puts the card into the desired test mode.
1875 *
1876 * Arguments:
1877 *       wlandev         wlan device structure
1878 *       msgp            ptr to msg buffer
1879 *
1880 * Returns:
1881 *       0       success and done
1882 *       <0      success, but we're waiting for something to finish.
1883 *       >0      an error occurred while handling the message.
1884 * Side effects:
1885 *
1886 * Call context:
1887 *       process thread  (usually)
1888 ----------------------------------------------------------------*/
1889 int prism2mgmt_test_command(wlandevice_t *wlandev, void *msgp)
1890 {
1891         hfa384x_t               *hw = wlandev->priv;
1892         p80211msg_p2req_test_command_t  *msg = msgp;
1893         hfa384x_metacmd_t cmd;
1894
1895         DBFENTER;
1896
1897         cmd.cmd = ((UINT16) msg->testcode.data) << 8 | 0x38;
1898         cmd.parm0 = (UINT16) msg->testparam.data;
1899         cmd.parm1 = 0;
1900         cmd.parm2 = 0;
1901
1902         /* call some routine to execute the test command */
1903
1904         hfa384x_drvr_low_level(hw,&cmd);
1905
1906         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1907         msg->resultcode.data = P80211ENUM_resultcode_success;
1908
1909         msg->status.status = P80211ENUM_msgitem_status_data_ok;
1910         msg->status.data = cmd.result.status;
1911         msg->resp0.status = P80211ENUM_msgitem_status_data_ok;
1912         msg->resp0.data = cmd.result.resp0;
1913         msg->resp1.status = P80211ENUM_msgitem_status_data_ok;
1914         msg->resp1.data = cmd.result.resp1;
1915         msg->resp2.status = P80211ENUM_msgitem_status_data_ok;
1916         msg->resp2.data = cmd.result.resp2;
1917
1918         DBFEXIT;
1919         return 0;
1920 }
1921
1922
1923 /*----------------------------------------------------------------
1924 * prism2mgmt_mmi_read
1925 *
1926 * Read from one of the MMI registers.
1927 *
1928 * Arguments:
1929 *       wlandev         wlan device structure
1930 *       msgp            ptr to msg buffer
1931 *
1932 * Returns:
1933 *       0       success and done
1934 *       <0      success, but we're waiting for something to finish.
1935 *       >0      an error occurred while handling the message.
1936 * Side effects:
1937 *
1938 * Call context:
1939 *       process thread  (usually)
1940 ----------------------------------------------------------------*/
1941 int prism2mgmt_mmi_read(wlandevice_t *wlandev, void *msgp)
1942 {
1943         hfa384x_t               *hw = wlandev->priv;
1944         p80211msg_p2req_mmi_read_t      *msg = msgp;
1945         UINT32 resp = 0;
1946
1947         DBFENTER;
1948
1949         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1950
1951         /* call some routine to execute the test command */
1952
1953         hfa384x_drvr_mmi_read(hw, msg->addr.data, &resp);
1954
1955         /* I'm not sure if this is "architecturally" correct, but it
1956            is expedient. */
1957
1958         msg->value.status = P80211ENUM_msgitem_status_data_ok;
1959         msg->value.data = resp;
1960         msg->resultcode.data = P80211ENUM_resultcode_success;
1961
1962         DBFEXIT;
1963         return 0;
1964 }
1965
1966 /*----------------------------------------------------------------
1967 * prism2mgmt_mmi_write
1968 *
1969 * Write a data value to one of the MMI registers.
1970 *
1971 * Arguments:
1972 *       wlandev         wlan device structure
1973 *       msgp            ptr to msg buffer
1974 *
1975 * Returns:
1976 *       0       success and done
1977 *       <0      success, but we're waiting for something to finish.
1978 *       >0      an error occurred while handling the message.
1979 * Side effects:
1980 *
1981 * Call context:
1982 *       process thread  (usually)
1983 ----------------------------------------------------------------*/
1984 int prism2mgmt_mmi_write(wlandevice_t *wlandev, void *msgp)
1985 {
1986         hfa384x_t               *hw = wlandev->priv;
1987         p80211msg_p2req_mmi_write_t     *msg = msgp;
1988         DBFENTER;
1989
1990         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1991
1992         /* call some routine to execute the test command */
1993
1994         hfa384x_drvr_mmi_write(hw, msg->addr.data, msg->data.data);
1995
1996         msg->resultcode.data = P80211ENUM_resultcode_success;
1997
1998         DBFEXIT;
1999         return 0;
2000 }
2001
2002 /*----------------------------------------------------------------
2003 * prism2mgmt_ramdl_state
2004 *
2005 * Establishes the beginning/end of a card RAM download session.
2006 *
2007 * It is expected that the ramdl_write() function will be called
2008 * one or more times between the 'enable' and 'disable' calls to
2009 * this function.
2010 *
2011 * Note: This function should not be called when a mac comm port
2012 *       is active.
2013 *
2014 * Arguments:
2015 *       wlandev         wlan device structure
2016 *       msgp            ptr to msg buffer
2017 *
2018 * Returns:
2019 *       0       success and done
2020 *       <0      success, but we're waiting for something to finish.
2021 *       >0      an error occurred while handling the message.
2022 * Side effects:
2023 *
2024 * Call context:
2025 *       process thread  (usually)
2026 ----------------------------------------------------------------*/
2027 int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp)
2028 {
2029         hfa384x_t               *hw = wlandev->priv;
2030         p80211msg_p2req_ramdl_state_t   *msg = msgp;
2031         DBFENTER;
2032
2033         if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
2034                 WLAN_LOG_ERROR(
2035                         "ramdl_state(): may only be called "
2036                         "in the fwload state.\n");
2037                 msg->resultcode.data =
2038                         P80211ENUM_resultcode_implementation_failure;
2039                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
2040                 DBFEXIT;
2041                 return 0;
2042         }
2043
2044         /*
2045         ** Note: Interrupts are locked out if this is an AP and are NOT
2046         ** locked out if this is a station.
2047         */
2048
2049         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
2050         if  ( msg->enable.data == P80211ENUM_truth_true ) {
2051                 if ( hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data) ) {
2052                         msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
2053                 } else {
2054                         msg->resultcode.data = P80211ENUM_resultcode_success;
2055                 }
2056         } else {
2057                 hfa384x_drvr_ramdl_disable(hw);
2058                 msg->resultcode.data = P80211ENUM_resultcode_success;
2059         }
2060
2061         DBFEXIT;
2062         return 0;
2063 }
2064
2065
2066 /*----------------------------------------------------------------
2067 * prism2mgmt_ramdl_write
2068 *
2069 * Writes a buffer to the card RAM using the download state.  This
2070 * is for writing code to card RAM.  To just read or write raw data
2071 * use the aux functions.
2072 *
2073 * Arguments:
2074 *       wlandev         wlan device structure
2075 *       msgp            ptr to msg buffer
2076 *
2077 * Returns:
2078 *       0       success and done
2079 *       <0      success, but we're waiting for something to finish.
2080 *       >0      an error occurred while handling the message.
2081 * Side effects:
2082 *
2083 * Call context:
2084 *       process thread  (usually)
2085 ----------------------------------------------------------------*/
2086 int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp)
2087 {
2088         hfa384x_t               *hw = wlandev->priv;
2089         p80211msg_p2req_ramdl_write_t   *msg = msgp;
2090         UINT32                  addr;
2091         UINT32                  len;
2092         UINT8                   *buf;
2093         DBFENTER;
2094
2095         if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
2096                 WLAN_LOG_ERROR(
2097                         "ramdl_write(): may only be called "
2098                         "in the fwload state.\n");
2099                 msg->resultcode.data =
2100                         P80211ENUM_resultcode_implementation_failure;
2101                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
2102                 DBFEXIT;
2103                 return 0;
2104         }
2105
2106         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
2107         /* first validate the length */
2108         if  ( msg->len.data > sizeof(msg->data.data) ) {
2109                 msg->resultcode.status = P80211ENUM_resultcode_invalid_parameters;
2110                 return 0;
2111         }
2112         /* call the hfa384x function to do the write */
2113         addr = msg->addr.data;
2114         len = msg->len.data;
2115         buf = msg->data.data;
2116         if ( hfa384x_drvr_ramdl_write(hw, addr, buf, len) ) {
2117                 msg->resultcode.data = P80211ENUM_resultcode_refused;
2118
2119         }
2120         msg->resultcode.data = P80211ENUM_resultcode_success;
2121
2122         DBFEXIT;
2123         return 0;
2124 }
2125
2126
2127 /*----------------------------------------------------------------
2128 * prism2mgmt_flashdl_state
2129 *
2130 * Establishes the beginning/end of a card Flash download session.
2131 *
2132 * It is expected that the flashdl_write() function will be called
2133 * one or more times between the 'enable' and 'disable' calls to
2134 * this function.
2135 *
2136 * Note: This function should not be called when a mac comm port
2137 *       is active.
2138 *
2139 * Arguments:
2140 *       wlandev         wlan device structure
2141 *       msgp            ptr to msg buffer
2142 *
2143 * Returns:
2144 *       0       success and done
2145 *       <0      success, but we're waiting for something to finish.
2146 *       >0      an error occurred while handling the message.
2147 * Side effects:
2148 *
2149 * Call context:
2150 *       process thread  (usually)
2151 ----------------------------------------------------------------*/
2152 int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
2153 {
2154         int                     result = 0;
2155         hfa384x_t               *hw = wlandev->priv;
2156         p80211msg_p2req_flashdl_state_t *msg = msgp;
2157         DBFENTER;
2158
2159         if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
2160                 WLAN_LOG_ERROR(
2161                         "flashdl_state(): may only be called "
2162                         "in the fwload state.\n");
2163                 msg->resultcode.data =
2164                         P80211ENUM_resultcode_implementation_failure;
2165                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
2166                 DBFEXIT;
2167                 return 0;
2168         }
2169
2170         /*
2171         ** Note: Interrupts are locked out if this is an AP and are NOT
2172         ** locked out if this is a station.
2173         */
2174
2175         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
2176         if  ( msg->enable.data == P80211ENUM_truth_true ) {
2177                 if ( hfa384x_drvr_flashdl_enable(hw) ) {
2178                         msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
2179                 } else {
2180                         msg->resultcode.data = P80211ENUM_resultcode_success;
2181                 }
2182         } else {
2183                 hfa384x_drvr_flashdl_disable(hw);
2184                 msg->resultcode.data = P80211ENUM_resultcode_success;
2185                 /* NOTE: At this point, the MAC is in the post-reset
2186                  * state and the driver is in the fwload state.
2187                  * We need to get the MAC back into the fwload
2188                  * state.  To do this, we set the nsdstate to HWPRESENT
2189                  * and then call the ifstate function to redo everything
2190                  * that got us into the fwload state.
2191                  */
2192                 wlandev->msdstate = WLAN_MSD_HWPRESENT;
2193                 result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
2194                 if (result != P80211ENUM_resultcode_success) {
2195                         WLAN_LOG_ERROR("prism2sta_ifstate(fwload) failed,"
2196                                 "P80211ENUM_resultcode=%d\n", result);
2197                         msg->resultcode.data =
2198                                 P80211ENUM_resultcode_implementation_failure;
2199                         result = -1;
2200                 }
2201         }
2202
2203         DBFEXIT;
2204         return 0;
2205 }
2206
2207
2208 /*----------------------------------------------------------------
2209 * prism2mgmt_flashdl_write
2210 *
2211 *
2212 *
2213 * Arguments:
2214 *       wlandev         wlan device structure
2215 *       msgp            ptr to msg buffer
2216 *
2217 * Returns:
2218 *       0       success and done
2219 *       <0      success, but we're waiting for something to finish.
2220 *       >0      an error occurred while handling the message.
2221 * Side effects:
2222 *
2223 * Call context:
2224 *       process thread  (usually)
2225 ----------------------------------------------------------------*/
2226 int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp)
2227 {
2228         hfa384x_t               *hw = wlandev->priv;
2229         p80211msg_p2req_flashdl_write_t *msg = msgp;
2230         UINT32                  addr;
2231         UINT32                  len;
2232         UINT8                   *buf;
2233         DBFENTER;
2234
2235         if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
2236                 WLAN_LOG_ERROR(
2237                         "flashdl_write(): may only be called "
2238                         "in the fwload state.\n");
2239                 msg->resultcode.data =
2240                         P80211ENUM_resultcode_implementation_failure;
2241                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
2242                 DBFEXIT;
2243                 return 0;
2244         }
2245
2246         /*
2247         ** Note: Interrupts are locked out if this is an AP and are NOT
2248         ** locked out if this is a station.
2249         */
2250
2251         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
2252         /* first validate the length */
2253         if  ( msg->len.data > sizeof(msg->data.data) ) {
2254                 msg->resultcode.status =
2255                         P80211ENUM_resultcode_invalid_parameters;
2256                 return 0;
2257         }
2258         /* call the hfa384x function to do the write */
2259         addr = msg->addr.data;
2260         len = msg->len.data;
2261         buf = msg->data.data;
2262         if ( hfa384x_drvr_flashdl_write(hw, addr, buf, len) ) {
2263                 msg->resultcode.data = P80211ENUM_resultcode_refused;
2264
2265         }
2266         msg->resultcode.data = P80211ENUM_resultcode_success;
2267
2268         DBFEXIT;
2269         return 0;
2270 }
2271
2272
2273 /*----------------------------------------------------------------
2274 * prism2mgmt_dump_state
2275 *
2276 * Dumps the driver's and hardware's current state via the kernel
2277 * log at KERN_NOTICE level.
2278 *
2279 * Arguments:
2280 *       wlandev         wlan device structure
2281 *       msgp            ptr to msg buffer
2282 *
2283 * Returns:
2284 *       0       success and done
2285 *       <0      success, but we're waiting for something to finish.
2286 *       >0      an error occurred while handling the message.
2287 * Side effects:
2288 *
2289 * Call context:
2290 *       process thread  (usually)
2291 ----------------------------------------------------------------*/
2292 int prism2mgmt_dump_state(wlandevice_t *wlandev, void *msgp)
2293 {
2294         p80211msg_p2req_dump_state_t    *msg = msgp;
2295         int                             result = 0;
2296
2297         DBFENTER;
2298
2299         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
2300         msg->resultcode.data = P80211ENUM_resultcode_not_supported;
2301         goto failed;
2302
2303 failed:
2304         DBFEXIT;
2305         return result;
2306 }
2307
2308 /*----------------------------------------------------------------
2309 * prism2mgmt_autojoin
2310 *
2311 * Associate with an ESS.
2312 *
2313 * Arguments:
2314 *       wlandev         wlan device structure
2315 *       msgp            ptr to msg buffer
2316 *
2317 * Returns:
2318 *       0       success and done
2319 *       <0      success, but we're waiting for something to finish.
2320 *       >0      an error occurred while handling the message.
2321 * Side effects:
2322 *
2323 * Call context:
2324 *       process thread  (usually)
2325 *       interrupt
2326 ----------------------------------------------------------------*/
2327 int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
2328 {
2329         hfa384x_t                       *hw = wlandev->priv;
2330         int                     result = 0;
2331         UINT16                  reg;
2332         UINT16                  port_type;
2333         p80211msg_lnxreq_autojoin_t     *msg = msgp;
2334         p80211pstrd_t           *pstr;
2335         UINT8                   bytebuf[256];
2336         hfa384x_bytestr_t       *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
2337         DBFENTER;
2338
2339         wlandev->macmode = WLAN_MACMODE_NONE;
2340
2341         /* Set the SSID */
2342         memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
2343
2344         if (hw->ap) {
2345
2346                 /*** ACCESS POINT ***/
2347
2348                 /* Never supported on AP */
2349                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
2350                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
2351                 goto done;
2352         }
2353
2354         /* Disable the Port */
2355         hfa384x_drvr_disable(hw, 0);
2356
2357         /*** STATION ***/
2358         /* Set the TxRates */
2359         hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
2360
2361         /* Set the auth type */
2362         if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) {
2363                 reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
2364         } else {
2365                 reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
2366         }
2367         hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
2368
2369         /* Set the ssid */
2370         memset(bytebuf, 0, 256);
2371         pstr = (p80211pstrd_t*)&(msg->ssid.data);
2372         prism2mgmt_pstr2bytestr(p2bytestr, pstr);
2373         result = hfa384x_drvr_setconfig(
2374                         hw, HFA384x_RID_CNFDESIREDSSID,
2375                         bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
2376 #if 0
2377         /* we can use the new-fangled auto-unknown mode if the firmware
2378            is 1.3.3 or newer */
2379         if (HFA384x_FIRMARE_VERSION(hw->ident_sta_fw.major,
2380                                     hw->ident_sta_fw.minor,
2381                                     hw->ident_sta_fw.variant) >=
2382             HFA384x_FIRMWARE_VERSION(1,3,3)) {
2383                 /* Set up the IBSS options */
2384                 reg =  HFA384x_CREATEIBSS_JOINESS_JOINCREATEIBSS;
2385                 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CREATEIBSS, reg);
2386
2387                 /* Set the PortType */
2388                 port_type = HFA384x_PORTTYPE_IBSS;
2389         } else {
2390                 port_type = HFA384x_PORTTYPE_BSS;
2391         }
2392 #else
2393         port_type = HFA384x_PORTTYPE_BSS;
2394 #endif
2395         /* Set the PortType */
2396         hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
2397
2398         /* Enable the Port */
2399         hfa384x_drvr_enable(hw, 0);
2400
2401         /* Set the resultcode */
2402         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
2403         msg->resultcode.data = P80211ENUM_resultcode_success;
2404
2405 done:
2406         DBFEXIT;
2407         return result;
2408 }
2409
2410
2411 /*----------------------------------------------------------------
2412 * prism2mgmt_wlansniff
2413 *
2414 * Start or stop sniffing.
2415 *
2416 * Arguments:
2417 *       wlandev         wlan device structure
2418 *       msgp            ptr to msg buffer
2419 *
2420 * Returns:
2421 *       0       success and done
2422 *       <0      success, but we're waiting for something to finish.
2423 *       >0      an error occurred while handling the message.
2424 * Side effects:
2425 *
2426 * Call context:
2427 *       process thread  (usually)
2428 *       interrupt
2429 ----------------------------------------------------------------*/
2430 int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
2431 {
2432         int                     result = 0;
2433         p80211msg_lnxreq_wlansniff_t    *msg = msgp;
2434
2435         hfa384x_t                       *hw = wlandev->priv;
2436         UINT16                  word;
2437
2438         DBFENTER;
2439
2440         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
2441         switch (msg->enable.data)
2442         {
2443         case P80211ENUM_truth_false:
2444                 /* Confirm that we're in monitor mode */
2445                 if ( wlandev->netdev->type == ARPHRD_ETHER ) {
2446                         msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
2447                         result = 0;
2448                         goto exit;
2449                 }
2450                 /* Disable monitor mode */
2451                 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
2452                 if ( result ) {
2453                         WLAN_LOG_DEBUG(1,
2454                                 "failed to disable monitor mode, result=%d\n",
2455                                 result);
2456                         goto failed;
2457                 }
2458                 /* Disable port 0 */
2459                 result = hfa384x_drvr_disable(hw, 0);
2460                 if ( result ) {
2461                         WLAN_LOG_DEBUG(1,
2462                         "failed to disable port 0 after sniffing, result=%d\n",
2463                         result);
2464                         goto failed;
2465                 }
2466                 /* Clear the driver state */
2467                 wlandev->netdev->type = ARPHRD_ETHER;
2468
2469                 /* Restore the wepflags */
2470                 result = hfa384x_drvr_setconfig16(hw,
2471                                 HFA384x_RID_CNFWEPFLAGS,
2472                                 hw->presniff_wepflags);
2473                 if ( result ) {
2474                         WLAN_LOG_DEBUG(1,
2475                         "failed to restore wepflags=0x%04x, result=%d\n",
2476                         hw->presniff_wepflags,
2477                         result);
2478                         goto failed;
2479                 }
2480
2481                 /* Set the port to its prior type and enable (if necessary) */
2482                 if (hw->presniff_port_type != 0 ) {
2483                         word = hw->presniff_port_type;
2484                         result = hfa384x_drvr_setconfig16(hw,
2485                                 HFA384x_RID_CNFPORTTYPE, word);
2486                         if ( result ) {
2487                                 WLAN_LOG_DEBUG(1,
2488                                 "failed to restore porttype, result=%d\n",
2489                                 result);
2490                                 goto failed;
2491                         }
2492
2493                         /* Enable the port */
2494                         result = hfa384x_drvr_enable(hw, 0);
2495                         if ( result ) {
2496                                 WLAN_LOG_DEBUG(1, "failed to enable port to presniff setting, result=%d\n", result);
2497                                 goto failed;
2498                         }
2499                 } else {
2500                         result = hfa384x_drvr_disable(hw, 0);
2501
2502                 }
2503
2504                 WLAN_LOG_INFO("monitor mode disabled\n");
2505                 msg->resultcode.data = P80211ENUM_resultcode_success;
2506                 result = 0;
2507                 goto exit;
2508                 break;
2509         case P80211ENUM_truth_true:
2510                 /* Disable the port (if enabled), only check Port 0 */
2511                 if ( hw->port_enabled[0]) {
2512                         if (wlandev->netdev->type == ARPHRD_ETHER) {
2513                                 /* Save macport 0 state */
2514                                 result = hfa384x_drvr_getconfig16(hw,
2515                                                                   HFA384x_RID_CNFPORTTYPE,
2516                                                                   &(hw->presniff_port_type));
2517                                 if ( result ) {
2518                                         WLAN_LOG_DEBUG(1,"failed to read porttype, result=%d\n", result);
2519                                         goto failed;
2520                                 }
2521                                 /* Save the wepflags state */
2522                                 result = hfa384x_drvr_getconfig16(hw,
2523                                                                   HFA384x_RID_CNFWEPFLAGS,
2524                                                                   &(hw->presniff_wepflags));
2525                                 if ( result ) {
2526                                         WLAN_LOG_DEBUG(1,"failed to read wepflags, result=%d\n", result);
2527                                         goto failed;
2528                                 }
2529                                 hfa384x_drvr_stop(hw);
2530                                 result = hfa384x_drvr_start(hw);
2531                                 if ( result ) {
2532                                         WLAN_LOG_DEBUG(1,
2533                                                        "failed to restart the card for sniffing, result=%d\n",
2534                                                        result);
2535                                         goto failed;
2536                                 }
2537                         } else {
2538                                 /* Disable the port */
2539                                 result = hfa384x_drvr_disable(hw, 0);
2540                                 if ( result ) {
2541                                         WLAN_LOG_DEBUG(1,
2542                                                        "failed to enable port for sniffing, result=%d\n",
2543                                                        result);
2544                                         goto failed;
2545                                 }
2546                         }
2547                 } else {
2548                         hw->presniff_port_type = 0;
2549                 }
2550
2551                 /* Set the channel we wish to sniff  */
2552                 word = msg->channel.data;
2553                 result = hfa384x_drvr_setconfig16(hw,
2554                                                   HFA384x_RID_CNFOWNCHANNEL, word);
2555                 hw->sniff_channel=word;
2556
2557                 if ( result ) {
2558                         WLAN_LOG_DEBUG(1,
2559                                        "failed to set channel %d, result=%d\n",
2560                                                word,
2561                                        result);
2562                         goto failed;
2563                 }
2564
2565                 /* Now if we're already sniffing, we can skip the rest */
2566                 if (wlandev->netdev->type != ARPHRD_ETHER) {
2567                         /* Set the port type to pIbss */
2568                         word = HFA384x_PORTTYPE_PSUEDOIBSS;
2569                         result = hfa384x_drvr_setconfig16(hw,
2570                                                           HFA384x_RID_CNFPORTTYPE, word);
2571                         if ( result ) {
2572                                 WLAN_LOG_DEBUG(1,
2573                                                "failed to set porttype %d, result=%d\n",
2574                                                word,
2575                                                result);
2576                                 goto failed;
2577                         }
2578                         if ((msg->keepwepflags.status == P80211ENUM_msgitem_status_data_ok) && (msg->keepwepflags.data != P80211ENUM_truth_true)) {
2579                                 /* Set the wepflags for no decryption */
2580                                 word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
2581                                         HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
2582                                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFWEPFLAGS, word);
2583                         }
2584
2585                         if ( result ) {
2586                                 WLAN_LOG_DEBUG(1,
2587                                                "failed to set wepflags=0x%04x, result=%d\n",
2588                                                word,
2589                                                result);
2590                                 goto failed;
2591                         }
2592                 }
2593
2594                 /* Do we want to strip the FCS in monitor mode? */
2595                 if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok) && (msg->stripfcs.data == P80211ENUM_truth_true)) {
2596                         hw->sniff_fcs = 0;
2597                 } else {
2598                         hw->sniff_fcs = 1;
2599                 }
2600
2601                 /* Do we want to truncate the packets? */
2602                 if (msg->packet_trunc.status == P80211ENUM_msgitem_status_data_ok) {
2603                         hw->sniff_truncate = msg->packet_trunc.data;
2604                 } else {
2605                         hw->sniff_truncate = 0;
2606                 }
2607
2608                 /* Enable the port */
2609                 result = hfa384x_drvr_enable(hw, 0);
2610                 if ( result ) {
2611                         WLAN_LOG_DEBUG(1,
2612                         "failed to enable port for sniffing, result=%d\n",
2613                         result);
2614                         goto failed;
2615                 }
2616                 /* Enable monitor mode */
2617                 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
2618                 if ( result ) {
2619                         WLAN_LOG_DEBUG(1,
2620                         "failed to enable monitor mode, result=%d\n",
2621                         result);
2622                         goto failed;
2623                 }
2624
2625                 if (wlandev->netdev->type == ARPHRD_ETHER) {
2626                         WLAN_LOG_INFO("monitor mode enabled\n");
2627                 }
2628
2629                 /* Set the driver state */
2630                 /* Do we want the prism2 header? */
2631                 if ((msg->prismheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->prismheader.data == P80211ENUM_truth_true)) {
2632                         hw->sniffhdr = 0;
2633                         wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
2634                 } else if ((msg->wlanheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->wlanheader.data == P80211ENUM_truth_true)) {
2635                         hw->sniffhdr = 1;
2636                         wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
2637                 } else {
2638                         wlandev->netdev->type = ARPHRD_IEEE80211;
2639                 }
2640
2641                 msg->resultcode.data = P80211ENUM_resultcode_success;
2642                 result = 0;
2643                 goto exit;
2644                 break;
2645         default:
2646                 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
2647                 result = 0;
2648                 goto exit;
2649                 break;
2650         }
2651
2652 failed:
2653         msg->resultcode.data = P80211ENUM_resultcode_refused;
2654         result = 0;
2655 exit:
2656
2657         DBFEXIT;
2658         return result;
2659 }