Staging: wlan-ng: Eliminate one more rx mtu test.
[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 /* Converts 802.11 format rate specifications to prism2 */
101 #define p80211rate_to_p2bit(n)  ((((n)&~BIT7) == 2) ? BIT0 : \
102                                  (((n)&~BIT7) == 4) ? BIT1 : \
103                                  (((n)&~BIT7) == 11) ? BIT2 : \
104                                  (((n)&~BIT7) == 22) ? BIT3 : 0)
105
106 /*----------------------------------------------------------------
107 * prism2mgmt_scan
108 *
109 * Initiate a scan for BSSs.
110 *
111 * This function corresponds to MLME-scan.request and part of
112 * MLME-scan.confirm.  As far as I can tell in the standard, there
113 * are no restrictions on when a scan.request may be issued.  We have
114 * to handle in whatever state the driver/MAC happen to be.
115 *
116 * Arguments:
117 *       wlandev         wlan device structure
118 *       msgp            ptr to msg buffer
119 *
120 * Returns:
121 *       0       success and done
122 *       <0      success, but we're waiting for something to finish.
123 *       >0      an error occurred while handling the message.
124 * Side effects:
125 *
126 * Call context:
127 *       process thread  (usually)
128 *       interrupt
129 ----------------------------------------------------------------*/
130 int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp)
131 {
132         int                     result = 0;
133         hfa384x_t               *hw = wlandev->priv;
134         p80211msg_dot11req_scan_t       *msg = msgp;
135         UINT16                  roamingmode, word;
136         int                     i, timeout;
137         int                     istmpenable = 0;
138
139         hfa384x_HostScanRequest_data_t  scanreq;
140
141         DBFENTER;
142
143         /* gatekeeper check */
144         if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
145                                      hw->ident_sta_fw.minor,
146                                      hw->ident_sta_fw.variant) <
147             HFA384x_FIRMWARE_VERSION(1,3,2)) {
148                 WLAN_LOG_ERROR("HostScan not supported with current firmware (<1.3.2).\n");
149                 result = 1;
150                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
151                 goto exit;
152         }
153
154         memset(&scanreq, 0, sizeof(scanreq));
155
156         /* save current roaming mode */
157         result = hfa384x_drvr_getconfig16(hw,
158                         HFA384x_RID_CNFROAMINGMODE, &roamingmode);
159         if ( result ) {
160                 WLAN_LOG_ERROR("getconfig(ROAMMODE) failed. result=%d\n",
161                                 result);
162                 msg->resultcode.data =
163                         P80211ENUM_resultcode_implementation_failure;
164                 goto exit;
165         }
166
167         /* drop into mode 3 for the scan */
168         result = hfa384x_drvr_setconfig16(hw,
169                         HFA384x_RID_CNFROAMINGMODE,
170                         HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
171         if ( result ) {
172                 WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n",
173                                 result);
174                 msg->resultcode.data =
175                         P80211ENUM_resultcode_implementation_failure;
176                 goto exit;
177         }
178
179         /* active or passive? */
180         if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
181                                      hw->ident_sta_fw.minor,
182                                      hw->ident_sta_fw.variant) >
183             HFA384x_FIRMWARE_VERSION(1,5,0)) {
184                 if (msg->scantype.data != P80211ENUM_scantype_active) {
185                         word = host2hfa384x_16(msg->maxchanneltime.data);
186                 } else {
187                         word = 0;
188                 }
189                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL, word);
190                 if ( result ) {
191                         WLAN_LOG_WARNING("Passive scan not supported with "
192                                           "current firmware.  (<1.5.1)\n");
193                 }
194         }
195
196         /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
197         word = HFA384x_RATEBIT_2;
198         scanreq.txRate = host2hfa384x_16(word);
199
200         /* set up the channel list */
201         word = 0;
202         for (i = 0; i < msg->channellist.data.len; i++) {
203                 UINT8 channel = msg->channellist.data.data[i];
204                 if (channel > 14) continue;
205                 /* channel 1 is BIT0 ... channel 14 is BIT13 */
206                 word |= (1 << (channel-1));
207         }
208         scanreq.channelList = host2hfa384x_16(word);
209
210         /* set up the ssid, if present. */
211         scanreq.ssid.len = host2hfa384x_16(msg->ssid.data.len);
212         memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
213
214         /* Enable the MAC port if it's not already enabled  */
215         result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
216         if ( result ) {
217                 WLAN_LOG_ERROR("getconfig(PORTSTATUS) failed. "
218                                 "result=%d\n", result);
219                 msg->resultcode.data =
220                         P80211ENUM_resultcode_implementation_failure;
221                 goto exit;
222         }
223         if (word == HFA384x_PORTSTATUS_DISABLED) {
224                 UINT16 wordbuf[17];
225
226                 result = hfa384x_drvr_setconfig16(hw,
227                         HFA384x_RID_CNFROAMINGMODE,
228                         HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
229                 if ( result ) {
230                         WLAN_LOG_ERROR("setconfig(ROAMINGMODE) failed. result=%d\n", result);
231                         msg->resultcode.data =
232                                 P80211ENUM_resultcode_implementation_failure;
233                         goto exit;
234                 }
235                 /* Construct a bogus SSID and assign it to OwnSSID and
236                  * DesiredSSID
237                  */
238                 wordbuf[0] = host2hfa384x_16(WLAN_SSID_MAXLEN);
239                 get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
240                 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
241                                 wordbuf, HFA384x_RID_CNFOWNSSID_LEN);
242                 if ( result ) {
243                         WLAN_LOG_ERROR("Failed to set OwnSSID.\n");
244                         msg->resultcode.data =
245                                 P80211ENUM_resultcode_implementation_failure;
246                         goto exit;
247                 }
248                 result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID,
249                                 wordbuf, HFA384x_RID_CNFDESIREDSSID_LEN);
250                 if ( result ) {
251                         WLAN_LOG_ERROR("Failed to set DesiredSSID.\n");
252                         msg->resultcode.data =
253                                 P80211ENUM_resultcode_implementation_failure;
254                         goto exit;
255                 }
256                 /* bsstype */
257                 result = hfa384x_drvr_setconfig16(hw,
258                                 HFA384x_RID_CNFPORTTYPE,
259                                 HFA384x_PORTTYPE_IBSS);
260                 if ( result ) {
261                         WLAN_LOG_ERROR("Failed to set CNFPORTTYPE.\n");
262                         msg->resultcode.data =
263                                 P80211ENUM_resultcode_implementation_failure;
264                         goto exit;
265                 }
266                 /* ibss options */
267                 result = hfa384x_drvr_setconfig16(hw,
268                                 HFA384x_RID_CREATEIBSS,
269                                 HFA384x_CREATEIBSS_JOINCREATEIBSS);
270                 if ( result ) {
271                         WLAN_LOG_ERROR("Failed to set CREATEIBSS.\n");
272                         msg->resultcode.data =
273                                 P80211ENUM_resultcode_implementation_failure;
274                         goto exit;
275                 }
276                 result = hfa384x_drvr_enable(hw, 0);
277                 if ( result ) {
278                         WLAN_LOG_ERROR("drvr_enable(0) failed. "
279                                         "result=%d\n", result);
280                         msg->resultcode.data =
281                         P80211ENUM_resultcode_implementation_failure;
282                         goto exit;
283                 }
284                 istmpenable = 1;
285         }
286
287         /* Figure out our timeout first Kus, then HZ */
288         timeout = msg->channellist.data.len * msg->maxchanneltime.data;
289         timeout = (timeout * HZ)/1000;
290
291         /* Issue the scan request */
292         hw->scanflag = 0;
293
294         WLAN_HEX_DUMP(5,"hscanreq", &scanreq, sizeof(scanreq));
295
296         result = hfa384x_drvr_setconfig( hw,
297                         HFA384x_RID_HOSTSCAN, &scanreq,
298                         sizeof(hfa384x_HostScanRequest_data_t));
299         if ( result ) {
300                 WLAN_LOG_ERROR("setconfig(SCANREQUEST) failed. result=%d\n",
301                                 result);
302                 msg->resultcode.data =
303                         P80211ENUM_resultcode_implementation_failure;
304                 goto exit;
305         }
306
307         /* sleep until info frame arrives */
308         wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
309
310         msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
311         if (hw->scanflag == -1)
312                 hw->scanflag = 0;
313
314         msg->numbss.data = hw->scanflag;
315
316         hw->scanflag = 0;
317
318         /* Disable port if we temporarily enabled it. */
319         if (istmpenable) {
320                 result = hfa384x_drvr_disable(hw, 0);
321                 if ( result ) {
322                         WLAN_LOG_ERROR("drvr_disable(0) failed. "
323                                         "result=%d\n", result);
324                         msg->resultcode.data =
325                         P80211ENUM_resultcode_implementation_failure;
326                         goto exit;
327                 }
328         }
329
330         /* restore original roaming mode */
331         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
332                                           roamingmode);
333         if ( result ) {
334                 WLAN_LOG_ERROR("setconfig(ROAMMODE) failed. result=%d\n",
335                                 result);
336                 msg->resultcode.data =
337                         P80211ENUM_resultcode_implementation_failure;
338                 goto exit;
339         }
340
341         result = 0;
342         msg->resultcode.data = P80211ENUM_resultcode_success;
343
344  exit:
345         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
346
347         DBFEXIT;
348         return result;
349 }
350
351
352 /*----------------------------------------------------------------
353 * prism2mgmt_scan_results
354 *
355 * Retrieve the BSS description for one of the BSSs identified in
356 * a scan.
357 *
358 * Arguments:
359 *       wlandev         wlan device structure
360 *       msgp            ptr to msg buffer
361 *
362 * Returns:
363 *       0       success and done
364 *       <0      success, but we're waiting for something to finish.
365 *       >0      an error occurred while handling the message.
366 * Side effects:
367 *
368 * Call context:
369 *       process thread  (usually)
370 *       interrupt
371 ----------------------------------------------------------------*/
372 int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
373 {
374         int                     result = 0;
375         p80211msg_dot11req_scan_results_t       *req;
376         hfa384x_t               *hw = wlandev->priv;
377         hfa384x_HScanResultSub_t *item = NULL;
378
379         int count;
380
381         DBFENTER;
382
383         req = (p80211msg_dot11req_scan_results_t *) msgp;
384
385         req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
386
387         if (! hw->scanresults) {
388                 WLAN_LOG_ERROR("dot11req_scan_results can only be used after a successful dot11req_scan.\n");
389                 result = 2;
390                 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
391                 goto exit;
392         }
393
394         count = (hw->scanresults->framelen - 3) / 32;
395         if (count > 32)  count = 32;
396
397         if (req->bssindex.data >= count) {
398                 WLAN_LOG_DEBUG(0, "requested index (%d) out of range (%d)\n",
399                                 req->bssindex.data, count);
400                 result = 2;
401                 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
402                 goto exit;
403         }
404
405         item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]);
406         /* signal and noise */
407         req->signal.status = P80211ENUM_msgitem_status_data_ok;
408         req->noise.status = P80211ENUM_msgitem_status_data_ok;
409         req->signal.data = hfa384x2host_16(item->sl);
410         req->noise.data = hfa384x2host_16(item->anl);
411
412         /* BSSID */
413         req->bssid.status = P80211ENUM_msgitem_status_data_ok;
414         req->bssid.data.len = WLAN_BSSID_LEN;
415         memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
416
417         /* SSID */
418         req->ssid.status = P80211ENUM_msgitem_status_data_ok;
419         req->ssid.data.len = hfa384x2host_16(item->ssid.len);
420         memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
421
422         /* supported rates */
423         for (count = 0; count < 10 ; count++)
424                 if (item->supprates[count] == 0)
425                         break;
426
427 #define REQBASICRATE(N) \
428         if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \
429                 req->basicrate ## N .data = item->supprates[(N)-1]; \
430                 req->basicrate ## N .status = P80211ENUM_msgitem_status_data_ok; \
431         }
432
433         REQBASICRATE(1);
434         REQBASICRATE(2);
435         REQBASICRATE(3);
436         REQBASICRATE(4);
437         REQBASICRATE(5);
438         REQBASICRATE(6);
439         REQBASICRATE(7);
440         REQBASICRATE(8);
441
442 #define REQSUPPRATE(N) \
443         if (count >= N) { \
444                 req->supprate ## N .data = item->supprates[(N)-1]; \
445                 req->supprate ## N .status = P80211ENUM_msgitem_status_data_ok; \
446         }
447
448         REQSUPPRATE(1);
449         REQSUPPRATE(2);
450         REQSUPPRATE(3);
451         REQSUPPRATE(4);
452         REQSUPPRATE(5);
453         REQSUPPRATE(6);
454         REQSUPPRATE(7);
455         REQSUPPRATE(8);
456
457         /* beacon period */
458         req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
459         req->beaconperiod.data = hfa384x2host_16(item->bcnint);
460
461         /* timestamps */
462         req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
463         req->timestamp.data = jiffies;
464         req->localtime.status = P80211ENUM_msgitem_status_data_ok;
465         req->localtime.data = jiffies;
466
467         /* atim window */
468         req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
469         req->ibssatimwindow.data = hfa384x2host_16(item->atim);
470
471         /* Channel */
472         req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
473         req->dschannel.data = hfa384x2host_16(item->chid);
474
475         /* capinfo bits */
476         count = hfa384x2host_16(item->capinfo);
477
478         /* privacy flag */
479         req->privacy.status = P80211ENUM_msgitem_status_data_ok;
480         req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
481
482         /* cfpollable */
483         req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
484         req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
485
486         /* cfpollreq */
487         req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
488         req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
489
490         /* bsstype */
491         req->bsstype.status =  P80211ENUM_msgitem_status_data_ok;
492         req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
493                 P80211ENUM_bsstype_infrastructure :
494                 P80211ENUM_bsstype_independent;
495
496         // item->proberesp_rate
497 /*
498         req->fhdwelltime
499         req->fhhopset
500         req->fhhoppattern
501         req->fhhopindex
502         req->cfpdurremaining
503 */
504
505         result = 0;
506         req->resultcode.data = P80211ENUM_resultcode_success;
507
508  exit:
509         DBFEXIT;
510         return result;
511 }
512
513 /*----------------------------------------------------------------
514 * prism2mgmt_p2_join
515 *
516 * Join a specific BSS
517 *
518 * Arguments:
519 *       wlandev         wlan device structure
520 *       msgp            ptr to msg buffer
521 *
522 * Returns:
523 *       0       success and done
524 *       <0      success, but we're waiting for something to finish.
525 *       >0      an error occurred while handling the message.
526 * Side effects:
527 *
528 * Call context:
529 *       process thread  (usually)
530 *       interrupt
531 ----------------------------------------------------------------*/
532 int prism2mgmt_p2_join(wlandevice_t *wlandev, void *msgp)
533 {
534         int                     result = 0;
535         hfa384x_t               *hw = wlandev->priv;
536         p80211msg_p2req_join_t  *msg = msgp;
537         UINT16                  reg;
538         p80211pstrd_t           *pstr;
539         UINT8                   bytebuf[256];
540         hfa384x_bytestr_t       *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
541         hfa384x_JoinRequest_data_t      joinreq;
542         DBFENTER;
543
544         wlandev->macmode = WLAN_MACMODE_NONE;
545
546         /* Set the PortType */
547         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
548         msg->resultcode.data = P80211ENUM_resultcode_success;
549
550         /* ess port */
551         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 1);
552         if ( result ) {
553                 WLAN_LOG_ERROR("Failed to set Port Type\n");
554                 goto failed;
555         }
556
557         /* Set the auth type */
558         if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) {
559                 reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
560         } else {
561                 reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
562         }
563         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
564         if ( result ) {
565                 WLAN_LOG_ERROR("Failed to set Authentication\n");
566                 goto failed;
567         }
568
569         /* Turn off all roaming */
570         hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE, 3);
571         if ( result ) {
572                 WLAN_LOG_ERROR("Failed to Turn off Roaming\n");
573                 goto failed;
574         }
575
576         /* Basic rates */
577         reg = 0;
578         if ( msg->basicrate1.status == P80211ENUM_msgitem_status_data_ok ) {
579                 reg = p80211rate_to_p2bit(msg->basicrate1.data);
580         }
581         if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) {
582                 reg |= p80211rate_to_p2bit(msg->basicrate2.data);
583         }
584         if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) {
585                 reg |= p80211rate_to_p2bit(msg->basicrate3.data);
586         }
587         if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) {
588                 reg |= p80211rate_to_p2bit(msg->basicrate4.data);
589         }
590         if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) {
591                 reg |= p80211rate_to_p2bit(msg->basicrate5.data);
592         }
593         if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) {
594                 reg |= p80211rate_to_p2bit(msg->basicrate6.data);
595         }
596         if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) {
597                 reg |= p80211rate_to_p2bit(msg->basicrate7.data);
598         }
599         if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) {
600                 reg |= p80211rate_to_p2bit(msg->basicrate8.data);
601         }
602         if( reg == 0)
603                 reg = 0x03;
604         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, reg);
605         if ( result ) {
606                 WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", reg);
607                 goto failed;
608         }
609
610         /* Operational rates (supprates and txratecontrol) */
611         reg = 0;
612         if ( msg->operationalrate1.status == P80211ENUM_msgitem_status_data_ok ) {
613                 reg = p80211rate_to_p2bit(msg->operationalrate1.data);
614         }
615         if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) {
616                 reg |= p80211rate_to_p2bit(msg->operationalrate2.data);
617         }
618         if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) {
619                 reg |= p80211rate_to_p2bit(msg->operationalrate3.data);
620         }
621         if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) {
622                 reg |= p80211rate_to_p2bit(msg->operationalrate4.data);
623         }
624         if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) {
625                 reg |= p80211rate_to_p2bit(msg->operationalrate5.data);
626         }
627         if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) {
628                 reg |= p80211rate_to_p2bit(msg->operationalrate6.data);
629         }
630         if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) {
631                 reg |= p80211rate_to_p2bit(msg->operationalrate7.data);
632         }
633         if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) {
634                 reg |= p80211rate_to_p2bit(msg->operationalrate8.data);
635         }
636         if( reg == 0)
637                 reg = 0x0f;
638         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, reg);
639         if ( result ) {
640                 WLAN_LOG_ERROR("Failed to set supprates=%d.\n", reg);
641                 goto failed;
642         }
643
644         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, reg);
645         if ( result ) {
646                 WLAN_LOG_ERROR("Failed to set txrates=%d.\n", reg);
647                 goto failed;
648         }
649
650         /* Set the ssid */
651         memset(bytebuf, 0, 256);
652         pstr = (p80211pstrd_t*)&(msg->ssid.data);
653         prism2mgmt_pstr2bytestr(p2bytestr, pstr);
654         result = hfa384x_drvr_setconfig(
655                 hw, HFA384x_RID_CNFDESIREDSSID,
656                 bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
657         if ( result ) {
658                 WLAN_LOG_ERROR("Failed to set SSID\n");
659                 goto failed;
660         }
661
662         /* Enable the Port */
663         result = hfa384x_cmd_enable(hw, 0);
664         if ( result ) {
665                 WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result);
666                 goto failed;
667         }
668
669         /* Fill in the join request */
670         joinreq.channel = msg->channel.data;
671         memcpy( joinreq.bssid, ((unsigned char *) &msg->bssid.data) + 1, WLAN_BSSID_LEN);
672         hw->joinreq = joinreq;
673         hw->join_ap = 1;
674
675         /* Send the join request */
676         result = hfa384x_drvr_setconfig( hw,
677                                          HFA384x_RID_JOINREQUEST,
678                                          &joinreq, HFA384x_RID_JOINREQUEST_LEN);
679         if(result != 0) {
680                 WLAN_LOG_ERROR("Join request failed, result=%d.\n", result);
681                 goto failed;
682         }
683
684         goto done;
685 failed:
686         WLAN_LOG_DEBUG(1, "Failed to set a config option, result=%d\n", result);
687         msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
688
689 done:
690         result = 0;
691
692         DBFEXIT;
693         return result;
694 }
695
696 /*----------------------------------------------------------------
697 * prism2mgmt_associate
698 *
699 * Associate with an ESS.
700 *
701 * Arguments:
702 *       wlandev         wlan device structure
703 *       msgp            ptr to msg buffer
704 *
705 * Returns:
706 *       0       success and done
707 *       <0      success, but we're waiting for something to finish.
708 *       >0      an error occurred while handling the message.
709 * Side effects:
710 *
711 * Call context:
712 *       process thread  (usually)
713 *       interrupt
714 ----------------------------------------------------------------*/
715 int prism2mgmt_associate(wlandevice_t *wlandev, void *msgp)
716 {
717         hfa384x_t               *hw = wlandev->priv;
718         int                     result = 0;
719         p80211msg_dot11req_associate_t  *msg = msgp;
720         DBFENTER;
721
722 #if 0
723         /* Set the TxRates */
724         reg = 0x000f;
725         hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, reg);
726 #endif
727
728         /* Set the PortType */
729         /* ess port */
730         hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 1);
731
732         /* Enable the Port */
733         hfa384x_drvr_enable(hw, 0);
734
735         /* Set the resultcode */
736         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
737         msg->resultcode.data = P80211ENUM_resultcode_success;
738
739         DBFEXIT;
740         return result;
741 }
742
743 /*----------------------------------------------------------------
744 * prism2mgmt_reset
745 *
746 * Reset the MAC and MSD.  The p80211 layer has it's own handling
747 * that should be done before and after this function.
748 * Procedure:
749 *   - disable system interrupts ??
750 *   - disable MAC interrupts
751 *   - restore system interrupts
752 *   - issue the MAC initialize command
753 *   - clear any MSD level state (including timers, queued events,
754 *     etc.).  Note that if we're removing timer'd/queue events, we may
755 *     need to have remained in the system interrupt disabled state.
756 *     We should be left in the same state that we're in following
757 *     driver initialization.
758 *
759 * Arguments:
760 *       wlandev         wlan device structure
761 *       msgp            ptr to msg buffer, MAY BE NULL! for a driver local
762 *                       call.
763 *
764 * Returns:
765 *       0       success and done
766 *       <0      success, but we're waiting for something to finish.
767 *       >0      an error occurred while handling the message.
768 * Side effects:
769 *
770 * Call context:
771 *       process thread, commonly wlanctl, but might be rmmod/pci_close.
772 ----------------------------------------------------------------*/
773 int prism2mgmt_reset(wlandevice_t *wlandev, void *msgp)
774 {
775         int                     result = 0;
776         hfa384x_t               *hw = wlandev->priv;
777         p80211msg_dot11req_reset_t      *msg = msgp;
778         DBFENTER;
779
780         /*
781          * This is supported on both AP and STA and it's not allowed
782          * to fail.
783          */
784         if ( msgp ) {
785                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
786                 msg->resultcode.data = P80211ENUM_resultcode_success;
787                 WLAN_LOG_INFO("dot11req_reset: the macaddress and "
788                         "setdefaultmib arguments are currently unsupported.\n");
789         }
790
791         /*
792          * If we got this far, the MSD must be in the MSDRUNNING state
793          * therefore, we must stop and then restart the hw/MAC combo.
794          */
795         hfa384x_drvr_stop(hw);
796         result = hfa384x_drvr_start(hw);
797         if (result != 0) {
798                 WLAN_LOG_ERROR("dot11req_reset: Initialize command failed,"
799                                 " bad things will happen from here.\n");
800                 return 0;
801         }
802
803         DBFEXIT;
804         return 0;
805 }
806
807
808 /*----------------------------------------------------------------
809 * prism2mgmt_start
810 *
811 * Start a BSS.  Any station can do this for IBSS, only AP for ESS.
812 *
813 * Arguments:
814 *       wlandev         wlan device structure
815 *       msgp            ptr to msg buffer
816 *
817 * Returns:
818 *       0       success and done
819 *       <0      success, but we're waiting for something to finish.
820 *       >0      an error occurred while handling the message.
821 * Side effects:
822 *
823 * Call context:
824 *       process thread  (usually)
825 *       interrupt
826 ----------------------------------------------------------------*/
827 int prism2mgmt_start(wlandevice_t *wlandev, void *msgp)
828 {
829         int                     result = 0;
830         hfa384x_t               *hw = wlandev->priv;
831         p80211msg_dot11req_start_t      *msg = msgp;
832
833         p80211pstrd_t           *pstr;
834         UINT8                   bytebuf[80];
835         hfa384x_bytestr_t       *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
836         UINT16                  word;
837         DBFENTER;
838
839         wlandev->macmode = WLAN_MACMODE_NONE;
840
841         /* Set the SSID */
842         memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
843
844         /*** ADHOC IBSS ***/
845         /* see if current f/w is less than 8c3 */
846         if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
847                                      hw->ident_sta_fw.minor,
848                                      hw->ident_sta_fw.variant) <
849             HFA384x_FIRMWARE_VERSION(0,8,3)) {
850                 /* Ad-Hoc not quite supported on Prism2 */
851                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
852                 msg->resultcode.data = P80211ENUM_resultcode_not_supported;
853                 goto done;
854         }
855
856         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
857
858         /*** STATION ***/
859         /* Set the REQUIRED config items */
860         /* SSID */
861         pstr = (p80211pstrd_t*)&(msg->ssid.data);
862         prism2mgmt_pstr2bytestr(p2bytestr, pstr);
863         result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFOWNSSID,
864                                          bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
865         if ( result ) {
866                 WLAN_LOG_ERROR("Failed to set CnfOwnSSID\n");
867                 goto failed;
868         }
869         result = hfa384x_drvr_setconfig( hw, HFA384x_RID_CNFDESIREDSSID,
870                                          bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
871         if ( result ) {
872                 WLAN_LOG_ERROR("Failed to set CnfDesiredSSID\n");
873                 goto failed;
874         }
875
876         /* bsstype - we use the default in the ap firmware */
877         /* IBSS port */
878         hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
879
880         /* beacon period */
881         word = msg->beaconperiod.data;
882         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNINT, word);
883         if ( result ) {
884                 WLAN_LOG_ERROR("Failed to set beacon period=%d.\n", word);
885                 goto failed;
886         }
887
888         /* dschannel */
889         word = msg->dschannel.data;
890         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
891         if ( result ) {
892                 WLAN_LOG_ERROR("Failed to set channel=%d.\n", word);
893                 goto failed;
894         }
895         /* Basic rates */
896         word = p80211rate_to_p2bit(msg->basicrate1.data);
897         if ( msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok ) {
898                 word |= p80211rate_to_p2bit(msg->basicrate2.data);
899         }
900         if ( msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok ) {
901                 word |= p80211rate_to_p2bit(msg->basicrate3.data);
902         }
903         if ( msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok ) {
904                 word |= p80211rate_to_p2bit(msg->basicrate4.data);
905         }
906         if ( msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok ) {
907                 word |= p80211rate_to_p2bit(msg->basicrate5.data);
908         }
909         if ( msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok ) {
910                 word |= p80211rate_to_p2bit(msg->basicrate6.data);
911         }
912         if ( msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok ) {
913                 word |= p80211rate_to_p2bit(msg->basicrate7.data);
914         }
915         if ( msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok ) {
916                 word |= p80211rate_to_p2bit(msg->basicrate8.data);
917         }
918         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
919         if ( result ) {
920                 WLAN_LOG_ERROR("Failed to set basicrates=%d.\n", word);
921                 goto failed;
922         }
923
924         /* Operational rates (supprates and txratecontrol) */
925         word = p80211rate_to_p2bit(msg->operationalrate1.data);
926         if ( msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok ) {
927                 word |= p80211rate_to_p2bit(msg->operationalrate2.data);
928         }
929         if ( msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok ) {
930                 word |= p80211rate_to_p2bit(msg->operationalrate3.data);
931         }
932         if ( msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok ) {
933                 word |= p80211rate_to_p2bit(msg->operationalrate4.data);
934         }
935         if ( msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok ) {
936                 word |= p80211rate_to_p2bit(msg->operationalrate5.data);
937         }
938         if ( msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok ) {
939                 word |= p80211rate_to_p2bit(msg->operationalrate6.data);
940         }
941         if ( msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok ) {
942                 word |= p80211rate_to_p2bit(msg->operationalrate7.data);
943         }
944         if ( msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok ) {
945                 word |= p80211rate_to_p2bit(msg->operationalrate8.data);
946         }
947         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
948         if ( result ) {
949                 WLAN_LOG_ERROR("Failed to set supprates=%d.\n", word);
950                 goto failed;
951         }
952
953         result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
954         if ( result ) {
955                 WLAN_LOG_ERROR("Failed to set txrates=%d.\n", word);
956                 goto failed;
957         }
958
959         /* Set the macmode so the frame setup code knows what to do */
960         if ( msg->bsstype.data == P80211ENUM_bsstype_independent ) {
961                 wlandev->macmode = WLAN_MACMODE_IBSS_STA;
962                 /* lets extend the data length a bit */
963                 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
964         }
965
966         /* Enable the Port */
967         result = hfa384x_drvr_enable(hw, 0);
968         if ( result ) {
969                 WLAN_LOG_ERROR("Enable macport failed, result=%d.\n", result);
970                 goto failed;
971         }
972
973         msg->resultcode.data = P80211ENUM_resultcode_success;
974
975         goto done;
976 failed:
977         WLAN_LOG_DEBUG(1, "Failed to set a config option, result=%d\n", result);
978         msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
979
980 done:
981         result = 0;
982
983         DBFEXIT;
984         return result;
985 }
986
987 /*----------------------------------------------------------------
988 * prism2mgmt_readpda
989 *
990 * Collect the PDA data and put it in the message.
991 *
992 * Arguments:
993 *       wlandev         wlan device structure
994 *       msgp            ptr to msg buffer
995 *
996 * Returns:
997 *       0       success and done
998 *       <0      success, but we're waiting for something to finish.
999 *       >0      an error occurred while handling the message.
1000 * Side effects:
1001 *
1002 * Call context:
1003 *       process thread  (usually)
1004 ----------------------------------------------------------------*/
1005 int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp)
1006 {
1007         hfa384x_t               *hw = wlandev->priv;
1008         p80211msg_p2req_readpda_t       *msg = msgp;
1009         int                             result;
1010         DBFENTER;
1011
1012         /* We only support collecting the PDA when in the FWLOAD
1013          * state.
1014          */
1015         if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
1016                 WLAN_LOG_ERROR(
1017                         "PDA may only be read "
1018                         "in the fwload state.\n");
1019                 msg->resultcode.data =
1020                         P80211ENUM_resultcode_implementation_failure;
1021                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1022         } else {
1023                 /*  Call drvr_readpda(), it handles the auxport enable
1024                  *  and validating the returned PDA.
1025                  */
1026                 result = hfa384x_drvr_readpda(
1027                         hw,
1028                         msg->pda.data,
1029                         HFA384x_PDA_LEN_MAX);
1030                 if (result) {
1031                         WLAN_LOG_ERROR(
1032                                 "hfa384x_drvr_readpda() failed, "
1033                                 "result=%d\n",
1034                                 result);
1035
1036                         msg->resultcode.data =
1037                                 P80211ENUM_resultcode_implementation_failure;
1038                         msg->resultcode.status =
1039                                 P80211ENUM_msgitem_status_data_ok;
1040                         DBFEXIT;
1041                         return 0;
1042                 }
1043                 msg->pda.status = P80211ENUM_msgitem_status_data_ok;
1044                 msg->resultcode.data = P80211ENUM_resultcode_success;
1045                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1046         }
1047
1048         DBFEXIT;
1049         return 0;
1050 }
1051
1052 /*----------------------------------------------------------------
1053 * prism2mgmt_readcis
1054 *
1055 * Collect the CIS data and put it in the message.
1056 *
1057 * Arguments:
1058 *       wlandev         wlan device structure
1059 *       msgp            ptr to msg buffer
1060 *
1061 * Returns:
1062 *       0       success and done
1063 *       <0      success, but we're waiting for something to finish.
1064 *       >0      an error occurred while handling the message.
1065 * Side effects:
1066 *
1067 * Call context:
1068 *       process thread  (usually)
1069 ----------------------------------------------------------------*/
1070 int prism2mgmt_readcis(wlandevice_t *wlandev, void *msgp)
1071 {
1072         int                     result;
1073         hfa384x_t               *hw = wlandev->priv;
1074         p80211msg_p2req_readcis_t       *msg = msgp;
1075
1076         DBFENTER;
1077
1078         memset(msg->cis.data, 0, sizeof(msg->cis.data));
1079
1080         result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CIS,
1081                                         msg->cis.data, HFA384x_RID_CIS_LEN);
1082         if ( result ) {
1083                 WLAN_LOG_INFO("prism2mgmt_readcis: read(cis) failed.\n");
1084                 msg->cis.status = P80211ENUM_msgitem_status_no_value;
1085                 msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
1086
1087                 }
1088         else {
1089                 msg->cis.status = P80211ENUM_msgitem_status_data_ok;
1090                 msg->resultcode.data = P80211ENUM_resultcode_success;
1091                 }
1092
1093         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1094
1095         DBFEXIT;
1096         return 0;
1097 }
1098
1099 /*----------------------------------------------------------------
1100 * prism2mgmt_auxport_state
1101 *
1102 * Enables/Disables the card's auxiliary port.  Should be called
1103 * before and after a sequence of auxport_read()/auxport_write()
1104 * calls.
1105 *
1106 * Arguments:
1107 *       wlandev         wlan device structure
1108 *       msgp            ptr to msg buffer
1109 *
1110 * Returns:
1111 *       0       success and done
1112 *       <0      success, but we're waiting for something to finish.
1113 *       >0      an error occurred while handling the message.
1114 * Side effects:
1115 *
1116 * Call context:
1117 *       process thread  (usually)
1118 ----------------------------------------------------------------*/
1119 int prism2mgmt_auxport_state(wlandevice_t *wlandev, void *msgp)
1120 {
1121         p80211msg_p2req_auxport_state_t *msg = msgp;
1122
1123         DBFENTER;
1124
1125         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1126         msg->resultcode.data = P80211ENUM_resultcode_not_supported;
1127
1128         DBFEXIT;
1129         return 0;
1130 }
1131
1132
1133 /*----------------------------------------------------------------
1134 * prism2mgmt_auxport_read
1135 *
1136 * Copies data from the card using the auxport.  The auxport must
1137 * have previously been enabled.  Note: this is not the way to
1138 * do downloads, see the [ram|flash]dl functions.
1139 *
1140 * Arguments:
1141 *       wlandev         wlan device structure
1142 *       msgp            ptr to msg buffer
1143 *
1144 * Returns:
1145 *       0       success and done
1146 *       <0      success, but we're waiting for something to finish.
1147 *       >0      an error occurred while handling the message.
1148 * Side effects:
1149 *
1150 * Call context:
1151 *       process thread  (usually)
1152 ----------------------------------------------------------------*/
1153 int prism2mgmt_auxport_read(wlandevice_t *wlandev, void *msgp)
1154 {
1155         DBFENTER;
1156
1157         WLAN_LOG_ERROR("prism2mgmt_auxport_read: Not supported on USB.\n");
1158
1159         DBFEXIT;
1160         return 0;
1161 }
1162
1163
1164 /*----------------------------------------------------------------
1165 * prism2mgmt_auxport_write
1166 *
1167 * Copies data to the card using the auxport.  The auxport must
1168 * have previously been enabled.  Note: this is not the way to
1169 * do downloads, see the [ram|flash]dl functions.
1170 *
1171 * Arguments:
1172 *       wlandev         wlan device structure
1173 *       msgp            ptr to msg buffer
1174 *
1175 * Returns:
1176 *       0       success and done
1177 *       <0      success, but we're waiting for something to finish.
1178 *       >0      an error occurred while handling the message.
1179 * Side effects:
1180 *
1181 * Call context:
1182 *       process thread  (usually)
1183 ----------------------------------------------------------------*/
1184 int prism2mgmt_auxport_write(wlandevice_t *wlandev, void *msgp)
1185 {
1186         DBFENTER;
1187         WLAN_LOG_ERROR("prism2mgmt_auxport_read: Not supported on USB.\n");
1188         DBFEXIT;
1189         return 0;
1190 }
1191
1192 /*----------------------------------------------------------------
1193 * prism2mgmt_low_level
1194 *
1195 * Puts the card into the desired test mode.
1196 *
1197 * Arguments:
1198 *       wlandev         wlan device structure
1199 *       msgp            ptr to msg buffer
1200 *
1201 * Returns:
1202 *       0       success and done
1203 *       <0      success, but we're waiting for something to finish.
1204 *       >0      an error occurred while handling the message.
1205 * Side effects:
1206 *
1207 * Call context:
1208 *       process thread  (usually)
1209 ----------------------------------------------------------------*/
1210 int prism2mgmt_low_level(wlandevice_t *wlandev, void *msgp)
1211 {
1212         hfa384x_t               *hw = wlandev->priv;
1213         p80211msg_p2req_low_level_t     *msg = msgp;
1214         hfa384x_metacmd_t cmd;
1215         DBFENTER;
1216
1217         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1218
1219         /* call some routine to execute the test command */
1220         cmd.cmd = (UINT16) msg->command.data;
1221         cmd.parm0 = (UINT16) msg->param0.data;
1222         cmd.parm1 = (UINT16) msg->param1.data;
1223         cmd.parm2 = (UINT16) msg->param2.data;
1224
1225         hfa384x_drvr_low_level(hw,&cmd);
1226
1227         msg->resp0.data = (UINT32) cmd.result.resp0;
1228         msg->resp1.data = (UINT32) cmd.result.resp1;
1229         msg->resp2.data = (UINT32) cmd.result.resp2;
1230
1231         msg->resultcode.data = P80211ENUM_resultcode_success;
1232
1233         DBFEXIT;
1234         return 0;
1235 }
1236
1237 /*----------------------------------------------------------------
1238 * prism2mgmt_test_command
1239 *
1240 * Puts the card into the desired test mode.
1241 *
1242 * Arguments:
1243 *       wlandev         wlan device structure
1244 *       msgp            ptr to msg buffer
1245 *
1246 * Returns:
1247 *       0       success and done
1248 *       <0      success, but we're waiting for something to finish.
1249 *       >0      an error occurred while handling the message.
1250 * Side effects:
1251 *
1252 * Call context:
1253 *       process thread  (usually)
1254 ----------------------------------------------------------------*/
1255 int prism2mgmt_test_command(wlandevice_t *wlandev, void *msgp)
1256 {
1257         hfa384x_t               *hw = wlandev->priv;
1258         p80211msg_p2req_test_command_t  *msg = msgp;
1259         hfa384x_metacmd_t cmd;
1260
1261         DBFENTER;
1262
1263         cmd.cmd = ((UINT16) msg->testcode.data) << 8 | 0x38;
1264         cmd.parm0 = (UINT16) msg->testparam.data;
1265         cmd.parm1 = 0;
1266         cmd.parm2 = 0;
1267
1268         /* call some routine to execute the test command */
1269
1270         hfa384x_drvr_low_level(hw,&cmd);
1271
1272         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1273         msg->resultcode.data = P80211ENUM_resultcode_success;
1274
1275         msg->status.status = P80211ENUM_msgitem_status_data_ok;
1276         msg->status.data = cmd.result.status;
1277         msg->resp0.status = P80211ENUM_msgitem_status_data_ok;
1278         msg->resp0.data = cmd.result.resp0;
1279         msg->resp1.status = P80211ENUM_msgitem_status_data_ok;
1280         msg->resp1.data = cmd.result.resp1;
1281         msg->resp2.status = P80211ENUM_msgitem_status_data_ok;
1282         msg->resp2.data = cmd.result.resp2;
1283
1284         DBFEXIT;
1285         return 0;
1286 }
1287
1288
1289 /*----------------------------------------------------------------
1290 * prism2mgmt_mmi_read
1291 *
1292 * Read from one of the MMI registers.
1293 *
1294 * Arguments:
1295 *       wlandev         wlan device structure
1296 *       msgp            ptr to msg buffer
1297 *
1298 * Returns:
1299 *       0       success and done
1300 *       <0      success, but we're waiting for something to finish.
1301 *       >0      an error occurred while handling the message.
1302 * Side effects:
1303 *
1304 * Call context:
1305 *       process thread  (usually)
1306 ----------------------------------------------------------------*/
1307 int prism2mgmt_mmi_read(wlandevice_t *wlandev, void *msgp)
1308 {
1309         hfa384x_t               *hw = wlandev->priv;
1310         p80211msg_p2req_mmi_read_t      *msg = msgp;
1311         UINT32 resp = 0;
1312
1313         DBFENTER;
1314
1315         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1316
1317         /* call some routine to execute the test command */
1318
1319         hfa384x_drvr_mmi_read(hw, msg->addr.data, &resp);
1320
1321         /* I'm not sure if this is "architecturally" correct, but it
1322            is expedient. */
1323
1324         msg->value.status = P80211ENUM_msgitem_status_data_ok;
1325         msg->value.data = resp;
1326         msg->resultcode.data = P80211ENUM_resultcode_success;
1327
1328         DBFEXIT;
1329         return 0;
1330 }
1331
1332 /*----------------------------------------------------------------
1333 * prism2mgmt_mmi_write
1334 *
1335 * Write a data value to one of the MMI registers.
1336 *
1337 * Arguments:
1338 *       wlandev         wlan device structure
1339 *       msgp            ptr to msg buffer
1340 *
1341 * Returns:
1342 *       0       success and done
1343 *       <0      success, but we're waiting for something to finish.
1344 *       >0      an error occurred while handling the message.
1345 * Side effects:
1346 *
1347 * Call context:
1348 *       process thread  (usually)
1349 ----------------------------------------------------------------*/
1350 int prism2mgmt_mmi_write(wlandevice_t *wlandev, void *msgp)
1351 {
1352         hfa384x_t               *hw = wlandev->priv;
1353         p80211msg_p2req_mmi_write_t     *msg = msgp;
1354         DBFENTER;
1355
1356         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1357
1358         /* call some routine to execute the test command */
1359
1360         hfa384x_drvr_mmi_write(hw, msg->addr.data, msg->data.data);
1361
1362         msg->resultcode.data = P80211ENUM_resultcode_success;
1363
1364         DBFEXIT;
1365         return 0;
1366 }
1367
1368 /*----------------------------------------------------------------
1369 * prism2mgmt_ramdl_state
1370 *
1371 * Establishes the beginning/end of a card RAM download session.
1372 *
1373 * It is expected that the ramdl_write() function will be called
1374 * one or more times between the 'enable' and 'disable' calls to
1375 * this function.
1376 *
1377 * Note: This function should not be called when a mac comm port
1378 *       is active.
1379 *
1380 * Arguments:
1381 *       wlandev         wlan device structure
1382 *       msgp            ptr to msg buffer
1383 *
1384 * Returns:
1385 *       0       success and done
1386 *       <0      success, but we're waiting for something to finish.
1387 *       >0      an error occurred while handling the message.
1388 * Side effects:
1389 *
1390 * Call context:
1391 *       process thread  (usually)
1392 ----------------------------------------------------------------*/
1393 int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp)
1394 {
1395         hfa384x_t               *hw = wlandev->priv;
1396         p80211msg_p2req_ramdl_state_t   *msg = msgp;
1397         DBFENTER;
1398
1399         if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
1400                 WLAN_LOG_ERROR(
1401                         "ramdl_state(): may only be called "
1402                         "in the fwload state.\n");
1403                 msg->resultcode.data =
1404                         P80211ENUM_resultcode_implementation_failure;
1405                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1406                 DBFEXIT;
1407                 return 0;
1408         }
1409
1410         /*
1411         ** Note: Interrupts are locked out if this is an AP and are NOT
1412         ** locked out if this is a station.
1413         */
1414
1415         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1416         if  ( msg->enable.data == P80211ENUM_truth_true ) {
1417                 if ( hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data) ) {
1418                         msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
1419                 } else {
1420                         msg->resultcode.data = P80211ENUM_resultcode_success;
1421                 }
1422         } else {
1423                 hfa384x_drvr_ramdl_disable(hw);
1424                 msg->resultcode.data = P80211ENUM_resultcode_success;
1425         }
1426
1427         DBFEXIT;
1428         return 0;
1429 }
1430
1431
1432 /*----------------------------------------------------------------
1433 * prism2mgmt_ramdl_write
1434 *
1435 * Writes a buffer to the card RAM using the download state.  This
1436 * is for writing code to card RAM.  To just read or write raw data
1437 * use the aux functions.
1438 *
1439 * Arguments:
1440 *       wlandev         wlan device structure
1441 *       msgp            ptr to msg buffer
1442 *
1443 * Returns:
1444 *       0       success and done
1445 *       <0      success, but we're waiting for something to finish.
1446 *       >0      an error occurred while handling the message.
1447 * Side effects:
1448 *
1449 * Call context:
1450 *       process thread  (usually)
1451 ----------------------------------------------------------------*/
1452 int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp)
1453 {
1454         hfa384x_t               *hw = wlandev->priv;
1455         p80211msg_p2req_ramdl_write_t   *msg = msgp;
1456         UINT32                  addr;
1457         UINT32                  len;
1458         UINT8                   *buf;
1459         DBFENTER;
1460
1461         if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
1462                 WLAN_LOG_ERROR(
1463                         "ramdl_write(): may only be called "
1464                         "in the fwload state.\n");
1465                 msg->resultcode.data =
1466                         P80211ENUM_resultcode_implementation_failure;
1467                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1468                 DBFEXIT;
1469                 return 0;
1470         }
1471
1472         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1473         /* first validate the length */
1474         if  ( msg->len.data > sizeof(msg->data.data) ) {
1475                 msg->resultcode.status = P80211ENUM_resultcode_invalid_parameters;
1476                 return 0;
1477         }
1478         /* call the hfa384x function to do the write */
1479         addr = msg->addr.data;
1480         len = msg->len.data;
1481         buf = msg->data.data;
1482         if ( hfa384x_drvr_ramdl_write(hw, addr, buf, len) ) {
1483                 msg->resultcode.data = P80211ENUM_resultcode_refused;
1484
1485         }
1486         msg->resultcode.data = P80211ENUM_resultcode_success;
1487
1488         DBFEXIT;
1489         return 0;
1490 }
1491
1492
1493 /*----------------------------------------------------------------
1494 * prism2mgmt_flashdl_state
1495 *
1496 * Establishes the beginning/end of a card Flash download session.
1497 *
1498 * It is expected that the flashdl_write() function will be called
1499 * one or more times between the 'enable' and 'disable' calls to
1500 * this function.
1501 *
1502 * Note: This function should not be called when a mac comm port
1503 *       is active.
1504 *
1505 * Arguments:
1506 *       wlandev         wlan device structure
1507 *       msgp            ptr to msg buffer
1508 *
1509 * Returns:
1510 *       0       success and done
1511 *       <0      success, but we're waiting for something to finish.
1512 *       >0      an error occurred while handling the message.
1513 * Side effects:
1514 *
1515 * Call context:
1516 *       process thread  (usually)
1517 ----------------------------------------------------------------*/
1518 int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
1519 {
1520         int                     result = 0;
1521         hfa384x_t               *hw = wlandev->priv;
1522         p80211msg_p2req_flashdl_state_t *msg = msgp;
1523         DBFENTER;
1524
1525         if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
1526                 WLAN_LOG_ERROR(
1527                         "flashdl_state(): may only be called "
1528                         "in the fwload state.\n");
1529                 msg->resultcode.data =
1530                         P80211ENUM_resultcode_implementation_failure;
1531                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1532                 DBFEXIT;
1533                 return 0;
1534         }
1535
1536         /*
1537         ** Note: Interrupts are locked out if this is an AP and are NOT
1538         ** locked out if this is a station.
1539         */
1540
1541         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1542         if  ( msg->enable.data == P80211ENUM_truth_true ) {
1543                 if ( hfa384x_drvr_flashdl_enable(hw) ) {
1544                         msg->resultcode.data = P80211ENUM_resultcode_implementation_failure;
1545                 } else {
1546                         msg->resultcode.data = P80211ENUM_resultcode_success;
1547                 }
1548         } else {
1549                 hfa384x_drvr_flashdl_disable(hw);
1550                 msg->resultcode.data = P80211ENUM_resultcode_success;
1551                 /* NOTE: At this point, the MAC is in the post-reset
1552                  * state and the driver is in the fwload state.
1553                  * We need to get the MAC back into the fwload
1554                  * state.  To do this, we set the nsdstate to HWPRESENT
1555                  * and then call the ifstate function to redo everything
1556                  * that got us into the fwload state.
1557                  */
1558                 wlandev->msdstate = WLAN_MSD_HWPRESENT;
1559                 result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
1560                 if (result != P80211ENUM_resultcode_success) {
1561                         WLAN_LOG_ERROR("prism2sta_ifstate(fwload) failed,"
1562                                 "P80211ENUM_resultcode=%d\n", result);
1563                         msg->resultcode.data =
1564                                 P80211ENUM_resultcode_implementation_failure;
1565                         result = -1;
1566                 }
1567         }
1568
1569         DBFEXIT;
1570         return 0;
1571 }
1572
1573
1574 /*----------------------------------------------------------------
1575 * prism2mgmt_flashdl_write
1576 *
1577 *
1578 *
1579 * Arguments:
1580 *       wlandev         wlan device structure
1581 *       msgp            ptr to msg buffer
1582 *
1583 * Returns:
1584 *       0       success and done
1585 *       <0      success, but we're waiting for something to finish.
1586 *       >0      an error occurred while handling the message.
1587 * Side effects:
1588 *
1589 * Call context:
1590 *       process thread  (usually)
1591 ----------------------------------------------------------------*/
1592 int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp)
1593 {
1594         hfa384x_t               *hw = wlandev->priv;
1595         p80211msg_p2req_flashdl_write_t *msg = msgp;
1596         UINT32                  addr;
1597         UINT32                  len;
1598         UINT8                   *buf;
1599         DBFENTER;
1600
1601         if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
1602                 WLAN_LOG_ERROR(
1603                         "flashdl_write(): may only be called "
1604                         "in the fwload state.\n");
1605                 msg->resultcode.data =
1606                         P80211ENUM_resultcode_implementation_failure;
1607                 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1608                 DBFEXIT;
1609                 return 0;
1610         }
1611
1612         /*
1613         ** Note: Interrupts are locked out if this is an AP and are NOT
1614         ** locked out if this is a station.
1615         */
1616
1617         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1618         /* first validate the length */
1619         if  ( msg->len.data > sizeof(msg->data.data) ) {
1620                 msg->resultcode.status =
1621                         P80211ENUM_resultcode_invalid_parameters;
1622                 return 0;
1623         }
1624         /* call the hfa384x function to do the write */
1625         addr = msg->addr.data;
1626         len = msg->len.data;
1627         buf = msg->data.data;
1628         if ( hfa384x_drvr_flashdl_write(hw, addr, buf, len) ) {
1629                 msg->resultcode.data = P80211ENUM_resultcode_refused;
1630
1631         }
1632         msg->resultcode.data = P80211ENUM_resultcode_success;
1633
1634         DBFEXIT;
1635         return 0;
1636 }
1637
1638
1639 /*----------------------------------------------------------------
1640 * prism2mgmt_dump_state
1641 *
1642 * Dumps the driver's and hardware's current state via the kernel
1643 * log at KERN_NOTICE level.
1644 *
1645 * Arguments:
1646 *       wlandev         wlan device structure
1647 *       msgp            ptr to msg buffer
1648 *
1649 * Returns:
1650 *       0       success and done
1651 *       <0      success, but we're waiting for something to finish.
1652 *       >0      an error occurred while handling the message.
1653 * Side effects:
1654 *
1655 * Call context:
1656 *       process thread  (usually)
1657 ----------------------------------------------------------------*/
1658 int prism2mgmt_dump_state(wlandevice_t *wlandev, void *msgp)
1659 {
1660         p80211msg_p2req_dump_state_t    *msg = msgp;
1661         int                             result = 0;
1662
1663         DBFENTER;
1664
1665         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1666         msg->resultcode.data = P80211ENUM_resultcode_not_supported;
1667         goto failed;
1668
1669 failed:
1670         DBFEXIT;
1671         return result;
1672 }
1673
1674 /*----------------------------------------------------------------
1675 * prism2mgmt_autojoin
1676 *
1677 * Associate with an ESS.
1678 *
1679 * Arguments:
1680 *       wlandev         wlan device structure
1681 *       msgp            ptr to msg buffer
1682 *
1683 * Returns:
1684 *       0       success and done
1685 *       <0      success, but we're waiting for something to finish.
1686 *       >0      an error occurred while handling the message.
1687 * Side effects:
1688 *
1689 * Call context:
1690 *       process thread  (usually)
1691 *       interrupt
1692 ----------------------------------------------------------------*/
1693 int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
1694 {
1695         hfa384x_t                       *hw = wlandev->priv;
1696         int                     result = 0;
1697         UINT16                  reg;
1698         UINT16                  port_type;
1699         p80211msg_lnxreq_autojoin_t     *msg = msgp;
1700         p80211pstrd_t           *pstr;
1701         UINT8                   bytebuf[256];
1702         hfa384x_bytestr_t       *p2bytestr = (hfa384x_bytestr_t*)bytebuf;
1703         DBFENTER;
1704
1705         wlandev->macmode = WLAN_MACMODE_NONE;
1706
1707         /* Set the SSID */
1708         memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
1709
1710         /* Disable the Port */
1711         hfa384x_drvr_disable(hw, 0);
1712
1713         /*** STATION ***/
1714         /* Set the TxRates */
1715         hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
1716
1717         /* Set the auth type */
1718         if ( msg->authtype.data == P80211ENUM_authalg_sharedkey ) {
1719                 reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
1720         } else {
1721                 reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
1722         }
1723         hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
1724
1725         /* Set the ssid */
1726         memset(bytebuf, 0, 256);
1727         pstr = (p80211pstrd_t*)&(msg->ssid.data);
1728         prism2mgmt_pstr2bytestr(p2bytestr, pstr);
1729         result = hfa384x_drvr_setconfig(
1730                         hw, HFA384x_RID_CNFDESIREDSSID,
1731                         bytebuf, HFA384x_RID_CNFDESIREDSSID_LEN);
1732 #if 0
1733         /* we can use the new-fangled auto-unknown mode if the firmware
1734            is 1.3.3 or newer */
1735         if (HFA384x_FIRMARE_VERSION(hw->ident_sta_fw.major,
1736                                     hw->ident_sta_fw.minor,
1737                                     hw->ident_sta_fw.variant) >=
1738             HFA384x_FIRMWARE_VERSION(1,3,3)) {
1739                 /* Set up the IBSS options */
1740                 reg =  HFA384x_CREATEIBSS_JOINESS_JOINCREATEIBSS;
1741                 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CREATEIBSS, reg);
1742
1743                 /* Set the PortType */
1744                 port_type = HFA384x_PORTTYPE_IBSS;
1745         } else {
1746                 port_type = HFA384x_PORTTYPE_BSS;
1747         }
1748 #else
1749         port_type = HFA384x_PORTTYPE_BSS;
1750 #endif
1751         /* Set the PortType */
1752         hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
1753
1754         /* Enable the Port */
1755         hfa384x_drvr_enable(hw, 0);
1756
1757         /* Set the resultcode */
1758         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1759         msg->resultcode.data = P80211ENUM_resultcode_success;
1760
1761         DBFEXIT;
1762         return result;
1763 }
1764
1765
1766 /*----------------------------------------------------------------
1767 * prism2mgmt_wlansniff
1768 *
1769 * Start or stop sniffing.
1770 *
1771 * Arguments:
1772 *       wlandev         wlan device structure
1773 *       msgp            ptr to msg buffer
1774 *
1775 * Returns:
1776 *       0       success and done
1777 *       <0      success, but we're waiting for something to finish.
1778 *       >0      an error occurred while handling the message.
1779 * Side effects:
1780 *
1781 * Call context:
1782 *       process thread  (usually)
1783 *       interrupt
1784 ----------------------------------------------------------------*/
1785 int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
1786 {
1787         int                     result = 0;
1788         p80211msg_lnxreq_wlansniff_t    *msg = msgp;
1789
1790         hfa384x_t                       *hw = wlandev->priv;
1791         UINT16                  word;
1792
1793         DBFENTER;
1794
1795         msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1796         switch (msg->enable.data)
1797         {
1798         case P80211ENUM_truth_false:
1799                 /* Confirm that we're in monitor mode */
1800                 if ( wlandev->netdev->type == ARPHRD_ETHER ) {
1801                         msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1802                         result = 0;
1803                         goto exit;
1804                 }
1805                 /* Disable monitor mode */
1806                 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
1807                 if ( result ) {
1808                         WLAN_LOG_DEBUG(1,
1809                                 "failed to disable monitor mode, result=%d\n",
1810                                 result);
1811                         goto failed;
1812                 }
1813                 /* Disable port 0 */
1814                 result = hfa384x_drvr_disable(hw, 0);
1815                 if ( result ) {
1816                         WLAN_LOG_DEBUG(1,
1817                         "failed to disable port 0 after sniffing, result=%d\n",
1818                         result);
1819                         goto failed;
1820                 }
1821                 /* Clear the driver state */
1822                 wlandev->netdev->type = ARPHRD_ETHER;
1823
1824                 /* Restore the wepflags */
1825                 result = hfa384x_drvr_setconfig16(hw,
1826                                 HFA384x_RID_CNFWEPFLAGS,
1827                                 hw->presniff_wepflags);
1828                 if ( result ) {
1829                         WLAN_LOG_DEBUG(1,
1830                         "failed to restore wepflags=0x%04x, result=%d\n",
1831                         hw->presniff_wepflags,
1832                         result);
1833                         goto failed;
1834                 }
1835
1836                 /* Set the port to its prior type and enable (if necessary) */
1837                 if (hw->presniff_port_type != 0 ) {
1838                         word = hw->presniff_port_type;
1839                         result = hfa384x_drvr_setconfig16(hw,
1840                                 HFA384x_RID_CNFPORTTYPE, word);
1841                         if ( result ) {
1842                                 WLAN_LOG_DEBUG(1,
1843                                 "failed to restore porttype, result=%d\n",
1844                                 result);
1845                                 goto failed;
1846                         }
1847
1848                         /* Enable the port */
1849                         result = hfa384x_drvr_enable(hw, 0);
1850                         if ( result ) {
1851                                 WLAN_LOG_DEBUG(1, "failed to enable port to presniff setting, result=%d\n", result);
1852                                 goto failed;
1853                         }
1854                 } else {
1855                         result = hfa384x_drvr_disable(hw, 0);
1856
1857                 }
1858
1859                 WLAN_LOG_INFO("monitor mode disabled\n");
1860                 msg->resultcode.data = P80211ENUM_resultcode_success;
1861                 result = 0;
1862                 goto exit;
1863                 break;
1864         case P80211ENUM_truth_true:
1865                 /* Disable the port (if enabled), only check Port 0 */
1866                 if ( hw->port_enabled[0]) {
1867                         if (wlandev->netdev->type == ARPHRD_ETHER) {
1868                                 /* Save macport 0 state */
1869                                 result = hfa384x_drvr_getconfig16(hw,
1870                                                                   HFA384x_RID_CNFPORTTYPE,
1871                                                                   &(hw->presniff_port_type));
1872                                 if ( result ) {
1873                                         WLAN_LOG_DEBUG(1,"failed to read porttype, result=%d\n", result);
1874                                         goto failed;
1875                                 }
1876                                 /* Save the wepflags state */
1877                                 result = hfa384x_drvr_getconfig16(hw,
1878                                                                   HFA384x_RID_CNFWEPFLAGS,
1879                                                                   &(hw->presniff_wepflags));
1880                                 if ( result ) {
1881                                         WLAN_LOG_DEBUG(1,"failed to read wepflags, result=%d\n", result);
1882                                         goto failed;
1883                                 }
1884                                 hfa384x_drvr_stop(hw);
1885                                 result = hfa384x_drvr_start(hw);
1886                                 if ( result ) {
1887                                         WLAN_LOG_DEBUG(1,
1888                                                        "failed to restart the card for sniffing, result=%d\n",
1889                                                        result);
1890                                         goto failed;
1891                                 }
1892                         } else {
1893                                 /* Disable the port */
1894                                 result = hfa384x_drvr_disable(hw, 0);
1895                                 if ( result ) {
1896                                         WLAN_LOG_DEBUG(1,
1897                                                        "failed to enable port for sniffing, result=%d\n",
1898                                                        result);
1899                                         goto failed;
1900                                 }
1901                         }
1902                 } else {
1903                         hw->presniff_port_type = 0;
1904                 }
1905
1906                 /* Set the channel we wish to sniff  */
1907                 word = msg->channel.data;
1908                 result = hfa384x_drvr_setconfig16(hw,
1909                                                   HFA384x_RID_CNFOWNCHANNEL, word);
1910                 hw->sniff_channel=word;
1911
1912                 if ( result ) {
1913                         WLAN_LOG_DEBUG(1,
1914                                        "failed to set channel %d, result=%d\n",
1915                                                word,
1916                                        result);
1917                         goto failed;
1918                 }
1919
1920                 /* Now if we're already sniffing, we can skip the rest */
1921                 if (wlandev->netdev->type != ARPHRD_ETHER) {
1922                         /* Set the port type to pIbss */
1923                         word = HFA384x_PORTTYPE_PSUEDOIBSS;
1924                         result = hfa384x_drvr_setconfig16(hw,
1925                                                           HFA384x_RID_CNFPORTTYPE, word);
1926                         if ( result ) {
1927                                 WLAN_LOG_DEBUG(1,
1928                                                "failed to set porttype %d, result=%d\n",
1929                                                word,
1930                                                result);
1931                                 goto failed;
1932                         }
1933                         if ((msg->keepwepflags.status == P80211ENUM_msgitem_status_data_ok) && (msg->keepwepflags.data != P80211ENUM_truth_true)) {
1934                                 /* Set the wepflags for no decryption */
1935                                 word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
1936                                         HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
1937                                 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFWEPFLAGS, word);
1938                         }
1939
1940                         if ( result ) {
1941                                 WLAN_LOG_DEBUG(1,
1942                                                "failed to set wepflags=0x%04x, result=%d\n",
1943                                                word,
1944                                                result);
1945                                 goto failed;
1946                         }
1947                 }
1948
1949                 /* Do we want to strip the FCS in monitor mode? */
1950                 if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok) && (msg->stripfcs.data == P80211ENUM_truth_true)) {
1951                         hw->sniff_fcs = 0;
1952                 } else {
1953                         hw->sniff_fcs = 1;
1954                 }
1955
1956                 /* Do we want to truncate the packets? */
1957                 if (msg->packet_trunc.status == P80211ENUM_msgitem_status_data_ok) {
1958                         hw->sniff_truncate = msg->packet_trunc.data;
1959                 } else {
1960                         hw->sniff_truncate = 0;
1961                 }
1962
1963                 /* Enable the port */
1964                 result = hfa384x_drvr_enable(hw, 0);
1965                 if ( result ) {
1966                         WLAN_LOG_DEBUG(1,
1967                         "failed to enable port for sniffing, result=%d\n",
1968                         result);
1969                         goto failed;
1970                 }
1971                 /* Enable monitor mode */
1972                 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
1973                 if ( result ) {
1974                         WLAN_LOG_DEBUG(1,
1975                         "failed to enable monitor mode, result=%d\n",
1976                         result);
1977                         goto failed;
1978                 }
1979
1980                 if (wlandev->netdev->type == ARPHRD_ETHER) {
1981                         WLAN_LOG_INFO("monitor mode enabled\n");
1982                 }
1983
1984                 /* Set the driver state */
1985                 /* Do we want the prism2 header? */
1986                 if ((msg->prismheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->prismheader.data == P80211ENUM_truth_true)) {
1987                         hw->sniffhdr = 0;
1988                         wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1989                 } else if ((msg->wlanheader.status == P80211ENUM_msgitem_status_data_ok) && (msg->wlanheader.data == P80211ENUM_truth_true)) {
1990                         hw->sniffhdr = 1;
1991                         wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1992                 } else {
1993                         wlandev->netdev->type = ARPHRD_IEEE80211;
1994                 }
1995
1996                 msg->resultcode.data = P80211ENUM_resultcode_success;
1997                 result = 0;
1998                 goto exit;
1999                 break;
2000         default:
2001                 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
2002                 result = 0;
2003                 goto exit;
2004                 break;
2005         }
2006
2007 failed:
2008         msg->resultcode.data = P80211ENUM_resultcode_refused;
2009         result = 0;
2010 exit:
2011
2012         DBFEXIT;
2013         return result;
2014 }