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