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