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