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