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(wlandevice_t *wlandev, void *msgp)
 117{
 118        int result = 0;
 119        hfa384x_t *hw = wlandev->priv;
 120        struct p80211msg_dot11req_scan *msg = msgp;
 121        u16 roamingmode, word;
 122        int i, timeout;
 123        int istmpenable = 0;
 124
 125        hfa384x_HostScanRequest_data_t 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(hfa384x_HostScanRequest_data_t));
 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(wlandevice_t *wlandev, void *msgp)
 370{
 371        int result = 0;
 372        struct p80211msg_dot11req_scan_results *req;
 373        hfa384x_t *hw = wlandev->priv;
 374        hfa384x_HScanResultSub_t *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(wlandevice_t *wlandev, void *msgp)
 529{
 530        int result = 0;
 531        hfa384x_t *hw = wlandev->priv;
 532        struct p80211msg_dot11req_start *msg = msgp;
 533
 534        p80211pstrd_t *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 = (p80211pstrd_t *) &(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        result = 0;
 689
 690        return result;
 691}
 692
 693/*----------------------------------------------------------------
 694* prism2mgmt_readpda
 695*
 696* Collect the PDA data and put it in the message.
 697*
 698* Arguments:
 699*       wlandev         wlan device structure
 700*       msgp            ptr to msg buffer
 701*
 702* Returns:
 703*       0       success and done
 704*       <0      success, but we're waiting for something to finish.
 705*       >0      an error occurred while handling the message.
 706* Side effects:
 707*
 708* Call context:
 709*       process thread  (usually)
 710----------------------------------------------------------------*/
 711int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp)
 712{
 713        hfa384x_t *hw = wlandev->priv;
 714        struct p80211msg_p2req_readpda *msg = msgp;
 715        int result;
 716
 717        /* We only support collecting the PDA when in the FWLOAD
 718         * state.
 719         */
 720        if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
 721                netdev_err(wlandev->netdev,
 722                           "PDA may only be read in the fwload state.\n");
 723                msg->resultcode.data =
 724                    P80211ENUM_resultcode_implementation_failure;
 725                msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
 726        } else {
 727                /*  Call drvr_readpda(), it handles the auxport enable
 728                 *  and validating the returned PDA.
 729                 */
 730                result = hfa384x_drvr_readpda(hw,
 731                                              msg->pda.data,
 732                                              HFA384x_PDA_LEN_MAX);
 733                if (result) {
 734                        netdev_err(wlandev->netdev,
 735                                   "hfa384x_drvr_readpda() failed, result=%d\n",
 736                                   result);
 737
 738                        msg->resultcode.data =
 739                            P80211ENUM_resultcode_implementation_failure;
 740                        msg->resultcode.status =
 741                            P80211ENUM_msgitem_status_data_ok;
 742                        return 0;
 743                }
 744                msg->pda.status = P80211ENUM_msgitem_status_data_ok;
 745                msg->resultcode.data = P80211ENUM_resultcode_success;
 746                msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
 747        }
 748
 749        return 0;
 750}
 751
 752/*----------------------------------------------------------------
 753* prism2mgmt_ramdl_state
 754*
 755* Establishes the beginning/end of a card RAM download session.
 756*
 757* It is expected that the ramdl_write() function will be called
 758* one or more times between the 'enable' and 'disable' calls to
 759* this function.
 760*
 761* Note: This function should not be called when a mac comm port
 762*       is active.
 763*
 764* Arguments:
 765*       wlandev         wlan device structure
 766*       msgp            ptr to msg buffer
 767*
 768* Returns:
 769*       0       success and done
 770*       <0      success, but we're waiting for something to finish.
 771*       >0      an error occurred while handling the message.
 772* Side effects:
 773*
 774* Call context:
 775*       process thread  (usually)
 776----------------------------------------------------------------*/
 777int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp)
 778{
 779        hfa384x_t *hw = wlandev->priv;
 780        struct p80211msg_p2req_ramdl_state *msg = msgp;
 781
 782        if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
 783                netdev_err(wlandev->netdev,
 784                           "ramdl_state(): may only be called in the fwload state.\n");
 785                msg->resultcode.data =
 786                    P80211ENUM_resultcode_implementation_failure;
 787                msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
 788                return 0;
 789        }
 790
 791        /*
 792         ** Note: Interrupts are locked out if this is an AP and are NOT
 793         ** locked out if this is a station.
 794         */
 795
 796        msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
 797        if (msg->enable.data == P80211ENUM_truth_true) {
 798                if (hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data)) {
 799                        msg->resultcode.data =
 800                            P80211ENUM_resultcode_implementation_failure;
 801                } else {
 802                        msg->resultcode.data = P80211ENUM_resultcode_success;
 803                }
 804        } else {
 805                hfa384x_drvr_ramdl_disable(hw);
 806                msg->resultcode.data = P80211ENUM_resultcode_success;
 807        }
 808
 809        return 0;
 810}
 811
 812/*----------------------------------------------------------------
 813* prism2mgmt_ramdl_write
 814*
 815* Writes a buffer to the card RAM using the download state.  This
 816* is for writing code to card RAM.  To just read or write raw data
 817* use the aux functions.
 818*
 819* Arguments:
 820*       wlandev         wlan device structure
 821*       msgp            ptr to msg buffer
 822*
 823* Returns:
 824*       0       success and done
 825*       <0      success, but we're waiting for something to finish.
 826*       >0      an error occurred while handling the message.
 827* Side effects:
 828*
 829* Call context:
 830*       process thread  (usually)
 831----------------------------------------------------------------*/
 832int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp)
 833{
 834        hfa384x_t *hw = wlandev->priv;
 835        struct p80211msg_p2req_ramdl_write *msg = msgp;
 836        u32 addr;
 837        u32 len;
 838        u8 *buf;
 839
 840        if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
 841                netdev_err(wlandev->netdev,
 842                           "ramdl_write(): may only be called in the fwload state.\n");
 843                msg->resultcode.data =
 844                    P80211ENUM_resultcode_implementation_failure;
 845                msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
 846                return 0;
 847        }
 848
 849        msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
 850        /* first validate the length */
 851        if (msg->len.data > sizeof(msg->data.data)) {
 852                msg->resultcode.status =
 853                    P80211ENUM_resultcode_invalid_parameters;
 854                return 0;
 855        }
 856        /* call the hfa384x function to do the write */
 857        addr = msg->addr.data;
 858        len = msg->len.data;
 859        buf = msg->data.data;
 860        if (hfa384x_drvr_ramdl_write(hw, addr, buf, len))
 861                msg->resultcode.data = P80211ENUM_resultcode_refused;
 862
 863        msg->resultcode.data = P80211ENUM_resultcode_success;
 864
 865        return 0;
 866}
 867
 868/*----------------------------------------------------------------
 869* prism2mgmt_flashdl_state
 870*
 871* Establishes the beginning/end of a card Flash download session.
 872*
 873* It is expected that the flashdl_write() function will be called
 874* one or more times between the 'enable' and 'disable' calls to
 875* this function.
 876*
 877* Note: This function should not be called when a mac comm port
 878*       is active.
 879*
 880* Arguments:
 881*       wlandev         wlan device structure
 882*       msgp            ptr to msg buffer
 883*
 884* Returns:
 885*       0       success and done
 886*       <0      success, but we're waiting for something to finish.
 887*       >0      an error occurred while handling the message.
 888* Side effects:
 889*
 890* Call context:
 891*       process thread  (usually)
 892----------------------------------------------------------------*/
 893int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
 894{
 895        int result = 0;
 896        hfa384x_t *hw = wlandev->priv;
 897        struct p80211msg_p2req_flashdl_state *msg = msgp;
 898
 899        if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
 900                netdev_err(wlandev->netdev,
 901                           "flashdl_state(): may only be called in the fwload state.\n");
 902                msg->resultcode.data =
 903                    P80211ENUM_resultcode_implementation_failure;
 904                msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
 905                return 0;
 906        }
 907
 908        /*
 909         ** Note: Interrupts are locked out if this is an AP and are NOT
 910         ** locked out if this is a station.
 911         */
 912
 913        msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
 914        if (msg->enable.data == P80211ENUM_truth_true) {
 915                if (hfa384x_drvr_flashdl_enable(hw)) {
 916                        msg->resultcode.data =
 917                            P80211ENUM_resultcode_implementation_failure;
 918                } else {
 919                        msg->resultcode.data = P80211ENUM_resultcode_success;
 920                }
 921        } else {
 922                hfa384x_drvr_flashdl_disable(hw);
 923                msg->resultcode.data = P80211ENUM_resultcode_success;
 924                /* NOTE: At this point, the MAC is in the post-reset
 925                 * state and the driver is in the fwload state.
 926                 * We need to get the MAC back into the fwload
 927                 * state.  To do this, we set the nsdstate to HWPRESENT
 928                 * and then call the ifstate function to redo everything
 929                 * that got us into the fwload state.
 930                 */
 931                wlandev->msdstate = WLAN_MSD_HWPRESENT;
 932                result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
 933                if (result != P80211ENUM_resultcode_success) {
 934                        netdev_err(wlandev->netdev,
 935                                   "prism2sta_ifstate(fwload) failed, P80211ENUM_resultcode=%d\n",
 936                                   result);
 937                        msg->resultcode.data =
 938                            P80211ENUM_resultcode_implementation_failure;
 939                        result = -1;
 940                }
 941        }
 942
 943        return 0;
 944}
 945
 946/*----------------------------------------------------------------
 947* prism2mgmt_flashdl_write
 948*
 949*
 950*
 951* Arguments:
 952*       wlandev         wlan device structure
 953*       msgp            ptr to msg buffer
 954*
 955* Returns:
 956*       0       success and done
 957*       <0      success, but we're waiting for something to finish.
 958*       >0      an error occurred while handling the message.
 959* Side effects:
 960*
 961* Call context:
 962*       process thread  (usually)
 963----------------------------------------------------------------*/
 964int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp)
 965{
 966        hfa384x_t *hw = wlandev->priv;
 967        struct p80211msg_p2req_flashdl_write *msg = msgp;
 968        u32 addr;
 969        u32 len;
 970        u8 *buf;
 971
 972        if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
 973                netdev_err(wlandev->netdev,
 974                           "flashdl_write(): may only be called in the fwload state.\n");
 975                msg->resultcode.data =
 976                    P80211ENUM_resultcode_implementation_failure;
 977                msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
 978                return 0;
 979        }
 980
 981        /*
 982         ** Note: Interrupts are locked out if this is an AP and are NOT
 983         ** locked out if this is a station.
 984         */
 985
 986        msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
 987        /* first validate the length */
 988        if (msg->len.data > sizeof(msg->data.data)) {
 989                msg->resultcode.status =
 990                    P80211ENUM_resultcode_invalid_parameters;
 991                return 0;
 992        }
 993        /* call the hfa384x function to do the write */
 994        addr = msg->addr.data;
 995        len = msg->len.data;
 996        buf = msg->data.data;
 997        if (hfa384x_drvr_flashdl_write(hw, addr, buf, len))
 998                msg->resultcode.data = P80211ENUM_resultcode_refused;
 999
1000        msg->resultcode.data = P80211ENUM_resultcode_success;
1001
1002        return 0;
1003}
1004
1005/*----------------------------------------------------------------
1006* prism2mgmt_autojoin
1007*
1008* Associate with an ESS.
1009*
1010* Arguments:
1011*       wlandev         wlan device structure
1012*       msgp            ptr to msg buffer
1013*
1014* Returns:
1015*       0       success and done
1016*       <0      success, but we're waiting for something to finish.
1017*       >0      an error occurred while handling the message.
1018* Side effects:
1019*
1020* Call context:
1021*       process thread  (usually)
1022*       interrupt
1023----------------------------------------------------------------*/
1024int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
1025{
1026        hfa384x_t *hw = wlandev->priv;
1027        int result = 0;
1028        u16 reg;
1029        u16 port_type;
1030        struct p80211msg_lnxreq_autojoin *msg = msgp;
1031        p80211pstrd_t *pstr;
1032        u8 bytebuf[256];
1033        struct hfa384x_bytestr *p2bytestr = (struct hfa384x_bytestr *) bytebuf;
1034
1035        wlandev->macmode = WLAN_MACMODE_NONE;
1036
1037        /* Set the SSID */
1038        memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
1039
1040        /* Disable the Port */
1041        hfa384x_drvr_disable(hw, 0);
1042
1043        /*** STATION ***/
1044        /* Set the TxRates */
1045        hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
1046
1047        /* Set the auth type */
1048        if (msg->authtype.data == P80211ENUM_authalg_sharedkey)
1049                reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
1050        else
1051                reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
1052
1053        hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
1054
1055        /* Set the ssid */
1056        memset(bytebuf, 0, 256);
1057        pstr = (p80211pstrd_t *) &(msg->ssid.data);
1058        prism2mgmt_pstr2bytestr(p2bytestr, pstr);
1059        result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
1060                                        bytebuf,
1061                                        HFA384x_RID_CNFDESIREDSSID_LEN);
1062        port_type = HFA384x_PORTTYPE_BSS;
1063        /* Set the PortType */
1064        hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
1065
1066        /* Enable the Port */
1067        hfa384x_drvr_enable(hw, 0);
1068
1069        /* Set the resultcode */
1070        msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1071        msg->resultcode.data = P80211ENUM_resultcode_success;
1072
1073        return result;
1074}
1075
1076/*----------------------------------------------------------------
1077* prism2mgmt_wlansniff
1078*
1079* Start or stop sniffing.
1080*
1081* Arguments:
1082*       wlandev         wlan device structure
1083*       msgp            ptr to msg buffer
1084*
1085* Returns:
1086*       0       success and done
1087*       <0      success, but we're waiting for something to finish.
1088*       >0      an error occurred while handling the message.
1089* Side effects:
1090*
1091* Call context:
1092*       process thread  (usually)
1093*       interrupt
1094----------------------------------------------------------------*/
1095int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
1096{
1097        int result = 0;
1098        struct p80211msg_lnxreq_wlansniff *msg = msgp;
1099
1100        hfa384x_t *hw = wlandev->priv;
1101        u16 word;
1102
1103        msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
1104        switch (msg->enable.data) {
1105        case P80211ENUM_truth_false:
1106                /* Confirm that we're in monitor mode */
1107                if (wlandev->netdev->type == ARPHRD_ETHER) {
1108                        msg->resultcode.data =
1109                            P80211ENUM_resultcode_invalid_parameters;
1110                        return 0;
1111                }
1112                /* Disable monitor mode */
1113                result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
1114                if (result) {
1115                        pr_debug("failed to disable monitor mode, result=%d\n",
1116                                 result);
1117                        goto failed;
1118                }
1119                /* Disable port 0 */
1120                result = hfa384x_drvr_disable(hw, 0);
1121                if (result) {
1122                        pr_debug
1123                        ("failed to disable port 0 after sniffing, result=%d\n",
1124                             result);
1125                        goto failed;
1126                }
1127                /* Clear the driver state */
1128                wlandev->netdev->type = ARPHRD_ETHER;
1129
1130                /* Restore the wepflags */
1131                result = hfa384x_drvr_setconfig16(hw,
1132                                                  HFA384x_RID_CNFWEPFLAGS,
1133                                                  hw->presniff_wepflags);
1134                if (result) {
1135                        pr_debug
1136                            ("failed to restore wepflags=0x%04x, result=%d\n",
1137                             hw->presniff_wepflags, result);
1138                        goto failed;
1139                }
1140
1141                /* Set the port to its prior type and enable (if necessary) */
1142                if (hw->presniff_port_type != 0) {
1143                        word = hw->presniff_port_type;
1144                        result = hfa384x_drvr_setconfig16(hw,
1145                                                  HFA384x_RID_CNFPORTTYPE,
1146                                                  word);
1147                        if (result) {
1148                                pr_debug
1149                                    ("failed to restore porttype, result=%d\n",
1150                                     result);
1151                                goto failed;
1152                        }
1153
1154                        /* Enable the port */
1155                        result = hfa384x_drvr_enable(hw, 0);
1156                        if (result) {
1157                                pr_debug("failed to enable port to presniff setting, result=%d\n",
1158                                         result);
1159                                goto failed;
1160                        }
1161                } else {
1162                        result = hfa384x_drvr_disable(hw, 0);
1163
1164                }
1165
1166                netdev_info(wlandev->netdev, "monitor mode disabled\n");
1167                msg->resultcode.data = P80211ENUM_resultcode_success;
1168                return 0;
1169        case P80211ENUM_truth_true:
1170                /* Disable the port (if enabled), only check Port 0 */
1171                if (hw->port_enabled[0]) {
1172                        if (wlandev->netdev->type == ARPHRD_ETHER) {
1173                                /* Save macport 0 state */
1174                                result = hfa384x_drvr_getconfig16(hw,
1175                                                  HFA384x_RID_CNFPORTTYPE,
1176                                                  &(hw->presniff_port_type));
1177                                if (result) {
1178                                        pr_debug
1179                                        ("failed to read porttype, result=%d\n",
1180                                             result);
1181                                        goto failed;
1182                                }
1183                                /* Save the wepflags state */
1184                                result = hfa384x_drvr_getconfig16(hw,
1185                                                  HFA384x_RID_CNFWEPFLAGS,
1186                                                  &(hw->presniff_wepflags));
1187                                if (result) {
1188                                        pr_debug
1189                                        ("failed to read wepflags, result=%d\n",
1190                                             result);
1191                                        goto failed;
1192                                }
1193                                hfa384x_drvr_stop(hw);
1194                                result = hfa384x_drvr_start(hw);
1195                                if (result) {
1196                                        pr_debug("failed to restart the card for sniffing, result=%d\n",
1197                                                 result);
1198                                        goto failed;
1199                                }
1200                        } else {
1201                                /* Disable the port */
1202                                result = hfa384x_drvr_disable(hw, 0);
1203                                if (result) {
1204                                        pr_debug("failed to enable port for sniffing, result=%d\n",
1205                                                 result);
1206                                        goto failed;
1207                                }
1208                        }
1209                } else {
1210                        hw->presniff_port_type = 0;
1211                }
1212
1213                /* Set the channel we wish to sniff  */
1214                word = msg->channel.data;
1215                result = hfa384x_drvr_setconfig16(hw,
1216                                                  HFA384x_RID_CNFOWNCHANNEL,
1217                                                  word);
1218                hw->sniff_channel = word;
1219
1220                if (result) {
1221                        pr_debug("failed to set channel %d, result=%d\n",
1222                                 word, result);
1223                        goto failed;
1224                }
1225
1226                /* Now if we're already sniffing, we can skip the rest */
1227                if (wlandev->netdev->type != ARPHRD_ETHER) {
1228                        /* Set the port type to pIbss */
1229                        word = HFA384x_PORTTYPE_PSUEDOIBSS;
1230                        result = hfa384x_drvr_setconfig16(hw,
1231                                                  HFA384x_RID_CNFPORTTYPE,
1232                                                  word);
1233                        if (result) {
1234                                pr_debug
1235                                    ("failed to set porttype %d, result=%d\n",
1236                                     word, result);
1237                                goto failed;
1238                        }
1239                        if ((msg->keepwepflags.status ==
1240                             P80211ENUM_msgitem_status_data_ok)
1241                            && (msg->keepwepflags.data !=
1242                                P80211ENUM_truth_true)) {
1243                                /* Set the wepflags for no decryption */
1244                                word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
1245                                    HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
1246                                result =
1247                                    hfa384x_drvr_setconfig16(hw,
1248                                                     HFA384x_RID_CNFWEPFLAGS,
1249                                                     word);
1250                        }
1251
1252                        if (result) {
1253                                pr_debug
1254                                  ("failed to set wepflags=0x%04x, result=%d\n",
1255                                   word, result);
1256                                goto failed;
1257                        }
1258                }
1259
1260                /* Do we want to strip the FCS in monitor mode? */
1261                if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok)
1262                    && (msg->stripfcs.data == P80211ENUM_truth_true)) {
1263                        hw->sniff_fcs = 0;
1264                } else {
1265                        hw->sniff_fcs = 1;
1266                }
1267
1268                /* Do we want to truncate the packets? */
1269                if (msg->packet_trunc.status ==
1270                    P80211ENUM_msgitem_status_data_ok) {
1271                        hw->sniff_truncate = msg->packet_trunc.data;
1272                } else {
1273                        hw->sniff_truncate = 0;
1274                }
1275
1276                /* Enable the port */
1277                result = hfa384x_drvr_enable(hw, 0);
1278                if (result) {
1279                        pr_debug
1280                            ("failed to enable port for sniffing, result=%d\n",
1281                             result);
1282                        goto failed;
1283                }
1284                /* Enable monitor mode */
1285                result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
1286                if (result) {
1287                        pr_debug("failed to enable monitor mode, result=%d\n",
1288                                 result);
1289                        goto failed;
1290                }
1291
1292                if (wlandev->netdev->type == ARPHRD_ETHER)
1293                        netdev_info(wlandev->netdev, "monitor mode enabled\n");
1294
1295                /* Set the driver state */
1296                /* Do we want the prism2 header? */
1297                if ((msg->prismheader.status ==
1298                     P80211ENUM_msgitem_status_data_ok)
1299                    && (msg->prismheader.data == P80211ENUM_truth_true)) {
1300                        hw->sniffhdr = 0;
1301                        wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1302                } else
1303                    if ((msg->wlanheader.status ==
1304                         P80211ENUM_msgitem_status_data_ok)
1305                        && (msg->wlanheader.data == P80211ENUM_truth_true)) {
1306                        hw->sniffhdr = 1;
1307                        wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1308                } else {
1309                        wlandev->netdev->type = ARPHRD_IEEE80211;
1310                }
1311
1312                msg->resultcode.data = P80211ENUM_resultcode_success;
1313                return 0;
1314        default:
1315                msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
1316                return 0;
1317        }
1318
1319failed:
1320        msg->resultcode.data = P80211ENUM_resultcode_refused;
1321        return 0;
1322}
1323