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