linux/drivers/staging/wlags49_h2/wl_priv.c
<<
>>
Prefs
   1/*******************************************************************************
   2 * Agere Systems Inc.
   3 * Wireless device driver for Linux (wlags49).
   4 *
   5 * Copyright (c) 1998-2003 Agere Systems Inc.
   6 * All rights reserved.
   7 *   http://www.agere.com
   8 *
   9 * Initially developed by TriplePoint, Inc.
  10 *   http://www.triplepoint.com
  11 *
  12 *------------------------------------------------------------------------------
  13 *
  14 *   This file defines handling routines for the private IOCTLs
  15 *
  16 *------------------------------------------------------------------------------
  17 *
  18 * SOFTWARE LICENSE
  19 *
  20 * This software is provided subject to the following terms and conditions,
  21 * which you should read carefully before using the software.  Using this
  22 * software indicates your acceptance of these terms and conditions.  If you do
  23 * not agree with these terms and conditions, do not use the software.
  24 *
  25 * Copyright © 2003 Agere Systems Inc.
  26 * All rights reserved.
  27 *
  28 * Redistribution and use in source or binary forms, with or without
  29 * modifications, are permitted provided that the following conditions are met:
  30 *
  31 * . Redistributions of source code must retain the above copyright notice, this
  32 *    list of conditions and the following Disclaimer as comments in the code as
  33 *    well as in the documentation and/or other materials provided with the
  34 *    distribution.
  35 *
  36 * . Redistributions in binary form must reproduce the above copyright notice,
  37 *    this list of conditions and the following Disclaimer in the documentation
  38 *    and/or other materials provided with the distribution.
  39 *
  40 * . Neither the name of Agere Systems Inc. nor the names of the contributors
  41 *    may be used to endorse or promote products derived from this software
  42 *    without specific prior written permission.
  43 *
  44 * Disclaimer
  45 *
  46 * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
  47 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
  48 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
  49 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
  50 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
  51 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  52 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  53 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  54 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
  55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  56 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  57 * DAMAGE.
  58 *
  59 ******************************************************************************/
  60
  61/*******************************************************************************
  62 * include files
  63 ******************************************************************************/
  64#include <wl_version.h>
  65
  66#include <linux/if_arp.h>
  67#include <linux/ioport.h>
  68#include <linux/slab.h>
  69#include <linux/delay.h>
  70#include <linux/uaccess.h>
  71
  72#include <debug.h>
  73#include <hcf.h>
  74#include <hcfdef.h>
  75
  76#include <wl_if.h>
  77#include <wl_internal.h>
  78#include <wl_enc.h>
  79#include <wl_main.h>
  80#include <wl_priv.h>
  81#include <wl_util.h>
  82#include <wl_netdev.h>
  83
  84int wvlan_uil_connect(struct uilreq *urq, struct wl_private *lp);
  85int wvlan_uil_disconnect(struct uilreq *urq, struct wl_private *lp);
  86int wvlan_uil_action(struct uilreq *urq, struct wl_private *lp);
  87int wvlan_uil_block(struct uilreq *urq, struct wl_private *lp);
  88int wvlan_uil_unblock(struct uilreq *urq, struct wl_private *lp);
  89int wvlan_uil_send_diag_msg(struct uilreq *urq, struct wl_private *lp);
  90int wvlan_uil_put_info(struct uilreq *urq, struct wl_private *lp);
  91int wvlan_uil_get_info(struct uilreq *urq, struct wl_private *lp);
  92
  93int cfg_driver_info(struct uilreq *urq, struct wl_private *lp);
  94int cfg_driver_identity(struct uilreq *urq, struct wl_private *lp);
  95
  96
  97/*******************************************************************************
  98 * global variables
  99 ******************************************************************************/
 100#if DBG
 101extern dbg_info_t *DbgInfo;
 102#endif  /* DBG */
 103
 104
 105
 106
 107/* If USE_UIL is not defined, then none of the UIL Interface code below will
 108   be included in the build */
 109#ifdef USE_UIL
 110
 111/*******************************************************************************
 112 *      wvlan_uil()
 113 *******************************************************************************
 114 *
 115 *  DESCRIPTION:
 116 *
 117 *      The handler function for the UIL interface.
 118 *
 119 *  PARAMETERS:
 120 *
 121 *      urq - a pointer to the UIL request buffer
 122 *      lp  - a pointer to the device's private adapter structure
 123 *
 124 *  RETURNS:
 125 *
 126 *      0 on success
 127 *      errno value otherwise
 128 *
 129 ******************************************************************************/
 130int wvlan_uil(struct uilreq *urq, struct wl_private *lp)
 131{
 132        int ioctl_ret = 0;
 133        /*------------------------------------------------------------------------*/
 134
 135        DBG_FUNC("wvlan_uil");
 136        DBG_ENTER(DbgInfo);
 137
 138        switch (urq->command) {
 139        case UIL_FUN_CONNECT:
 140                DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_CONNECT\n");
 141                ioctl_ret = wvlan_uil_connect(urq, lp);
 142                break;
 143        case UIL_FUN_DISCONNECT:
 144                DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_DISCONNECT\n");
 145                ioctl_ret = wvlan_uil_disconnect(urq, lp);
 146                break;
 147        case UIL_FUN_ACTION:
 148                DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_ACTION\n");
 149                ioctl_ret = wvlan_uil_action(urq, lp);
 150                break;
 151        case UIL_FUN_SEND_DIAG_MSG:
 152                DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_SEND_DIAG_MSG\n");
 153                ioctl_ret = wvlan_uil_send_diag_msg(urq, lp);
 154                break;
 155        case UIL_FUN_GET_INFO:
 156                DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_GET_INFO\n");
 157                ioctl_ret = wvlan_uil_get_info(urq, lp);
 158                break;
 159        case UIL_FUN_PUT_INFO:
 160                DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_PUT_INFO\n");
 161                ioctl_ret = wvlan_uil_put_info(urq, lp);
 162                break;
 163        default:
 164                DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- UNSUPPORTED UIL CODE: 0x%X", urq->command);
 165                ioctl_ret = -EOPNOTSUPP;
 166                break;
 167        }
 168        DBG_LEAVE(DbgInfo);
 169        return ioctl_ret;
 170} /* wvlan_uil */
 171/*============================================================================*/
 172
 173
 174
 175
 176/*******************************************************************************
 177 *      wvlan_uil_connect()
 178 *******************************************************************************
 179 *
 180 *  DESCRIPTION:
 181 *
 182 *      Connect to the UIL in order to make a request.
 183 *
 184 *  PARAMETERS:
 185 *
 186 *      urq - a pointer to the UIL request buffer
 187 *      lp  - a pointer to the device's private adapter structure
 188 *
 189 *  RETURNS:
 190 *
 191 *      UIL_SUCCESS
 192 *      UIL_ERR_xxx value otherwise
 193 *
 194 ******************************************************************************/
 195int wvlan_uil_connect(struct uilreq *urq, struct wl_private *lp)
 196{
 197        int result = 0;
 198        /*------------------------------------------------------------------------*/
 199
 200
 201        DBG_FUNC("wvlan_uil_connect");
 202        DBG_ENTER(DbgInfo);
 203
 204
 205        if (!(lp->flags & WVLAN2_UIL_CONNECTED)) {
 206                lp->flags |= WVLAN2_UIL_CONNECTED;
 207                urq->hcfCtx = &(lp->hcfCtx);
 208                urq->result = UIL_SUCCESS;
 209        } else {
 210                DBG_WARNING(DbgInfo, "UIL_ERR_IN_USE\n");
 211                urq->result = UIL_ERR_IN_USE;
 212        }
 213
 214        DBG_LEAVE(DbgInfo);
 215        return result;
 216} /* wvlan_uil_connect */
 217/*============================================================================*/
 218
 219
 220
 221
 222/*******************************************************************************
 223 *      wvlan_uil_disconnect()
 224 *******************************************************************************
 225 *
 226 *  DESCRIPTION:
 227 *
 228 *      Disconnect from the UIL after a request has been completed.
 229 *
 230 *  PARAMETERS:
 231 *
 232 *      urq - a pointer to the UIL request buffer
 233 *      lp  - a pointer to the device's private adapter structure
 234 *
 235 *  RETURNS:
 236 *
 237 *      UIL_SUCCESS
 238 *      UIL_ERR_xxx value otherwise
 239 *
 240 ******************************************************************************/
 241int wvlan_uil_disconnect(struct uilreq *urq, struct wl_private *lp)
 242{
 243        int result = 0;
 244        /*------------------------------------------------------------------------*/
 245
 246
 247        DBG_FUNC("wvlan_uil_disconnect");
 248        DBG_ENTER(DbgInfo);
 249
 250
 251        if (urq->hcfCtx == &(lp->hcfCtx)) {
 252                if (lp->flags & WVLAN2_UIL_CONNECTED) {
 253                        lp->flags &= ~WVLAN2_UIL_CONNECTED;
 254                        /*
 255                        if (lp->flags & WVLAN2_UIL_BUSY) {
 256                                lp->flags &= ~WVLAN2_UIL_BUSY;
 257                                netif_start_queue(lp->dev);
 258                        }
 259                        */
 260                }
 261
 262                urq->hcfCtx = NULL;
 263                urq->result = UIL_SUCCESS;
 264        } else {
 265                DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
 266                urq->result = UIL_ERR_WRONG_IFB;
 267        }
 268
 269        DBG_LEAVE(DbgInfo);
 270        return result;
 271} /* wvlan_uil_disconnect */
 272/*============================================================================*/
 273
 274
 275
 276
 277/*******************************************************************************
 278 *      wvlan_uil_action()
 279 *******************************************************************************
 280 *
 281 *  DESCRIPTION:
 282 *
 283 *      Handler for the UIL_ACT_xxx subcodes associated with UIL_FUN_ACTION
 284 *
 285 *  PARAMETERS:
 286 *
 287 *      urq - a pointer to the UIL request buffer
 288 *      lp  - a pointer to the device's private adapter structure
 289 *
 290 *  RETURNS:
 291 *
 292 *      UIL_SUCCESS
 293 *      UIL_ERR_xxx value otherwise
 294 *
 295 ******************************************************************************/
 296int wvlan_uil_action(struct uilreq *urq, struct wl_private *lp)
 297{
 298        int     result = 0;
 299        ltv_t   *ltv;
 300        /*------------------------------------------------------------------------*/
 301
 302
 303        DBG_FUNC("wvlan_uil_action");
 304        DBG_ENTER(DbgInfo);
 305
 306
 307        if (urq->hcfCtx == &(lp->hcfCtx)) {
 308                /* Make sure there's an LTV in the request buffer */
 309                ltv = (ltv_t *)urq->data;
 310                if (ltv != NULL) {
 311                        /* Switch on the Type field of the LTV contained in the request
 312                           buffer */
 313                        switch (ltv->typ) {
 314                        case UIL_ACT_BLOCK:
 315                                DBG_TRACE(DbgInfo, "UIL_ACT_BLOCK\n");
 316                                result = wvlan_uil_block(urq, lp);
 317                                break;
 318                        case UIL_ACT_UNBLOCK:
 319                                DBG_TRACE(DbgInfo, "UIL_ACT_UNBLOCK\n");
 320                                result = wvlan_uil_unblock(urq, lp);
 321                                break;
 322                        case UIL_ACT_SCAN:
 323                                DBG_TRACE(DbgInfo, "UIL_ACT_SCAN\n");
 324                                urq->result = hcf_action(&(lp->hcfCtx), MDD_ACT_SCAN);
 325                                break;
 326                        case UIL_ACT_APPLY:
 327                                DBG_TRACE(DbgInfo, "UIL_ACT_APPLY\n");
 328                                urq->result = wl_apply(lp);
 329                                break;
 330                        case UIL_ACT_RESET:
 331                                DBG_TRACE(DbgInfo, "UIL_ACT_RESET\n");
 332                                urq->result = wl_go(lp);
 333                                break;
 334                        default:
 335                                DBG_WARNING(DbgInfo, "Unknown action code: 0x%x\n", ltv->typ);
 336                                break;
 337                        }
 338                } else {
 339                        DBG_ERROR(DbgInfo, "Bad LTV for this action\n");
 340                        urq->result = UIL_ERR_LEN;
 341                }
 342        } else {
 343                DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
 344                urq->result = UIL_ERR_WRONG_IFB;
 345        }
 346
 347        DBG_LEAVE(DbgInfo);
 348        return result;
 349} /* wvlan_uil_action */
 350/*============================================================================*/
 351
 352
 353
 354
 355/*******************************************************************************
 356 *      wvlan_uil_block()
 357 *******************************************************************************
 358 *
 359 *  DESCRIPTION:
 360 *
 361 *      Sets a block in the driver to prevent access to the card by other
 362 *  processes.
 363 *
 364 *  PARAMETERS:
 365 *
 366 *      urq - a pointer to the UIL request buffer
 367 *      lp  - a pointer to the device's private adapter structure
 368 *
 369 *  RETURNS:
 370 *
 371 *      UIL_SUCCESS
 372 *      UIL_ERR_xxx value otherwise
 373 *
 374 ******************************************************************************/
 375
 376int wvlan_uil_block(struct uilreq *urq, struct wl_private *lp)
 377{
 378        int result = 0;
 379        /*------------------------------------------------------------------------*/
 380
 381
 382        DBG_FUNC("wvlan_uil_block");
 383        DBG_ENTER(DbgInfo);
 384
 385        if (urq->hcfCtx == &(lp->hcfCtx)) {
 386                if (capable(CAP_NET_ADMIN)) {
 387                        lp->flags |= WVLAN2_UIL_BUSY;
 388                        netif_stop_queue(lp->dev);
 389                        WL_WDS_NETIF_STOP_QUEUE(lp);
 390                        urq->result = UIL_SUCCESS;
 391                } else {
 392                        DBG_ERROR(DbgInfo, "EPERM\n");
 393                        urq->result = UIL_FAILURE;
 394                        result = -EPERM;
 395                }
 396        } else {
 397                DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
 398                urq->result = UIL_ERR_WRONG_IFB;
 399        }
 400
 401        DBG_LEAVE(DbgInfo);
 402        return result;
 403} /* wvlan_uil_block */
 404/*============================================================================*/
 405
 406
 407
 408
 409/*******************************************************************************
 410 *      wvlan_uil_unblock()
 411 *******************************************************************************
 412 *
 413 *  DESCRIPTION:
 414 *
 415 *      Unblocks the driver to restore access to the card by other processes.
 416 *
 417 *  PARAMETERS:
 418 *
 419 *      urq - a pointer to the UIL request buffer
 420 *      lp  - a pointer to the device's private adapter structure
 421 *
 422 *  RETURNS:
 423 *
 424 *      UIL_SUCCESS
 425 *      UIL_ERR_xxx value otherwise
 426 *
 427 ******************************************************************************/
 428int wvlan_uil_unblock(struct uilreq *urq, struct wl_private *lp)
 429{
 430        int result = 0;
 431        /*------------------------------------------------------------------------*/
 432
 433
 434        DBG_FUNC("wvlan_uil_unblock");
 435        DBG_ENTER(DbgInfo);
 436
 437        if (urq->hcfCtx == &(lp->hcfCtx)) {
 438                if (capable(CAP_NET_ADMIN)) {
 439                        if (lp->flags & WVLAN2_UIL_BUSY) {
 440                                lp->flags &= ~WVLAN2_UIL_BUSY;
 441                                netif_wake_queue(lp->dev);
 442                                WL_WDS_NETIF_WAKE_QUEUE(lp);
 443                        }
 444                } else {
 445                        DBG_ERROR(DbgInfo, "EPERM\n");
 446                        urq->result = UIL_FAILURE;
 447                        result = -EPERM;
 448                }
 449        } else {
 450                DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
 451                urq->result = UIL_ERR_WRONG_IFB;
 452        }
 453
 454        DBG_LEAVE(DbgInfo);
 455        return result;
 456} /* wvlan_uil_unblock */
 457/*============================================================================*/
 458
 459
 460
 461
 462/*******************************************************************************
 463 *      wvlan_uil_send_diag_msg()
 464 *******************************************************************************
 465 *
 466 *  DESCRIPTION:
 467 *
 468 *      Sends a diagnostic message to the card.
 469 *
 470 *  PARAMETERS:
 471 *
 472 *      urq - a pointer to the UIL request buffer
 473 *      lp  - a pointer to the device's private adapter structure
 474 *
 475 *  RETURNS:
 476 *
 477 *      UIL_SUCCESS
 478 *      UIL_ERR_xxx value otherwise
 479 *
 480 ******************************************************************************/
 481int wvlan_uil_send_diag_msg(struct uilreq *urq, struct wl_private *lp)
 482{
 483        int         result = 0;
 484        DESC_STRCT  Descp[1];
 485        /*------------------------------------------------------------------------*/
 486
 487
 488        DBG_FUNC("wvlan_uil_send_diag_msg");
 489        DBG_ENTER(DbgInfo);
 490
 491        if (urq->hcfCtx == &(lp->hcfCtx)) {
 492                if (capable(CAP_NET_ADMIN)) {
 493                        if ((urq->data != NULL) && (urq->len != 0)) {
 494                                if (lp->hcfCtx.IFB_RscInd != 0) {
 495                                        u_char *data;
 496
 497                                        /* Verify the user buffer */
 498                                        result = verify_area(VERIFY_READ, urq->data, urq->len);
 499                                        if (result != 0) {
 500                                                DBG_ERROR(DbgInfo, "verify_area failed, result: %d\n", result);
 501                                                urq->result = UIL_FAILURE;
 502                                                DBG_LEAVE(DbgInfo);
 503                                                return result;
 504                                        }
 505
 506                                        data = kmalloc(urq->len, GFP_KERNEL);
 507                                        if (data != NULL) {
 508                                                memset(Descp, 0, sizeof(DESC_STRCT));
 509                                                memcpy(data, urq->data, urq->len);
 510
 511                                                Descp[0].buf_addr       = (wci_bufp)data;
 512                                                Descp[0].BUF_CNT        = urq->len;
 513                                                Descp[0].next_desc_addr = 0;    /* terminate list */
 514
 515                                                hcf_send_msg(&(lp->hcfCtx),  &Descp[0], HCF_PORT_0);
 516                                                kfree(data);
 517                                        } else {
 518                                                DBG_ERROR(DbgInfo, "ENOMEM\n");
 519                                                urq->result = UIL_FAILURE;
 520                                                result = -ENOMEM;
 521                                                DBG_LEAVE(DbgInfo);
 522                                                return result;
 523                                        }
 524
 525                                } else {
 526                                        urq->result = UIL_ERR_BUSY;
 527                                }
 528
 529                        } else {
 530                                urq->result = UIL_FAILURE;
 531                        }
 532                } else {
 533                        DBG_ERROR(DbgInfo, "EPERM\n");
 534                        urq->result = UIL_FAILURE;
 535                        result = -EPERM;
 536                }
 537        } else {
 538                DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
 539                urq->result = UIL_ERR_WRONG_IFB;
 540        }
 541
 542        DBG_LEAVE(DbgInfo);
 543        return result;
 544} /* wvlan_uil_send_diag_msg */
 545/*============================================================================*/
 546
 547
 548/*******************************************************************************
 549 *      wvlan_uil_put_info()
 550 *******************************************************************************
 551 *
 552 *  DESCRIPTION:
 553 *
 554 *      Sends a specific RID directly to the driver to set configuration info.
 555 *
 556 *  PARAMETERS:
 557 *
 558 *      urq - a pointer to the UIL request buffer
 559 *      lp  - a pointer to the device's private adapter structure
 560 *
 561 *  RETURNS:
 562 *
 563 *      UIL_SUCCESS
 564 *      UIL_ERR_xxx value otherwise
 565 *
 566 ******************************************************************************/
 567int wvlan_uil_put_info(struct uilreq *urq, struct wl_private *lp)
 568{
 569        int                     result = 0;
 570        ltv_t                   *pLtv;
 571        bool_t                  ltvAllocated = FALSE;
 572        ENCSTRCT                sEncryption;
 573
 574#ifdef USE_WDS
 575        hcf_16                  hcfPort  = HCF_PORT_0;
 576#endif  /* USE_WDS */
 577        /*------------------------------------------------------------------------*/
 578        DBG_FUNC("wvlan_uil_put_info");
 579        DBG_ENTER(DbgInfo);
 580
 581
 582        if (urq->hcfCtx == &(lp->hcfCtx)) {
 583                if (capable(CAP_NET_ADMIN)) {
 584                        if ((urq->data != NULL) && (urq->len != 0)) {
 585                                /* Make sure that we have at least a command and length to send. */
 586                                if (urq->len < (sizeof(hcf_16) * 2)) {
 587                                        urq->len = sizeof(lp->ltvRecord);
 588                                        urq->result = UIL_ERR_LEN;
 589                                        DBG_ERROR(DbgInfo, "No Length/Type in LTV!!!\n");
 590                                        DBG_ERROR(DbgInfo, "UIL_ERR_LEN\n");
 591                                        DBG_LEAVE(DbgInfo);
 592                                        return result;
 593                                }
 594
 595                                /* Verify the user buffer */
 596                                result = verify_area(VERIFY_READ, urq->data, urq->len);
 597                                if (result != 0) {
 598                                        urq->result = UIL_FAILURE;
 599                                        DBG_ERROR(DbgInfo, "verify_area(), VERIFY_READ FAILED\n");
 600                                        DBG_LEAVE(DbgInfo);
 601                                        return result;
 602                                }
 603
 604                                /* Get only the command and length information. */
 605                                copy_from_user(&(lp->ltvRecord), urq->data, sizeof(hcf_16) * 2);
 606
 607                                /* Make sure the incoming LTV record length is within the bounds of the
 608                                   IOCTL length */
 609                                if (((lp->ltvRecord.len + 1) * sizeof(hcf_16)) > urq->len) {
 610                                        urq->len = sizeof(lp->ltvRecord);
 611                                        urq->result = UIL_ERR_LEN;
 612                                        DBG_ERROR(DbgInfo, "UIL_ERR_LEN\n");
 613                                        DBG_LEAVE(DbgInfo);
 614                                        return result;
 615                                }
 616
 617                                /* If the requested length is greater than the size of our local
 618                                   LTV record, try to allocate it from the kernel stack.
 619                                   Otherwise, we just use our local LTV record. */
 620                                if (urq->len > sizeof(lp->ltvRecord)) {
 621                                        pLtv = kmalloc(urq->len, GFP_KERNEL);
 622                                        if (pLtv != NULL) {
 623                                                ltvAllocated = TRUE;
 624                                        } else {
 625                                                DBG_ERROR(DbgInfo, "Alloc FAILED\n");
 626                                                urq->len = sizeof(lp->ltvRecord);
 627                                                urq->result = UIL_ERR_LEN;
 628                                                result = -ENOMEM;
 629                                                DBG_LEAVE(DbgInfo);
 630                                                return result;
 631                                        }
 632                                } else {
 633                                        pLtv = &(lp->ltvRecord);
 634                                }
 635
 636                                /* Copy the data from the user's buffer into the local LTV
 637                                   record data area. */
 638                                copy_from_user(pLtv, urq->data, urq->len);
 639
 640
 641                                /* We need to snoop the commands to see if there is anything we
 642                                   need to store for the purposes of a reset or start/stop
 643                                   sequence. Perform endian translation as needed */
 644                                switch (pLtv->typ) {
 645                                case CFG_CNF_PORT_TYPE:
 646                                        lp->PortType    = pLtv->u.u16[0];
 647                                        pLtv->u.u16[0]  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 648                                        break;
 649                                case CFG_CNF_OWN_MAC_ADDR:
 650                                        /* TODO: determine if we are going to store anything based on this */
 651                                        break;
 652                                case CFG_CNF_OWN_CHANNEL:
 653                                        lp->Channel     = pLtv->u.u16[0];
 654                                        pLtv->u.u16[0]  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 655                                        break;
 656                                /* CFG_CNF_OWN_SSID currently same as CNF_DESIRED_SSID. Do we
 657                                   need separate storage for this? */
 658                                /* case CFG_CNF_OWN_SSID: */
 659                                case CFG_CNF_OWN_ATIM_WINDOW:
 660                                        lp->atimWindow  = pLtv->u.u16[0];
 661                                        pLtv->u.u16[0]  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 662                                        break;
 663                                case CFG_CNF_SYSTEM_SCALE:
 664                                        lp->DistanceBetweenAPs  = pLtv->u.u16[0];
 665                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 666
 667                                case CFG_CNF_MAX_DATA_LEN:
 668                                        /* TODO: determine if we are going to store anything based
 669                                           on this */
 670                                        break;
 671                                case CFG_CNF_PM_ENABLED:
 672                                        lp->PMEnabled   = pLtv->u.u16[0];
 673                                        pLtv->u.u16[0]  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 674                                        break;
 675                                case CFG_CNF_MCAST_RX:
 676                                        lp->MulticastReceive    = pLtv->u.u16[0];
 677                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 678                                        break;
 679                                case CFG_CNF_MAX_SLEEP_DURATION:
 680                                        lp->MaxSleepDuration    = pLtv->u.u16[0];
 681                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 682                                        break;
 683                                case CFG_CNF_HOLDOVER_DURATION:
 684                                        lp->holdoverDuration    = pLtv->u.u16[0];
 685                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 686                                        break;
 687                                case CFG_CNF_OWN_NAME:
 688                                        memset(lp->StationName, 0, sizeof(lp->StationName));
 689                                        memcpy((void *)lp->StationName, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0]);
 690                                        pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 691                                        break;
 692                                case CFG_CNF_LOAD_BALANCING:
 693                                        lp->loadBalancing       = pLtv->u.u16[0];
 694                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 695                                        break;
 696                                case CFG_CNF_MEDIUM_DISTRIBUTION:
 697                                        lp->mediumDistribution  = pLtv->u.u16[0];
 698                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 699                                        break;
 700#ifdef WARP
 701                                case CFG_CNF_TX_POW_LVL:
 702                                        lp->txPowLevel          = pLtv->u.u16[0];
 703                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 704                                        break;
 705                                /* case CFG_CNF_SHORT_RETRY_LIMIT: */ /* Short Retry Limit */
 706                                /* case 0xFC33: */   /* Long Retry Limit */
 707                                case CFG_SUPPORTED_RATE_SET_CNTL:        /* Supported Rate Set Control */
 708                                        lp->srsc[0]             = pLtv->u.u16[0];
 709                                        lp->srsc[1]             = pLtv->u.u16[1];
 710                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 711                                        pLtv->u.u16[1]          = CNV_INT_TO_LITTLE(pLtv->u.u16[1]);
 712                                        break;
 713                                case CFG_BASIC_RATE_SET_CNTL:        /* Basic Rate Set Control */
 714                                        lp->brsc[0]             = pLtv->u.u16[0];
 715                                        lp->brsc[1]             = pLtv->u.u16[1];
 716                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 717                                        pLtv->u.u16[1]          = CNV_INT_TO_LITTLE(pLtv->u.u16[1]);
 718                                        break;
 719                                case CFG_CNF_CONNECTION_CNTL:
 720                                        lp->connectionControl   = pLtv->u.u16[0];
 721                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 722                                        break;
 723                                /* case CFG_PROBE_DATA_RATE: */
 724#endif  /* HERMES25 */
 725
 726#if 1 /* ;? (HCF_TYPE) & HCF_TYPE_AP */
 727                /* ;?should we restore this to allow smaller memory footprint */
 728
 729                                case CFG_CNF_OWN_DTIM_PERIOD:
 730                                        lp->DTIMPeriod  = pLtv->u.u16[0];
 731                                        pLtv->u.u16[0]  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 732                                        break;
 733#ifdef WARP
 734                                case CFG_CNF_OWN_BEACON_INTERVAL:        /* Own Beacon Interval */
 735                                        lp->ownBeaconInterval   = pLtv->u.u16[0];
 736                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 737                                        break;
 738#endif /* WARP */
 739                                case CFG_COEXISTENSE_BEHAVIOUR:         /* Coexistence behavior */
 740                                        lp->coexistence         = pLtv->u.u16[0];
 741                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 742                                        break;
 743#ifdef USE_WDS
 744                                case CFG_CNF_WDS_ADDR1:
 745                                        memcpy(&lp->wds_port[0].wdsAddress, &pLtv->u.u8[0], ETH_ALEN);
 746                                        hcfPort = HCF_PORT_1;
 747                                        break;
 748                                case CFG_CNF_WDS_ADDR2:
 749                                        memcpy(&lp->wds_port[1].wdsAddress, &pLtv->u.u8[0], ETH_ALEN);
 750                                        hcfPort = HCF_PORT_2;
 751                                        break;
 752                                case CFG_CNF_WDS_ADDR3:
 753                                        memcpy(&lp->wds_port[2].wdsAddress, &pLtv->u.u8[0], ETH_ALEN);
 754                                        hcfPort = HCF_PORT_3;
 755                                        break;
 756                                case CFG_CNF_WDS_ADDR4:
 757                                        memcpy(&lp->wds_port[3].wdsAddress, &pLtv->u.u8[0], ETH_ALEN);
 758                                        hcfPort = HCF_PORT_4;
 759                                        break;
 760                                case CFG_CNF_WDS_ADDR5:
 761                                        memcpy(&lp->wds_port[4].wdsAddress, &pLtv->u.u8[0], ETH_ALEN);
 762                                        hcfPort = HCF_PORT_5;
 763                                        break;
 764                                case CFG_CNF_WDS_ADDR6:
 765                                        memcpy(&lp->wds_port[5].wdsAddress, &pLtv->u.u8[0], ETH_ALEN);
 766                                        hcfPort = HCF_PORT_6;
 767                                        break;
 768#endif  /* USE_WDS */
 769
 770                                case CFG_CNF_MCAST_PM_BUF:
 771                                        lp->multicastPMBuffering    = pLtv->u.u16[0];
 772                                        pLtv->u.u16[0]              = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 773                                        break;
 774                                case CFG_CNF_REJECT_ANY:
 775                                        lp->RejectAny   = pLtv->u.u16[0];
 776                                        pLtv->u.u16[0]  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 777                                        break;
 778#endif
 779
 780                                case CFG_CNF_ENCRYPTION:
 781                                        lp->EnableEncryption    = pLtv->u.u16[0];
 782                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 783                                        break;
 784                                case CFG_CNF_AUTHENTICATION:
 785                                        lp->authentication  = pLtv->u.u16[0];
 786                                        pLtv->u.u16[0]      = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 787                                        break;
 788#if 1 /* ;? (HCF_TYPE) & HCF_TYPE_AP */
 789                /* ;?should we restore this to allow smaller memory footprint */
 790
 791                                /* case CFG_CNF_EXCL_UNENCRYPTED:
 792                                        lp->ExcludeUnencrypted  = pLtv->u.u16[0];
 793                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 794                                        break; */
 795                                case CFG_CNF_MCAST_RATE:
 796                                        /* TODO: determine if we are going to store anything based on this */
 797                                        break;
 798                                case CFG_CNF_INTRA_BSS_RELAY:
 799                                        lp->intraBSSRelay   = pLtv->u.u16[0];
 800                                        pLtv->u.u16[0]      = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 801                                        break;
 802#endif
 803
 804                                case CFG_CNF_MICRO_WAVE:
 805                                        /* TODO: determine if we are going to store anything based on this */
 806                                        break;
 807                                /*case CFG_CNF_LOAD_BALANCING:*/
 808                                        /* TODO: determine if we are going to store anything based on this */
 809                                        /* break; */
 810                                /* case CFG_CNF_MEDIUM_DISTRIBUTION: */
 811                                        /* TODO: determine if we are going to store anything based on this */
 812                                        /* break; */
 813                                /* case CFG_CNF_RX_ALL_GROUP_ADDRESS: */
 814                                        /*  TODO: determine if we are going to store anything based on this */
 815                                        /* break; */
 816                                /* case CFG_CNF_COUNTRY_INFO: */
 817                                        /* TODO: determine if we are going to store anything based on this */
 818                                        /* break; */
 819                                case CFG_CNF_OWN_SSID:
 820                                /* case CNF_DESIRED_SSID: */
 821                                case CFG_DESIRED_SSID:
 822                                        memset(lp->NetworkName, 0, sizeof(lp->NetworkName));
 823                                        memcpy((void *)lp->NetworkName, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0]);
 824                                        pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 825
 826                                        /* take care of the special network name "ANY" case */
 827                                        if ((strlen(&pLtv->u.u8[2]) == 0) ||
 828                                           (strcmp(&pLtv->u.u8[2], "ANY") == 0) ||
 829                                           (strcmp(&pLtv->u.u8[2], "any") == 0)) {
 830                                                /* set the SSID_STRCT llen field (u16[0]) to zero, and the
 831                                                effectually null the string u8[2] */
 832                                                pLtv->u.u16[0] = 0;
 833                                                pLtv->u.u8[2]  = 0;
 834                                        }
 835                                        break;
 836                                case CFG_GROUP_ADDR:
 837                                        /* TODO: determine if we are going to store anything based on this */
 838                                        break;
 839                                case CFG_CREATE_IBSS:
 840                                        lp->CreateIBSS  = pLtv->u.u16[0];
 841                                        pLtv->u.u16[0]  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 842                                        break;
 843                                case CFG_RTS_THRH:
 844                                        lp->RTSThreshold    = pLtv->u.u16[0];
 845                                        pLtv->u.u16[0]      = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 846                                        break;
 847                                case CFG_TX_RATE_CNTL:
 848                                        lp->TxRateControl[0]    = pLtv->u.u16[0];
 849                                        lp->TxRateControl[1]    = pLtv->u.u16[1];
 850                                        pLtv->u.u16[0]          = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 851                                        pLtv->u.u16[1]          = CNV_INT_TO_LITTLE(pLtv->u.u16[1]);
 852                                        break;
 853                                case CFG_PROMISCUOUS_MODE:
 854                                        /* TODO: determine if we are going to store anything based on this */
 855                                        break;
 856                                /* case CFG_WAKE_ON_LAN: */
 857                                        /* TODO: determine if we are going to store anything based on this */
 858                                        /* break; */
 859#if 1 /* ;? #if (HCF_TYPE) & HCF_TYPE_AP */
 860                /* ;?should we restore this to allow smaller memory footprint */
 861                                case CFG_RTS_THRH0:
 862                                        lp->RTSThreshold    = pLtv->u.u16[0];
 863                                        pLtv->u.u16[0]      = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 864                                        break;
 865                                case CFG_TX_RATE_CNTL0:
 866/*;?no idea what this should be, get going so comment it out                                    lp->TxRateControl   = pLtv->u.u16[0];*/
 867                                        pLtv->u.u16[0]      = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 868                                        break;
 869#ifdef USE_WDS
 870                                case CFG_RTS_THRH1:
 871                                        lp->wds_port[0].rtsThreshold    = pLtv->u.u16[0];
 872                                        pLtv->u.u16[0]                  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 873                                        hcfPort                         = HCF_PORT_1;
 874                                        break;
 875                                case CFG_RTS_THRH2:
 876                                        lp->wds_port[1].rtsThreshold    = pLtv->u.u16[0];
 877                                        pLtv->u.u16[0]                  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 878                                        hcfPort                         = HCF_PORT_2;
 879                                        break;
 880                                case CFG_RTS_THRH3:
 881                                        lp->wds_port[2].rtsThreshold    = pLtv->u.u16[0];
 882                                        pLtv->u.u16[0]                  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 883                                        hcfPort                         = HCF_PORT_3;
 884                                        break;
 885                                case CFG_RTS_THRH4:
 886                                        lp->wds_port[3].rtsThreshold    = pLtv->u.u16[0];
 887                                        pLtv->u.u16[0]                  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 888                                        hcfPort                         = HCF_PORT_4;
 889                                        break;
 890                                case CFG_RTS_THRH5:
 891                                        lp->wds_port[4].rtsThreshold    = pLtv->u.u16[0];
 892                                        pLtv->u.u16[0]                  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 893                                        hcfPort                         = HCF_PORT_5;
 894                                        break;
 895                                case CFG_RTS_THRH6:
 896                                        lp->wds_port[5].rtsThreshold    = pLtv->u.u16[0];
 897                                        pLtv->u.u16[0]                  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 898                                        hcfPort                         = HCF_PORT_6;
 899                                        break;
 900                                case CFG_TX_RATE_CNTL1:
 901                                        lp->wds_port[0].txRateCntl  = pLtv->u.u16[0];
 902                                        pLtv->u.u16[0]              = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 903                                        hcfPort                     = HCF_PORT_1;
 904                                        break;
 905                                case CFG_TX_RATE_CNTL2:
 906                                        lp->wds_port[1].txRateCntl  = pLtv->u.u16[0];
 907                                        pLtv->u.u16[0]              = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 908                                        hcfPort                     = HCF_PORT_2;
 909                                        break;
 910                                case CFG_TX_RATE_CNTL3:
 911                                        lp->wds_port[2].txRateCntl  = pLtv->u.u16[0];
 912                                        pLtv->u.u16[0]              = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 913                                        hcfPort                     = HCF_PORT_3;
 914                                        break;
 915                                case CFG_TX_RATE_CNTL4:
 916                                        lp->wds_port[3].txRateCntl  = pLtv->u.u16[0];
 917                                        pLtv->u.u16[0]              = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 918                                        hcfPort                     = HCF_PORT_4;
 919                                        break;
 920                                case CFG_TX_RATE_CNTL5:
 921                                        lp->wds_port[4].txRateCntl  = pLtv->u.u16[0];
 922                                        pLtv->u.u16[0]              = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 923                                        hcfPort                     = HCF_PORT_5;
 924                                        break;
 925                                case CFG_TX_RATE_CNTL6:
 926                                        lp->wds_port[5].txRateCntl  = pLtv->u.u16[0];
 927                                        pLtv->u.u16[0]              = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 928                                        hcfPort                     = HCF_PORT_6;
 929                                        break;
 930#endif  /* USE_WDS */
 931#endif  /* (HCF_TYPE) & HCF_TYPE_AP */
 932
 933                                case CFG_DEFAULT_KEYS:
 934                                        {
 935                                                CFG_DEFAULT_KEYS_STRCT *pKeys = (CFG_DEFAULT_KEYS_STRCT *)pLtv;
 936
 937                                                pKeys->key[0].len = CNV_INT_TO_LITTLE(pKeys->key[0].len);
 938                                                pKeys->key[1].len = CNV_INT_TO_LITTLE(pKeys->key[1].len);
 939                                                pKeys->key[2].len = CNV_INT_TO_LITTLE(pKeys->key[2].len);
 940                                                pKeys->key[3].len = CNV_INT_TO_LITTLE(pKeys->key[3].len);
 941
 942                                                memcpy((void *)&(lp->DefaultKeys), (void *)pKeys,
 943                                                                sizeof(CFG_DEFAULT_KEYS_STRCT));
 944                                        }
 945                                        break;
 946                                case CFG_TX_KEY_ID:
 947                                        lp->TransmitKeyID   = pLtv->u.u16[0];
 948                                        pLtv->u.u16[0]      = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
 949                                        break;
 950                                case CFG_SCAN_SSID:
 951                                        /* TODO: determine if we are going to store anything based on this */
 952                                        break;
 953                                case CFG_TICK_TIME:
 954                                        /* TODO: determine if we are going to store anything based on this */
 955                                        break;
 956                                /* these RIDS are Info RIDs, and should they be allowed for puts??? */
 957                                case CFG_MAX_LOAD_TIME:
 958                                case CFG_DL_BUF:
 959                                /* case CFG_HSI_SUP_RANGE: */
 960                                case CFG_NIC_SERIAL_NUMBER:
 961                                case CFG_NIC_IDENTITY:
 962                                case CFG_NIC_MFI_SUP_RANGE:
 963                                case CFG_NIC_CFI_SUP_RANGE:
 964                                case CFG_NIC_TEMP_TYPE:
 965                                case CFG_NIC_PROFILE:
 966                                case CFG_FW_IDENTITY:
 967                                case CFG_FW_SUP_RANGE:
 968                                case CFG_MFI_ACT_RANGES_STA:
 969                                case CFG_CFI_ACT_RANGES_STA:
 970                                case CFG_PORT_STAT:
 971                                case CFG_CUR_SSID:
 972                                case CFG_CUR_BSSID:
 973                                case CFG_COMMS_QUALITY:
 974                                case CFG_CUR_TX_RATE:
 975                                case CFG_CUR_BEACON_INTERVAL:
 976                                case CFG_CUR_SCALE_THRH:
 977                                case CFG_PROTOCOL_RSP_TIME:
 978                                case CFG_CUR_SHORT_RETRY_LIMIT:
 979                                case CFG_CUR_LONG_RETRY_LIMIT:
 980                                case CFG_MAX_TX_LIFETIME:
 981                                case CFG_MAX_RX_LIFETIME:
 982                                case CFG_CF_POLLABLE:
 983                                case CFG_AUTHENTICATION_ALGORITHMS:
 984                                case CFG_PRIVACY_OPT_IMPLEMENTED:
 985                                /* case CFG_CURRENT_REMOTE_RATES: */
 986                                /* case CFG_CURRENT_USED_RATES: */
 987                                /* case CFG_CURRENT_SYSTEM_SCALE: */
 988                                /* case CFG_CURRENT_TX_RATE1: */
 989                                /* case CFG_CURRENT_TX_RATE2: */
 990                                /* case CFG_CURRENT_TX_RATE3: */
 991                                /* case CFG_CURRENT_TX_RATE4: */
 992                                /* case CFG_CURRENT_TX_RATE5: */
 993                                /* case CFG_CURRENT_TX_RATE6: */
 994                                case CFG_NIC_MAC_ADDR:
 995                                case CFG_PCF_INFO:
 996                                /* case CFG_CURRENT_COUNTRY_INFO: */
 997                                case CFG_PHY_TYPE:
 998                                case CFG_CUR_CHANNEL:
 999                                /* case CFG_CURRENT_POWER_STATE: */
1000                                /* case CFG_CCAMODE: */
1001                                case CFG_SUPPORTED_DATA_RATES:
1002                                        break;
1003                                case CFG_AP_MODE:
1004/*;?                            lp->DownloadFirmware = (pLtv->u.u16[0]) + 1; */
1005                                        DBG_ERROR(DbgInfo, "set CFG_AP_MODE no longer supported\n");
1006                                        break;
1007                                case CFG_ENCRYPT_STRING:
1008                                        /* TODO: ENDIAN TRANSLATION HERE??? */
1009                                        memset(lp->szEncryption, 0, sizeof(lp->szEncryption));
1010                                        memcpy((void *)lp->szEncryption,  (void *)&pLtv->u.u8[0],
1011                                                        (pLtv->len * sizeof(hcf_16)));
1012                                        wl_wep_decode(CRYPT_CODE, &sEncryption,
1013                                                                    lp->szEncryption);
1014
1015                                        /* the Linux driver likes to use 1-4 for the key IDs, and then
1016                                        convert to 0-3 when sending to the card.  The Windows code
1017                                        base used 0-3 in the API DLL, which was ported to Linux.  For
1018                                        the sake of the user experience, we decided to keep 0-3 as the
1019                                        numbers used in the DLL; and will perform the +1 conversion here.
1020                                        We could have converted  the entire Linux driver, but this is
1021                                        less obtrusive.  This may be a "todo" to convert the whole driver */
1022                                        lp->TransmitKeyID    = sEncryption.wTxKeyID + 1;
1023                                        lp->EnableEncryption = sEncryption.wEnabled;
1024
1025                                        memcpy(&lp->DefaultKeys, &sEncryption.EncStr,
1026                                                        sizeof(CFG_DEFAULT_KEYS_STRCT));
1027                                        break;
1028                                /*case CFG_COUNTRY_STRING:
1029                                        memset(lp->countryString, 0, sizeof(lp->countryString));
1030                                        memcpy((void *)lp->countryString, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0]);
1031                                        break;
1032                                */
1033
1034                                case CFG_DRIVER_ENABLE:
1035                                        lp->driverEnable    = pLtv->u.u16[0];
1036                                        pLtv->u.u16[0]      = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
1037                                        break;
1038                                case CFG_WOLAS_ENABLE:
1039                                        lp->wolasEnable = pLtv->u.u16[0];
1040                                        pLtv->u.u16[0]  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
1041                                        break;
1042                                case CFG_SET_WPA_AUTH_KEY_MGMT_SUITE:
1043                                        lp->AuthKeyMgmtSuite = pLtv->u.u16[0];
1044                                        pLtv->u.u16[0]  = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
1045                                        break;
1046                                case CFG_DISASSOCIATE_ADDR:
1047                                        pLtv->u.u16[ETH_ALEN / 2] = CNV_INT_TO_LITTLE(pLtv->u.u16[ETH_ALEN / 2]);
1048                                        break;
1049                                case CFG_ADD_TKIP_DEFAULT_KEY:
1050                                case CFG_REMOVE_TKIP_DEFAULT_KEY:
1051                                        /* Endian convert the Tx Key Information */
1052                                        pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
1053                                        break;
1054                                case CFG_ADD_TKIP_MAPPED_KEY:
1055                                        break;
1056                                case CFG_REMOVE_TKIP_MAPPED_KEY:
1057                                        break;
1058                                /* some RIDs just can't be put */
1059                                case CFG_MB_INFO:
1060                                case CFG_IFB:
1061                                default:
1062                                        break;
1063                                }
1064
1065                                /* This code will prevent Static Configuration Entities from
1066                                   being sent to the card, as they require a call to
1067                                   UIL_ACT_APPLY to take effect. Dynamic Entities will be sent
1068                                   immediately */
1069                                switch (pLtv->typ) {
1070                                case CFG_CNF_PORT_TYPE:
1071                                case CFG_CNF_OWN_MAC_ADDR:
1072                                case CFG_CNF_OWN_CHANNEL:
1073                                case CFG_CNF_OWN_SSID:
1074                                case CFG_CNF_OWN_ATIM_WINDOW:
1075                                case CFG_CNF_SYSTEM_SCALE:
1076                                case CFG_CNF_MAX_DATA_LEN:
1077                                case CFG_CNF_PM_ENABLED:
1078                                case CFG_CNF_MCAST_RX:
1079                                case CFG_CNF_MAX_SLEEP_DURATION:
1080                                case CFG_CNF_HOLDOVER_DURATION:
1081                                case CFG_CNF_OWN_NAME:
1082                                case CFG_CNF_LOAD_BALANCING:
1083                                case CFG_CNF_MEDIUM_DISTRIBUTION:
1084#ifdef WARP
1085                                case CFG_CNF_TX_POW_LVL:
1086                                case CFG_CNF_CONNECTION_CNTL:
1087                                /*case CFG_PROBE_DATA_RATE: */
1088#endif /* HERMES25 */
1089#if 1 /*;? (HCF_TYPE) & HCF_TYPE_AP */
1090                /*;?should we restore this to allow smaller memory footprint */
1091                                case CFG_CNF_OWN_DTIM_PERIOD:
1092#ifdef WARP
1093                                case CFG_CNF_OWN_BEACON_INTERVAL:                    /* Own Beacon Interval */
1094#endif /* WARP */
1095#ifdef USE_WDS
1096                                case CFG_CNF_WDS_ADDR1:
1097                                case CFG_CNF_WDS_ADDR2:
1098                                case CFG_CNF_WDS_ADDR3:
1099                                case CFG_CNF_WDS_ADDR4:
1100                                case CFG_CNF_WDS_ADDR5:
1101                                case CFG_CNF_WDS_ADDR6:
1102#endif
1103                                case CFG_CNF_MCAST_PM_BUF:
1104                                case CFG_CNF_REJECT_ANY:
1105#endif
1106
1107                                case CFG_CNF_ENCRYPTION:
1108                                case CFG_CNF_AUTHENTICATION:
1109#if 1 /* ;? (HCF_TYPE) & HCF_TYPE_AP */
1110                /* ;?should we restore this to allow smaller memory footprint */
1111
1112                                case CFG_CNF_EXCL_UNENCRYPTED:
1113                                case CFG_CNF_MCAST_RATE:
1114                                case CFG_CNF_INTRA_BSS_RELAY:
1115#endif
1116
1117                                case CFG_CNF_MICRO_WAVE:
1118                                /* case CFG_CNF_LOAD_BALANCING: */
1119                                /* case CFG_CNF_MEDIUM_DISTRIBUTION: */
1120                                /* case CFG_CNF_RX_ALL_GROUP_ADDRESS: */
1121                                /* case CFG_CNF_COUNTRY_INFO: */
1122                                /* case CFG_COUNTRY_STRING: */
1123                                case CFG_AP_MODE:
1124                                case CFG_ENCRYPT_STRING:
1125                                /* case CFG_DRIVER_ENABLE: */
1126                                case CFG_WOLAS_ENABLE:
1127                                case CFG_MB_INFO:
1128                                case CFG_IFB:
1129                                        break;
1130                                /* Deal with this dynamic MSF RID, as it's required for WPA */
1131                                case CFG_DRIVER_ENABLE:
1132                                        if (lp->driverEnable) {
1133                                                hcf_cntl(&(lp->hcfCtx), HCF_CNTL_ENABLE | HCF_PORT_0);
1134                                                hcf_cntl(&(lp->hcfCtx), HCF_CNTL_CONNECT);
1135                                        } else {
1136                                                hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
1137                                                hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISCONNECT);
1138                                        }
1139                                        break;
1140                                default:
1141                                        wl_act_int_off(lp);
1142                                        urq->result = hcf_put_info(&(lp->hcfCtx), (LTVP) pLtv);
1143                                        wl_act_int_on(lp);
1144                                        break;
1145                                }
1146
1147                                if (ltvAllocated)
1148                                        kfree(pLtv);
1149                        } else {
1150                                urq->result = UIL_FAILURE;
1151                        }
1152                } else {
1153                        DBG_ERROR(DbgInfo, "EPERM\n");
1154                        urq->result = UIL_FAILURE;
1155                        result = -EPERM;
1156                }
1157        } else {
1158                DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
1159                urq->result = UIL_ERR_WRONG_IFB;
1160        }
1161
1162        DBG_LEAVE(DbgInfo);
1163        return result;
1164} /* wvlan_uil_put_info */
1165
1166/*============================================================================*/
1167
1168/*******************************************************************************
1169 *      wvlan_uil_get_info()
1170 *******************************************************************************
1171 *
1172 *  DESCRIPTION:
1173 *
1174 *      Sends a specific RID directly to the driver to retrieve configuration
1175 *      info.
1176 *
1177 *  PARAMETERS:
1178 *
1179 *      urq - a pointer to the UIL request buffer
1180 *      lp  - a pointer to the device's private adapter structure
1181 *
1182 *  RETURNS:
1183 *
1184 *      UIL_SUCCESS
1185 *      UIL_ERR_xxx value otherwise
1186 *
1187 ******************************************************************************/
1188int wvlan_uil_get_info(struct uilreq *urq, struct wl_private *lp)
1189{
1190        int result = 0;
1191        int i;
1192        /*------------------------------------------------------------------------*/
1193
1194        DBG_FUNC("wvlan_uil_get_info");
1195        DBG_ENTER(DbgInfo);
1196
1197        if (urq->hcfCtx == &(lp->hcfCtx)) {
1198                if ((urq->data != NULL) && (urq->len != 0)) {
1199                        ltv_t      *pLtv;
1200                        bool_t      ltvAllocated = FALSE;
1201
1202                        /* Make sure that we have at least a command and length */
1203                        if (urq->len < (sizeof(hcf_16) * 2)) {
1204                                urq->len = sizeof(lp->ltvRecord);
1205                                DBG_ERROR(DbgInfo, "No Length/Type in LTV!!!\n");
1206                                DBG_ERROR(DbgInfo, "UIL_ERR_LEN\n");
1207                                urq->result = UIL_ERR_LEN;
1208                                DBG_LEAVE(DbgInfo);
1209                                return result;
1210                        }
1211
1212                        /* Verify the user's LTV record header. */
1213                        result = verify_area(VERIFY_READ, urq->data, sizeof(hcf_16) * 2);
1214                        if (result != 0) {
1215                                DBG_ERROR(DbgInfo, "verify_area(), VERIFY_READ FAILED\n");
1216                                urq->result = UIL_FAILURE;
1217                                DBG_LEAVE(DbgInfo);
1218                                return result;
1219                        }
1220
1221                        /* Get only the command and length information. */
1222                        result = copy_from_user(&(lp->ltvRecord), urq->data, sizeof(hcf_16) * 2);
1223
1224                        /* Make sure the incoming LTV record length is within the bounds of
1225                           the IOCTL length. */
1226                        if (((lp->ltvRecord.len + 1) * sizeof(hcf_16)) > urq->len) {
1227                                DBG_ERROR(DbgInfo, "Incoming LTV too big\n");
1228                                urq->len = sizeof(lp->ltvRecord);
1229                                urq->result = UIL_ERR_LEN;
1230                                DBG_LEAVE(DbgInfo);
1231                                return result;
1232                        }
1233
1234                        /* Determine if hcf_get_info() is needed or not */
1235                        switch (lp->ltvRecord.typ) {
1236                        case CFG_NIC_IDENTITY:
1237                                memcpy(&lp->ltvRecord.u.u8[0], &lp->NICIdentity, sizeof(lp->NICIdentity));
1238                                break;
1239                        case CFG_PRI_IDENTITY:
1240                                memcpy(&lp->ltvRecord.u.u8[0], &lp->PrimaryIdentity, sizeof(lp->PrimaryIdentity));
1241                                break;
1242                        case CFG_AP_MODE:
1243                                DBG_ERROR(DbgInfo, "set CFG_AP_MODE no longer supported, so is get useful ????\n");
1244                                lp->ltvRecord.u.u16[0] =
1245                                        CNV_INT_TO_LITTLE(lp->hcfCtx.IFB_FWIdentity.comp_id) == COMP_ID_FW_AP;
1246                                break;
1247                        /* case CFG_DRV_INFO: */
1248                        case CFG_ENCRYPT_STRING:
1249                        case CFG_COUNTRY_STRING:
1250                        case CFG_DRIVER_ENABLE:
1251                        case CFG_WOLAS_ENABLE:
1252                                /* TODO: determine if we're going to support these */
1253                                urq->result = UIL_FAILURE;
1254                                break;
1255                        case CFG_DRV_INFO:
1256                                DBG_TRACE(DbgInfo, "Intercept CFG_DRV_INFO\n");
1257                                result = cfg_driver_info(urq, lp);
1258                                break;
1259                        case CFG_DRV_IDENTITY:
1260                                DBG_TRACE(DbgInfo, "Intercept CFG_DRV_IDENTITY\n");
1261                                result = cfg_driver_identity(urq, lp);
1262                                break;
1263                        case CFG_IFB:
1264                                /* IFB can be a security hole */
1265                                if (!capable(CAP_NET_ADMIN)) {
1266                                        result = -EPERM;
1267                                        break;
1268                                }
1269
1270                                /* Else fall through to the default */
1271
1272                        case CFG_FW_IDENTITY:   /* For Hermes-1, this is cached */
1273                        default:
1274
1275                                /* Verify the user buffer */
1276                                result = verify_area(VERIFY_WRITE, urq->data, urq->len);
1277                                if (result != 0) {
1278                                        DBG_ERROR(DbgInfo, "verify_area(), VERIFY_WRITE FAILED\n");
1279                                        urq->result = UIL_FAILURE;
1280                                        break;
1281                                }
1282
1283                                /* If the requested length is greater than the size of our local
1284                                   LTV record, try to allocate it from the kernel stack.
1285                                   Otherwise, we just use our local LTV record. */
1286                                if (urq->len > sizeof(lp->ltvRecord)) {
1287                                        pLtv = kmalloc(urq->len, GFP_KERNEL);
1288                                        if (pLtv != NULL) {
1289                                                ltvAllocated = TRUE;
1290
1291                                                /* Copy the command/length information into the new buffer. */
1292                                                memcpy(pLtv, &(lp->ltvRecord), sizeof(hcf_16) * 2);
1293                                        } else {
1294                                                urq->len = sizeof(lp->ltvRecord);
1295                                                urq->result = UIL_ERR_LEN;
1296                                                DBG_ERROR(DbgInfo, "kmalloc FAILED\n");
1297                                                DBG_ERROR(DbgInfo, "UIL_ERR_LEN\n");
1298                                                result = -ENOMEM;
1299                                                break;
1300                                        }
1301                                } else {
1302                                        pLtv = &(lp->ltvRecord);
1303                                }
1304
1305                                wl_act_int_off(lp);
1306                                urq->result = hcf_get_info(&(lp->hcfCtx), (LTVP) pLtv);
1307                                wl_act_int_on(lp);
1308
1309                                /* Copy the LTV into the user's buffer. */
1310                                /*copy_to_user(urq->data, pLtv, urq->len); */
1311
1312                                /*if(ltvAllocated)
1313                                {
1314                                    kfree(pLtv);
1315                                }*/
1316
1317                                /* urq->result = UIL_SUCCESS; */
1318                                break;
1319                        }
1320
1321                        /* Handle endian conversion of special fields */
1322                        switch (lp->ltvRecord.typ) {
1323                        /* simple int gets just need the first hcf_16 byte flipped */
1324                        case CFG_CNF_PORT_TYPE:
1325                        case CFG_CNF_OWN_CHANNEL:
1326                        case CFG_CNF_OWN_ATIM_WINDOW:
1327                        case CFG_CNF_SYSTEM_SCALE:
1328                        case CFG_CNF_MAX_DATA_LEN:
1329                        case CFG_CNF_PM_ENABLED:
1330                        case CFG_CNF_MCAST_RX:
1331                        case CFG_CNF_MAX_SLEEP_DURATION:
1332                        case CFG_CNF_HOLDOVER_DURATION:
1333                        case CFG_CNF_OWN_DTIM_PERIOD:
1334                        case CFG_CNF_MCAST_PM_BUF:
1335                        case CFG_CNF_REJECT_ANY:
1336                        case CFG_CNF_ENCRYPTION:
1337                        case CFG_CNF_AUTHENTICATION:
1338                        case CFG_CNF_EXCL_UNENCRYPTED:
1339                        case CFG_CNF_INTRA_BSS_RELAY:
1340                        case CFG_CNF_MICRO_WAVE:
1341                        case CFG_CNF_LOAD_BALANCING:
1342                        case CFG_CNF_MEDIUM_DISTRIBUTION:
1343#ifdef WARP
1344                        case CFG_CNF_TX_POW_LVL:
1345                        case CFG_CNF_CONNECTION_CNTL:
1346                        case CFG_CNF_OWN_BEACON_INTERVAL:                          /* Own Beacon Interval */
1347                        case CFG_COEXISTENSE_BEHAVIOUR:                            /* Coexistence Behavior */
1348                        /*case CFG_CNF_RX_ALL_GROUP_ADDRESS: */
1349#endif /* HERMES25 */
1350                        case CFG_CREATE_IBSS:
1351                        case CFG_RTS_THRH:
1352                        case CFG_PROMISCUOUS_MODE:
1353                        /*case CFG_WAKE_ON_LAN: */
1354                        case CFG_RTS_THRH0:
1355                        case CFG_RTS_THRH1:
1356                        case CFG_RTS_THRH2:
1357                        case CFG_RTS_THRH3:
1358                        case CFG_RTS_THRH4:
1359                        case CFG_RTS_THRH5:
1360                        case CFG_RTS_THRH6:
1361                        case CFG_TX_RATE_CNTL0:
1362                        case CFG_TX_RATE_CNTL1:
1363                        case CFG_TX_RATE_CNTL2:
1364                        case CFG_TX_RATE_CNTL3:
1365                        case CFG_TX_RATE_CNTL4:
1366                        case CFG_TX_RATE_CNTL5:
1367                        case CFG_TX_RATE_CNTL6:
1368                        case CFG_TX_KEY_ID:
1369                        case CFG_TICK_TIME:
1370                        case CFG_MAX_LOAD_TIME:
1371                        case CFG_NIC_TEMP_TYPE:
1372                        case CFG_PORT_STAT:
1373                        case CFG_CUR_TX_RATE:
1374                        case CFG_CUR_BEACON_INTERVAL:
1375                        case CFG_PROTOCOL_RSP_TIME:
1376                        case CFG_CUR_SHORT_RETRY_LIMIT:
1377                        case CFG_CUR_LONG_RETRY_LIMIT:
1378                        case CFG_MAX_TX_LIFETIME:
1379                        case CFG_MAX_RX_LIFETIME:
1380                        case CFG_CF_POLLABLE:
1381                        case CFG_PRIVACY_OPT_IMPLEMENTED:
1382                        /* case CFG_CURRENT_REMOTE_RATES: */
1383                        /* case CFG_CURRENT_USED_RATES: */
1384                        /* case CFG_CURRENT_SYSTEM_SCALE: */
1385                        /* case CFG_CURRENT_TX_RATE1: */
1386                        /* case CFG_CURRENT_TX_RATE2: */
1387                        /* case CFG_CURRENT_TX_RATE3: */
1388                        /* case CFG_CURRENT_TX_RATE4: */
1389                        /* case CFG_CURRENT_TX_RATE5: */
1390                        /* case CFG_CURRENT_TX_RATE6: */
1391                        case CFG_PHY_TYPE:
1392                        case CFG_CUR_CHANNEL:
1393                        /* case CFG_CURRENT_POWER_STATE: */
1394                        /* case CFG_CCAMODE: */
1395                        /*     lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]); */
1396                        /*     break; */
1397                        /* name string gets just need the first hcf_16 byte flipped (length of string) */
1398                        case CFG_CNF_OWN_SSID:
1399                        case CFG_CNF_OWN_NAME:
1400                        /* case CNF_DESIRED_SSID: */
1401                        case CFG_DESIRED_SSID:
1402                        case CFG_SCAN_SSID:
1403                        case CFG_CUR_SSID:
1404                                lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]);
1405                                break;
1406                        /* non-length counted strings need no byte flipping */
1407                        case CFG_CNF_OWN_MAC_ADDR:
1408                        /* this case is no longer valid: CFG_CNF_WDS_ADDR */
1409                        case CFG_CNF_WDS_ADDR1:
1410                        case CFG_CNF_WDS_ADDR2:
1411                        case CFG_CNF_WDS_ADDR3:
1412                        case CFG_CNF_WDS_ADDR4:
1413                        case CFG_CNF_WDS_ADDR5:
1414                        case CFG_CNF_WDS_ADDR6:
1415                        case CFG_GROUP_ADDR:
1416                        case CFG_NIC_SERIAL_NUMBER:
1417                        case CFG_CUR_BSSID:
1418                        case CFG_NIC_MAC_ADDR:
1419                        case CFG_SUPPORTED_DATA_RATES:  /* need to ensure we can treat this as a string */
1420                                break;
1421                        /* case CFG_CNF_COUNTRY_INFO: */     /* special case, see page 75  of 022486, Rev C. */
1422                        /* case CFG_CURRENT_COUNTRY_INFO: */ /* special case, see page 101 of 022486, Rev C. */
1423                        /*
1424                                lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]);
1425                                lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[3]);
1426
1427                                for(i = 4; i < lp->ltvRecord.len; i++) {
1428                                        lp->ltvRecord.u.u16[i] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[i]);
1429                                }
1430                                break;
1431                        */
1432
1433                        case CFG_DEFAULT_KEYS:
1434                                {
1435                                        CFG_DEFAULT_KEYS_STRCT *pKeys = (CFG_DEFAULT_KEYS_STRCT *)&lp->ltvRecord.u.u8[0];
1436
1437                                        pKeys[0].len = CNV_INT_TO_LITTLE(pKeys[0].len);
1438                                        pKeys[1].len = CNV_INT_TO_LITTLE(pKeys[1].len);
1439                                        pKeys[2].len = CNV_INT_TO_LITTLE(pKeys[2].len);
1440                                        pKeys[3].len = CNV_INT_TO_LITTLE(pKeys[3].len);
1441                                }
1442                                break;
1443                        case CFG_CNF_MCAST_RATE:
1444                        case CFG_TX_RATE_CNTL:
1445                        case CFG_SUPPORTED_RATE_SET_CNTL:    /*  Supported Rate Set Control */
1446                        case CFG_BASIC_RATE_SET_CNTL:    /*  Basic Rate Set Control */
1447                                lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]);
1448                                lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[1]);
1449                                break;
1450                        case CFG_DL_BUF:
1451                        case CFG_NIC_IDENTITY:
1452                        case CFG_COMMS_QUALITY:
1453                        case CFG_PCF_INFO:
1454                                lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]);
1455                                lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[1]);
1456                                lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[2]);
1457                                break;
1458                        case CFG_FW_IDENTITY:
1459                                lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]);
1460                                lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[1]);
1461                                lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[2]);
1462                                lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[3]);
1463                                break;
1464                        /* case CFG_HSI_SUP_RANGE: */
1465                        case CFG_NIC_MFI_SUP_RANGE:
1466                        case CFG_NIC_CFI_SUP_RANGE:
1467                        case CFG_NIC_PROFILE:
1468                        case CFG_FW_SUP_RANGE:
1469                                lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]);
1470                                lp->ltvRecord.u.u16[1] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[1]);
1471                                lp->ltvRecord.u.u16[2] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[2]);
1472                                lp->ltvRecord.u.u16[3] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[3]);
1473                                lp->ltvRecord.u.u16[4] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[4]);
1474                                break;
1475                        case CFG_MFI_ACT_RANGES_STA:
1476                        case CFG_CFI_ACT_RANGES_STA:
1477                        case CFG_CUR_SCALE_THRH:
1478                        case CFG_AUTHENTICATION_ALGORITHMS:
1479                                for (i = 0; i < (lp->ltvRecord.len - 1); i++)
1480                                        lp->ltvRecord.u.u16[i] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[i]);
1481                                break;
1482                        /* done at init time, and endian handled then */
1483                        case CFG_PRI_IDENTITY:
1484                                break;
1485                        case CFG_MB_INFO:
1486                                /* wvlanEndianTranslateMailbox(pLtv); */
1487                                break;
1488                        /* MSF and HCF RIDS */
1489                        case CFG_IFB:
1490                        case CFG_DRV_INFO:
1491                        case CFG_AP_MODE:
1492                        case CFG_ENCRYPT_STRING:
1493                        case CFG_COUNTRY_STRING:
1494                        case CFG_DRIVER_ENABLE:
1495                        case CFG_WOLAS_ENABLE:
1496                        default:
1497                                break;
1498                        }
1499
1500                        /* Copy the LTV into the user's buffer. */
1501                        copy_to_user(urq->data, &(lp->ltvRecord), urq->len);
1502
1503                        if (ltvAllocated)
1504                                kfree(&(lp->ltvRecord));
1505                        urq->result = UIL_SUCCESS;
1506                } else {
1507                        urq->result = UIL_FAILURE;
1508                }
1509        } else {
1510                DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
1511                urq->result = UIL_ERR_WRONG_IFB;
1512        }
1513
1514        DBG_LEAVE(DbgInfo);
1515        return result;
1516} /* wvlan_uil_get_info */
1517/*============================================================================*/
1518
1519
1520
1521
1522
1523/*******************************************************************************
1524 *      cfg_driver_info()
1525 *******************************************************************************
1526 *
1527 *  DESCRIPTION:
1528 *
1529 *      Retrieves driver information.
1530 *
1531 *  PARAMETERS:
1532 *
1533 *      urq - a pointer to the UIL request buffer
1534 *      lp  - a pointer to the device's private adapter structure
1535 *
1536 *  RETURNS:
1537 *
1538 *      UIL_SUCCESS
1539 *      UIL_ERR_xxx value otherwise
1540 *
1541 ******************************************************************************/
1542int cfg_driver_info(struct uilreq *urq, struct wl_private *lp)
1543{
1544        int result = 0;
1545        /*------------------------------------------------------------------------*/
1546
1547
1548        DBG_FUNC("cfg_driver_info");
1549        DBG_ENTER(DbgInfo);
1550
1551
1552        /* Make sure that user buffer can handle the driver information buffer */
1553        if (urq->len < sizeof(lp->driverInfo)) {
1554                urq->len = sizeof(lp->driverInfo);
1555                urq->result = UIL_ERR_LEN;
1556                DBG_LEAVE(DbgInfo);
1557                return result;
1558        }
1559
1560        /* Verify the user buffer. */
1561        result = verify_area(VERIFY_WRITE, urq->data, sizeof(lp->driverInfo));
1562        if (result != 0) {
1563                urq->result = UIL_FAILURE;
1564                DBG_LEAVE(DbgInfo);
1565                return result;
1566        }
1567
1568        lp->driverInfo.card_stat = lp->hcfCtx.IFB_CardStat;
1569
1570        /* Copy the driver information into the user's buffer. */
1571        urq->result = UIL_SUCCESS;
1572        copy_to_user(urq->data, &(lp->driverInfo), sizeof(lp->driverInfo));
1573
1574        DBG_LEAVE(DbgInfo);
1575        return result;
1576} /* cfg_driver_info */
1577/*============================================================================*/
1578
1579
1580
1581
1582/*******************************************************************************
1583 *      cfg_driver_identity()
1584 *******************************************************************************
1585 *
1586 *  DESCRIPTION:
1587 *
1588 *      Retrieves ID information from the card.
1589 *
1590 *  PARAMETERS:
1591 *
1592 *      urq - a pointer to the UIL request buffer
1593 *      lp  - a pointer to the device's private adapter structure
1594 *
1595 *  RETURNS:
1596 *
1597 *      UIL_SUCCESS
1598 *      UIL_ERR_xxx value otherwise
1599 *
1600 ******************************************************************************/
1601int cfg_driver_identity(struct uilreq *urq, struct wl_private *lp)
1602{
1603        int result = 0;
1604        /*------------------------------------------------------------------------*/
1605
1606
1607        DBG_FUNC("wvlan_driver_identity");
1608        DBG_ENTER(DbgInfo);
1609
1610
1611        /* Make sure that user buffer can handle the driver identity structure. */
1612        if (urq->len < sizeof(lp->driverIdentity)) {
1613                urq->len = sizeof(lp->driverIdentity);
1614                urq->result = UIL_ERR_LEN;
1615                DBG_LEAVE(DbgInfo);
1616                return result;
1617        }
1618
1619        /* Verify the user buffer. */
1620        result = verify_area(VERIFY_WRITE, urq->data, sizeof(lp->driverIdentity));
1621        if (result != 0) {
1622                urq->result = UIL_FAILURE;
1623                DBG_LEAVE(DbgInfo);
1624                return result;
1625        }
1626
1627        /* Copy the driver identity into the user's buffer. */
1628        urq->result = UIL_SUCCESS;
1629        copy_to_user(urq->data, &(lp->driverIdentity), sizeof(lp->driverIdentity));
1630
1631        DBG_LEAVE(DbgInfo);
1632        return result;
1633} /* cfg_driver_identity */
1634/*============================================================================*/
1635
1636
1637#endif  /* USE_UIL */
1638
1639
1640/* If WIRELESS_EXT is not defined, then the functions that follow will not be
1641   included in the build. */
1642/* NOTE: Are these still even needed? */
1643#ifdef WIRELESS_EXT
1644
1645
1646/*******************************************************************************
1647 *      wvlan_set_netname()
1648 *******************************************************************************
1649 *
1650 *  DESCRIPTION:
1651 *
1652 *      Set the ESSID of the card.
1653 *
1654 *  PARAMETERS:
1655 *
1656 *      wrq - a pointer to the wireless request buffer
1657 *      lp  - a pointer to the device's private adapter structure
1658 *
1659 *  RETURNS:
1660 *
1661 *      0 on success
1662 *      errno value otherwise
1663 *
1664 ******************************************************************************/
1665int wvlan_set_netname(struct net_device *dev,
1666                      struct iw_request_info *info,
1667                      union iwreq_data *wrqu,
1668                      char *extra)
1669{
1670        struct wl_private *lp = wl_priv(dev);
1671        unsigned long flags;
1672        int ret = 0;
1673        /*------------------------------------------------------------------------*/
1674
1675
1676        DBG_FUNC("wvlan_set_netname");
1677        DBG_ENTER(DbgInfo);
1678
1679        wl_lock(lp, &flags);
1680
1681        memset(lp->NetworkName, 0, sizeof(lp->NetworkName));
1682        memcpy(lp->NetworkName, extra, wrqu->data.length);
1683
1684        /* Commit the adapter parameters */
1685        wl_apply(lp);
1686        wl_unlock(lp, &flags);
1687
1688        DBG_LEAVE(DbgInfo);
1689        return ret;
1690} /* wvlan_set_netname */
1691/*============================================================================*/
1692
1693
1694
1695
1696/*******************************************************************************
1697 *      wvlan_get_netname()
1698 *******************************************************************************
1699 *
1700 *  DESCRIPTION:
1701 *
1702 *      Get the ESSID of the card.
1703 *
1704 *  PARAMETERS:
1705 *
1706 *      wrq - a pointer to the wireless request buffer
1707 *      lp  - a pointer to the device's private adapter structure
1708 *
1709 *  RETURNS:
1710 *
1711 *      0 on success
1712 *      errno value otherwise
1713 *
1714 ******************************************************************************/
1715int wvlan_get_netname(struct net_device *dev,
1716                      struct iw_request_info *info,
1717                      union iwreq_data *wrqu,
1718                      char *extra)
1719{
1720        struct wl_private *lp = wl_priv(dev);
1721        unsigned long flags;
1722        int         ret = 0;
1723        int         status = -1;
1724        wvName_t   *pName;
1725        /*------------------------------------------------------------------------*/
1726
1727
1728        DBG_FUNC("wvlan_get_netname");
1729        DBG_ENTER(DbgInfo);
1730
1731        wl_lock(lp, &flags);
1732
1733        /* Get the current network name */
1734        lp->ltvRecord.len = 1 + (sizeof(*pName) / sizeof(hcf_16));
1735        lp->ltvRecord.typ = CFG_CUR_SSID;
1736
1737        status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1738
1739        if (status == HCF_SUCCESS) {
1740                pName = (wvName_t *)&(lp->ltvRecord.u.u32);
1741
1742                memset(extra, '\0', HCF_MAX_NAME_LEN);
1743                wrqu->data.length = pName->length;
1744
1745                memcpy(extra, pName->name, pName->length);
1746        } else {
1747                ret = -EFAULT;
1748        }
1749
1750        wl_unlock(lp, &flags);
1751
1752        DBG_LEAVE(DbgInfo);
1753        return ret;
1754} /* wvlan_get_netname */
1755/*============================================================================*/
1756
1757
1758
1759
1760/*******************************************************************************
1761 *      wvlan_set_station_nickname()
1762 *******************************************************************************
1763 *
1764 *  DESCRIPTION:
1765 *
1766 *      Set the card's station nickname.
1767 *
1768 *  PARAMETERS:
1769 *
1770 *      wrq - a pointer to the wireless request buffer
1771 *      lp  - a pointer to the device's private adapter structure
1772 *
1773 *  RETURNS:
1774 *
1775 *      0 on success
1776 *      errno value otherwise
1777 *
1778 ******************************************************************************/
1779int wvlan_set_station_nickname(struct net_device *dev,
1780                      struct iw_request_info *info,
1781                      union iwreq_data *wrqu,
1782                      char *extra)
1783{
1784        struct wl_private *lp = wl_priv(dev);
1785        unsigned long flags;
1786        int         ret = 0;
1787        /*------------------------------------------------------------------------*/
1788
1789
1790        DBG_FUNC("wvlan_set_station_nickname");
1791        DBG_ENTER(DbgInfo);
1792
1793        wl_lock(lp, &flags);
1794
1795        memset(lp->StationName, 0, sizeof(lp->StationName));
1796
1797        memcpy(lp->StationName, extra, wrqu->data.length);
1798
1799        /* Commit the adapter parameters */
1800        wl_apply(lp);
1801        wl_unlock(lp, &flags);
1802
1803        DBG_LEAVE(DbgInfo);
1804        return ret;
1805} /* wvlan_set_station_nickname */
1806/*============================================================================*/
1807
1808
1809
1810
1811/*******************************************************************************
1812 *      wvlan_get_station_nickname()
1813 *******************************************************************************
1814 *
1815 *  DESCRIPTION:
1816 *
1817 *      Get the card's station nickname.
1818 *
1819 *  PARAMETERS:
1820 *
1821 *      wrq - a pointer to the wireless request buffer
1822 *      lp  - a pointer to the device's private adapter structure
1823 *
1824 *  RETURNS:
1825 *
1826 *      0 on success
1827 *      errno value otherwise
1828 *
1829 ******************************************************************************/
1830int wvlan_get_station_nickname(struct net_device *dev,
1831                      struct iw_request_info *info,
1832                      union iwreq_data *wrqu,
1833                      char *extra)
1834{
1835        struct wl_private *lp = wl_priv(dev);
1836        unsigned long flags;
1837        int         ret = 0;
1838        int         status = -1;
1839        wvName_t   *pName;
1840        /*------------------------------------------------------------------------*/
1841
1842
1843        DBG_FUNC("wvlan_get_station_nickname");
1844        DBG_ENTER(DbgInfo);
1845
1846        wl_lock(lp, &flags);
1847
1848        /* Get the current station name */
1849        lp->ltvRecord.len = 1 + (sizeof(*pName) / sizeof(hcf_16));
1850        lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1851
1852        status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1853
1854        if (status == HCF_SUCCESS) {
1855                pName = (wvName_t *)&(lp->ltvRecord.u.u32);
1856
1857                memset(extra, '\0', HCF_MAX_NAME_LEN);
1858                wrqu->data.length = pName->length;
1859                memcpy(extra, pName->name, pName->length);
1860        } else {
1861                ret = -EFAULT;
1862        }
1863
1864        wl_unlock(lp, &flags);
1865
1866/* out: */
1867        DBG_LEAVE(DbgInfo);
1868        return ret;
1869} /* wvlan_get_station_nickname */
1870/*============================================================================*/
1871
1872
1873
1874
1875/*******************************************************************************
1876 *      wvlan_set_porttype()
1877 *******************************************************************************
1878 *
1879 *  DESCRIPTION:
1880 *
1881 *      Set the card's porttype
1882 *
1883 *  PARAMETERS:
1884 *
1885 *      wrq - a pointer to the wireless request buffer
1886 *      lp  - a pointer to the device's private adapter structure
1887 *
1888 *  RETURNS:
1889 *
1890 *      0 on success
1891 *      errno value otherwise
1892 *
1893 ******************************************************************************/
1894int wvlan_set_porttype(struct net_device *dev,
1895                      struct iw_request_info *info,
1896                      union iwreq_data *wrqu,
1897                      char *extra)
1898{
1899        struct wl_private *lp = wl_priv(dev);
1900        unsigned long flags;
1901        int     ret = 0;
1902        hcf_16  portType;
1903        /*------------------------------------------------------------------------*/
1904
1905
1906        DBG_FUNC("wvlan_set_porttype");
1907        DBG_ENTER(DbgInfo);
1908
1909        wl_lock(lp, &flags);
1910
1911        /* Validate the new value */
1912        portType = *((__u32 *)extra);
1913
1914        if (!((portType == 1) || (portType == 3))) {
1915                ret = -EINVAL;
1916                goto out_unlock;
1917        }
1918
1919        lp->PortType = portType;
1920
1921        /* Commit the adapter parameters */
1922        wl_apply(lp);
1923
1924out_unlock:
1925        wl_unlock(lp, &flags);
1926
1927/* out: */
1928        DBG_LEAVE(DbgInfo);
1929        return ret;
1930}
1931
1932/*============================================================================*/
1933
1934
1935/*******************************************************************************
1936 *      wvlan_get_porttype()
1937 *******************************************************************************
1938 *
1939 *  DESCRIPTION:
1940 *
1941 *      Get the card's porttype
1942 *
1943 *  PARAMETERS:
1944 *
1945 *      wrq - a pointer to the wireless request buffer
1946 *      lp  - a pointer to the device's private adapter structure
1947 *
1948 *  RETURNS:
1949 *
1950 *      0 on success
1951 *      errno value otherwise
1952 *
1953 ******************************************************************************/
1954int wvlan_get_porttype(struct net_device *dev,
1955                      struct iw_request_info *info,
1956                      union iwreq_data *wrqu,
1957                      char *extra)
1958{
1959        struct wl_private *lp = wl_priv(dev);
1960        unsigned long flags;
1961        int     ret = 0;
1962        int     status = -1;
1963        hcf_16  *pPortType;
1964        __u32 *pData = (__u32 *)extra;
1965        /*------------------------------------------------------------------------*/
1966
1967
1968        DBG_FUNC("wvlan_get_porttype");
1969        DBG_ENTER(DbgInfo);
1970
1971        wl_lock(lp, &flags);
1972
1973        /* Get the current port type */
1974        lp->ltvRecord.len = 1 + (sizeof(*pPortType) / sizeof(hcf_16));
1975        lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1976
1977        status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1978
1979        if (status == HCF_SUCCESS) {
1980                pPortType = (hcf_16 *)&(lp->ltvRecord.u.u32);
1981
1982                *pData = CNV_LITTLE_TO_INT(*pPortType);
1983        } else {
1984            ret = -EFAULT;
1985        }
1986
1987        wl_unlock(lp, &flags);
1988
1989/* out: */
1990        DBG_LEAVE(DbgInfo);
1991        return ret;
1992} /* wvlan_get_porttype */
1993/*============================================================================*/
1994
1995#endif  /* WIRELESS_EXT */
1996
1997
1998
1999
2000#ifdef USE_RTS
2001/*******************************************************************************
2002 *      wvlan_rts()
2003 *******************************************************************************
2004 *
2005 *  DESCRIPTION:
2006 *
2007 *      IOCTL handler for RTS commands
2008 *
2009 *  PARAMETERS:
2010 *
2011 *      rrq - a pointer to the rts request buffer
2012 *      lp  - a pointer to the device's private adapter structure
2013 *
2014 *  RETURNS:
2015 *
2016 *      0 on success
2017 *      errno value otherwise
2018 *
2019 ******************************************************************************/
2020int wvlan_rts(struct rtsreq *rrq, __u32 io_base)
2021{
2022        int ioctl_ret = 0;
2023        /*------------------------------------------------------------------------*/
2024
2025
2026        DBG_FUNC("wvlan_rts");
2027        DBG_ENTER(DbgInfo);
2028
2029
2030        DBG_PRINT("io_base: 0x%08x\n", io_base);
2031
2032        switch (rrq->typ) {
2033        case WL_IOCTL_RTS_READ:
2034                DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- WL_IOCTL_RTS_READ\n");
2035                rrq->data[0] = IN_PORT_WORD(io_base + rrq->reg);
2036                DBG_TRACE(DbgInfo, "  reg 0x%04x ==> 0x%04x\n", rrq->reg, CNV_LITTLE_TO_SHORT(rrq->data[0]));
2037                break;
2038        case WL_IOCTL_RTS_WRITE:
2039                DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- WL_IOCTL_RTS_WRITE\n");
2040                OUT_PORT_WORD(io_base + rrq->reg, rrq->data[0]);
2041                DBG_TRACE(DbgInfo, "  reg 0x%04x <== 0x%04x\n", rrq->reg, CNV_LITTLE_TO_SHORT(rrq->data[0]));
2042                break;
2043        case WL_IOCTL_RTS_BATCH_READ:
2044                DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- WL_IOCTL_RTS_BATCH_READ\n");
2045                IN_PORT_STRING_16(io_base + rrq->reg, rrq->data, rrq->len);
2046                DBG_TRACE(DbgInfo, "  reg 0x%04x ==> %d bytes\n", rrq->reg, rrq->len * sizeof(__u16));
2047                break;
2048        case WL_IOCTL_RTS_BATCH_WRITE:
2049                DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- WL_IOCTL_RTS_BATCH_WRITE\n");
2050                OUT_PORT_STRING_16(io_base + rrq->reg, rrq->data, rrq->len);
2051                DBG_TRACE(DbgInfo, "  reg 0x%04x <== %d bytes\n", rrq->reg, rrq->len * sizeof(__u16));
2052                break;
2053        default:
2054
2055                DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- UNSUPPORTED RTS CODE: 0x%X", rrq->typ);
2056                ioctl_ret = -EOPNOTSUPP;
2057                break;
2058        }
2059
2060        DBG_LEAVE(DbgInfo);
2061        return ioctl_ret;
2062} /* wvlan_rts */
2063/*============================================================================*/
2064
2065#endif  /* USE_RTS */
2066