/*******************************************************************************
 * Agere Systems Inc.
 * Wireless device driver for Linux (wlags49).
 *
 * Copyright (c) 1998-2003 Agere Systems Inc. 
 * All rights reserved.
 *   http://www.agere.com
 *
 * Initially developed by TriplePoint, Inc.
 *   http://www.triplepoint.com
 *
 *------------------------------------------------------------------------------
 *
 *   This file contains the main driver entry points and other adapter
 *   specific routines.
 *
 *------------------------------------------------------------------------------
 *
 * SOFTWARE LICENSE
 *
 * This software is provided subject to the following terms and conditions,
 * which you should read carefully before using the software.  Using this
 * software indicates your acceptance of these terms and conditions.  If you do
 * not agree with these terms and conditions, do not use the software.
 *
 * Copyright © 2003 Agere Systems Inc.
 * All rights reserved.
 *
 * Redistribution and use in source or binary forms, with or without
 * modifications, are permitted provided that the following conditions are met:
 *
 * . Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following Disclaimer as comments in the code as
 *    well as in the documentation and/or other materials provided with the
 *    distribution.
 * 
 * . Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following Disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 
 * . Neither the name of Agere Systems Inc. nor the names of the contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * Disclaimer
 *
 * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 ******************************************************************************/




/*******************************************************************************
 * VERSION CONTROL INFORMATION
 *******************************************************************************
 *
 * $Author: vjs $
 * $Date: 2004/03/16 17:39:47 $
 * $Revision: 1.67 $
 * $Source: /cvsroot/wifi/wl_lkm/wireless/wl_main.c,v $
 *
 ******************************************************************************/




/*******************************************************************************
 *  include files
 ******************************************************************************/
#include <wireless/wl_version.h>

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/tqueue.h>
#include <linux/in.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/bitops.h>

#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/ioport.h>

#include <hcf/debug.h>

#include <hcf.h>
#include <dhf.h>
#include <hcfdef.h>

#include <wireless/wl_if.h>
#include <wireless/wl_internal.h>
#include <wireless/wl_util.h>
#include <wireless/wl_main.h>
#include <wireless/wl_netdev.h>
#include <wireless/wl_wext.h>

#ifdef USE_PROFILE
#include <wireless/wl_profile.h>
#endif  /* USE_PROFILE */

#ifdef BUS_PCMCIA
#include <wireless/wl_cs.h>
#endif  /* BUS_PCMCIA */

#ifdef BUS_PCI
#include <wireless/wl_pci.h>
#endif  /* BUS_PCI */




/*******************************************************************************
 *	macro defintions
 ******************************************************************************/
#define VALID_PARAM(C) \
    { \
        if (!(C)) \
        { \
            printk(KERN_INFO "Wireless, parameter error: \"%s\"\n", #C); \
            goto failed; \
        } \
    }




/*******************************************************************************
 *	local functions
 ******************************************************************************/
void wl_isr_handler( struct wl_private *lp );




/*******************************************************************************
 * module parameter definitions - set with 'insmod'
 ******************************************************************************/
static p_u16    irq_mask                = 0xdeb8; // IRQ3,4,5,7,9,10,11,12,14,15
static p_s8     irq_list[4]             = { -1 };

MODULE_PARM(irq_mask,               "h");
MODULE_PARM_DESC(irq_mask,               "IRQ mask [0xdeb8]");
MODULE_PARM(irq_list,               "1-4b");
MODULE_PARM_DESC(irq_list,               "IRQ list [<irq_mask>]");


/* THESE MODULE PARAMETERS ARE TO BE DEPRECATED IN FAVOR OF A NAMING CONVENTION
   WHICH IS INLINE WITH THE FORTHCOMING WAVELAN API */
#ifdef USE_OLD_PARMS

static p_char  *network_name            = PARM_DEFAULT_SSID;
static p_u8     channel                 = PARM_DEFAULT_CHANNEL;
static p_u8     distance_between_aps    = PARM_DEFAULT_SYSTEM_SCALE;
static p_u8     transmit_rate           = PARM_DEFAULT_TX_RATE;
static p_u16    medium_reservation      = PARM_DEFAULT_RTS_THRESHOLD;
static p_char  *microwave_robustness    = PARM_DEFAULT_MICROWAVE_ROBUSTNESS_STR;
static p_u8     mac_address[ETH_ALEN]   = PARM_DEFAULT_MAC_ADDRESS;
static p_char  *station_name            = PARM_DEFAULT_OWN_NAME;
static p_u16    enable_encryption       = PARM_DEFAULT_ENABLE_ENCRYPTION;
static p_char  *key_1                   = "";
static p_char  *key_2                   = "";
static p_char  *key_3                   = "";
static p_char  *key_4                   = "";
static p_u8     transmit_key_id         = PARM_DEFAULT_TX_KEY;
static p_u8     multicast_rate          = PARM_DEFAULT_MULTICAST_RATE;

static p_u16    auth_key_mgmt_suite     = PARM_DEFAULT_AUTH_KEY_MGMT_SUITE;

#if (HCF_TYPE) & HCF_TYPE_STA
static p_u8     card_power_management   = WVLAN_PM_STATE_DISABLED;
static p_u8     port_type               = PARM_DEFAULT_PORT_TYPE;
static p_char  *create_ibss             = PARM_DEFAULT_CREATE_IBSS_STR;
static p_char  *receive_all_multicasts  = PARM_DEFAULT_RX_MULTICAST_STR;
static p_u16    maximum_sleep_duration  = PARM_DEFAULT_MAX_PM_SLEEP;
static p_u8     authentication          = PARM_DEFAULT_AUTHENTICATION;
static p_u16    atim_window             = PARM_DEFAULT_OWN_ATIM_WINDOW;
static p_u16    holdover_duration       = PARM_DEFAULT_PM_HOLDOVER_DURATION;
static p_char   *promiscuous_mode       = PARM_DEFAULT_PROMISCUOUS_MODE_STR;
#endif /* HCF_STA */


#if (HCF_TYPE) & HCF_TYPE_STA
static p_u8     download_firmware       = WVLAN_DRV_MODE_STA;
#else
static p_u8     download_firmware       = WVLAN_DRV_MODE_AP;
#endif /* HCF_STA */


#if (HCF_TYPE) & HCF_TYPE_AP
static p_u8     dtim_period             = PARM_DEFAULT_OWN_DTIM_PERIOD;
static p_char  *closed_system           = PARM_DEFAULT_REJECT_ANY_STR;
static p_char  *deny_nonencrypted       = PARM_DEFAULT_EXCLUDE_UNENCRYPTED_STR;
static p_char  *multicast_pm_buffering  = PARM_DEFAULT_MULTICAST_PM_BUFFERING_STR;
static p_char  *intra_bss_relay         = PARM_DEFAULT_INTRA_BSS_RELAY_STR;
static p_u16    rts_threshold_1         = PARM_DEFAULT_RTS_THRESHOLD;
static p_u16    rts_threshold_2         = PARM_DEFAULT_RTS_THRESHOLD;
static p_u16    rts_threshold_3         = PARM_DEFAULT_RTS_THRESHOLD;
static p_u16    rts_threshold_4         = PARM_DEFAULT_RTS_THRESHOLD;
static p_u16    rts_threshold_5         = PARM_DEFAULT_RTS_THRESHOLD;
static p_u16    rts_threshold_6         = PARM_DEFAULT_RTS_THRESHOLD;
static p_u8     tx_rate_control_1       = PARM_DEFAULT_TX_RATE;
static p_u8     tx_rate_control_2       = PARM_DEFAULT_TX_RATE;
static p_u8     tx_rate_control_3       = PARM_DEFAULT_TX_RATE;
static p_u8     tx_rate_control_4       = PARM_DEFAULT_TX_RATE;
static p_u8     tx_rate_control_5       = PARM_DEFAULT_TX_RATE;
static p_u8     tx_rate_control_6       = PARM_DEFAULT_TX_RATE;
static p_u8     wds_address_1[ETH_ALEN] = PARM_DEFAULT_MAC_ADDRESS;
static p_u8     wds_address_2[ETH_ALEN] = PARM_DEFAULT_MAC_ADDRESS;
static p_u8     wds_address_3[ETH_ALEN] = PARM_DEFAULT_MAC_ADDRESS;
static p_u8     wds_address_4[ETH_ALEN] = PARM_DEFAULT_MAC_ADDRESS;
static p_u8     wds_address_5[ETH_ALEN] = PARM_DEFAULT_MAC_ADDRESS;
static p_u8     wds_address_6[ETH_ALEN] = PARM_DEFAULT_MAC_ADDRESS;
#endif /* HCF_AP */


MODULE_PARM(network_name,           "s");
MODULE_PARM_DESC(network_name,           "Network Name (<string>) [ANY]");
MODULE_PARM(channel,                "b");
MODULE_PARM_DESC(channel,                "Channel (0 - 14) [0]");
MODULE_PARM(distance_between_aps,   "b");
MODULE_PARM_DESC(distance_between_aps,   "Distance Between APs (1 - 3) [1]");
MODULE_PARM(transmit_rate,          "b");
MODULE_PARM_DESC(transmit_rate,          "Transmit Rate Control (1 - 7) [3]");
MODULE_PARM(medium_reservation,     "h");
MODULE_PARM_DESC(medium_reservation,     "Medium Reservation (RTS/CTS Fragment Length) (256 - 2347) [2347]");
MODULE_PARM(microwave_robustness,   "s");
MODULE_PARM_DESC(microwave_robustness,   "Microwave Oven Robustness Enabled (<string> N or Y) [N]");
MODULE_PARM(station_name,           "s");
MODULE_PARM_DESC(station_name,           "Station Name (<string>) [Linux]");
MODULE_PARM(enable_encryption,      "s");
MODULE_PARM_DESC(enable_encryption,      "Enable Encryption (<string> N or Y) [N]");
MODULE_PARM(key_1,                  "s");
MODULE_PARM_DESC(key_1,                  "Data Encryption Key 1 (<string>) []");
MODULE_PARM(key_2,                  "s");
MODULE_PARM_DESC(key_2,                  "Data Encryption Key 2 (<string>) []");
MODULE_PARM(key_3,                  "s");
MODULE_PARM_DESC(key_3,                  "Data Encryption Key 3 (<string>) []");
MODULE_PARM(key_4,                  "s");
MODULE_PARM_DESC(key_4,                  "Data Encryption Key 4 (<string>) []");
MODULE_PARM(transmit_key_id,        "b");
MODULE_PARM_DESC(transmit_key_id,        "Transmit Key ID (1 - 4) [1]");
MODULE_PARM(multicast_rate,         "b");
MODULE_PARM_DESC(multicast_rate,         "Multicast Rate (1 - 4) [2]");
MODULE_PARM(download_firmware,      "b");
MODULE_PARM_DESC(download_firmware,      "Download firmware (0 - 2) [1,2]");


MODULE_PARM(auth_key_mgmt_suite,   "b");
MODULE_PARM_DESC(auth_key_mgmt_suite,    "Authentication Key Management suite (0-4) [0]");


#if (HCF_TYPE) & HCF_TYPE_STA
MODULE_PARM(card_power_management,  "b");
MODULE_PARM_DESC(card_power_management,  "Power Management State (0 - 2) [0]");
MODULE_PARM(port_type,              "b");
MODULE_PARM_DESC(port_type,              "Port Type (1 - 3) [1]");
MODULE_PARM(create_ibss,            "s");
MODULE_PARM_DESC(create_ibss,            "Create IBSS (<string> N or Y) [N]");
MODULE_PARM(receive_all_multicasts, "s");
MODULE_PARM_DESC(receive_all_multicasts, "Multicast Receive Enable (<string> N or Y) [Y]");
MODULE_PARM(maximum_sleep_duration, "h");
MODULE_PARM_DESC(maximum_sleep_duration, "Maximum Power Management Sleep Duration (0 - 65535) [100]");
MODULE_PARM(mac_address,            "6b");
MODULE_PARM_DESC(mac_address,            "Hardware Ethernet Address ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [<factory value>]");
MODULE_PARM(authentication,         "b");
MODULE_PARM_DESC(authentication,         "Authentication Type (0-2) [0] 0=Open 1=SharedKey 2=LEAP");
MODULE_PARM(atim_window,            "b");
MODULE_PARM_DESC(atim_window,            "ATIM Window time in TU for IBSS creation (0-100) [0]");
MODULE_PARM(holdover_duration,      "b");
MODULE_PARM_DESC(holdover_duration,       "Time station remains awake after MAC frame transfer when PM is on (0-65535) [100]");
MODULE_PARM(promiscuous_mode,       "s");
MODULE_PARM_DESC(promiscuous_mode,       "Promiscuous Mode Enable (<string> Y or N ) [N]" );
#endif /* HCF_STA */


#if (HCF_TYPE) & HCF_TYPE_AP
MODULE_PARM(dtim_period,            "b");
MODULE_PARM_DESC(dtim_period,            "DTIM Period (0 - 255) [1]");
MODULE_PARM(closed_system,          "s");
MODULE_PARM_DESC(closed_system,          "Closed System (<string> N or Y) [N]");
MODULE_PARM(deny_nonencrypted,      "s");
MODULE_PARM_DESC(deny_nonencrypted,      "Deny non-encrypted (<string> N or Y) [Y]");
MODULE_PARM(multicast_pm_buffering, "s");
MODULE_PARM_DESC(multicast_pm_buffering, "Buffer MAC frames for Tx after DTIM (<string> Y or N) [Y]");
MODULE_PARM(intra_bss_relay,        "s");
MODULE_PARM_DESC(intra_bss_relay,        "IntraBSS Relay (<string> N or Y) [Y]");
MODULE_PARM(rts_threshold_1,        "h");
MODULE_PARM_DESC(rts_threshold_1,        "RTS Threshold, WDS Port 1 (256 - 2347) [2347]");
MODULE_PARM(rts_threshold_2,        "h");
MODULE_PARM_DESC(rts_threshold_2,        "RTS Threshold, WDS Port 2 (256 - 2347) [2347]");
MODULE_PARM(rts_threshold_3,        "h");
MODULE_PARM_DESC(rts_threshold_3,        "RTS Threshold, WDS Port 3 (256 - 2347) [2347]");
MODULE_PARM(rts_threshold_4,        "h");
MODULE_PARM_DESC(rts_threshold_4,        "RTS Threshold, WDS Port 4 (256 - 2347) [2347]");
MODULE_PARM(rts_threshold_5,        "h");
MODULE_PARM_DESC(rts_threshold_5,        "RTS Threshold, WDS Port 5 (256 - 2347) [2347]");
MODULE_PARM(rts_threshold_6,        "h");
MODULE_PARM_DESC(rts_threshold_6,        "RTS Threshold, WDS Port 6 (256 - 2347) [2347]");
MODULE_PARM(tx_rate_control_1,      "b");
MODULE_PARM_DESC(tx_rate_control_1,      "Transmit Rate Control, WDS Port 1 (1 - 7) [3]");
MODULE_PARM(tx_rate_control_2,      "b");
MODULE_PARM_DESC(tx_rate_control_2,      "Transmit Rate Control, WDS Port 2 (1 - 7) [3]");
MODULE_PARM(tx_rate_control_3,      "b");
MODULE_PARM_DESC(tx_rate_control_3,      "Transmit Rate Control, WDS Port 3 (1 - 7) [3]");
MODULE_PARM(tx_rate_control_4,      "b");
MODULE_PARM_DESC(tx_rate_control_4,      "Transmit Rate Control, WDS Port 4 (1 - 7) [3]");
MODULE_PARM(tx_rate_control_5,      "b");
MODULE_PARM_DESC(tx_rate_control_5,      "Transmit Rate Control, WDS Port 5 (1 - 7) [3]");
MODULE_PARM(tx_rate_control_6,      "b");
MODULE_PARM_DESC(tx_rate_control_6,      "Transmit Rate Control, WDS Port 6 (1 - 7) [3]");
MODULE_PARM(wds_address_1,          "6b");
MODULE_PARM_DESC(wds_address_1,     "MAC Address, WDS Port 1 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]");
MODULE_PARM(wds_address_2,          "6b");
MODULE_PARM_DESC(wds_address_2,     "MAC Address, WDS Port 2 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]");
MODULE_PARM(wds_address_3,          "6b");
MODULE_PARM_DESC(wds_address_3,     "MAC Address, WDS Port 3 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]");
MODULE_PARM(wds_address_4,          "6b");
MODULE_PARM_DESC(wds_address_4,     "MAC Address, WDS Port 4 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]");
MODULE_PARM(wds_address_5,          "6b");
MODULE_PARM_DESC(wds_address_5,     "MAC Address, WDS Port 5 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]");
MODULE_PARM(wds_address_6,          "6b");
MODULE_PARM_DESC(wds_address_6,     "MAC Address, WDS Port 6 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]");
#endif /* HCF_AP */

#endif /* USE_OLD_PARMS */
/* END DEPRECATED PARAMETERS */


/* START NEW PARAMETERS */
static p_char  *PARM_DESIRED_SSID           = PARM_DEFAULT_SSID;
static p_char  *PARM_OWN_SSID               = PARM_DEFAULT_SSID;
static p_u8     PARM_CHANNEL                = PARM_DEFAULT_CHANNEL;
static p_u8     PARM_SYSTEM_SCALE           = PARM_DEFAULT_SYSTEM_SCALE;
static p_u8     PARM_TX_RATE                = PARM_DEFAULT_TX_RATE;
static p_u16    PARM_RTS_THRESHOLD          = PARM_DEFAULT_RTS_THRESHOLD;
static p_char  *PARM_MICROWAVE_ROBUSTNESS   = PARM_DEFAULT_MICROWAVE_ROBUSTNESS_STR;
static p_u8     PARM_MAC_ADDRESS[ETH_ALEN]  = PARM_DEFAULT_MAC_ADDRESS;
static p_char  *PARM_OWN_NAME               = PARM_DEFAULT_OWN_NAME;

static p_u16    PARM_ENABLE_ENCRYPTION      = PARM_DEFAULT_ENABLE_ENCRYPTION;

static p_char  *PARM_KEY1                   = "";
static p_char  *PARM_KEY2                   = "";
static p_char  *PARM_KEY3                   = "";
static p_char  *PARM_KEY4                   = "";
static p_u8     PARM_TX_KEY                 = PARM_DEFAULT_TX_KEY;
static p_u8     PARM_MULTICAST_RATE         = PARM_DEFAULT_MULTICAST_RATE;

static p_u16    PARM_AUTH_KEY_MGMT_SUITE    = PARM_DEFAULT_AUTH_KEY_MGMT_SUITE;

#if (HCF_TYPE) & HCF_TYPE_STA
static p_u8     PARM_PM_ENABLED             = WVLAN_PM_STATE_DISABLED;
static p_u8     PARM_PORT_TYPE              = PARM_DEFAULT_PORT_TYPE;
static p_char  *PARM_CREATE_IBSS            = PARM_DEFAULT_CREATE_IBSS_STR;
static p_char  *PARM_RX_MULTICAST           = PARM_DEFAULT_RX_MULTICAST_STR;
static p_u16    PARM_MAX_SLEEP              = PARM_DEFAULT_MAX_PM_SLEEP;
static p_u8     PARM_AUTHENTICATION         = PARM_DEFAULT_AUTHENTICATION;
static p_u16    PARM_OWN_ATIM_WINDOW        = PARM_DEFAULT_OWN_ATIM_WINDOW;
static p_u16    PARM_PM_HOLDOVER_DURATION   = PARM_DEFAULT_PM_HOLDOVER_DURATION;
static p_char   *PARM_PROMISCUOUS_MODE      = PARM_DEFAULT_PROMISCUOUS_MODE_STR;
#endif /* HCF_STA */


#if (HCF_TYPE) & HCF_TYPE_STA
static p_u8     PARM_DOWNLOAD_FIRMWARE      = WVLAN_DRV_MODE_STA;
#else
static p_u8     PARM_DOWNLOAD_FIRMWARE      = WVLAN_DRV_MODE_AP;
#endif /* HCF_STA */


#if (HCF_TYPE) & HCF_TYPE_AP
static p_u8     PARM_OWN_DTIM_PERIOD        = PARM_DEFAULT_OWN_DTIM_PERIOD;
static p_char  *PARM_REJECT_ANY             = PARM_DEFAULT_REJECT_ANY_STR;
static p_char  *PARM_EXCLUDE_UNENCRYPTED    = PARM_DEFAULT_EXCLUDE_UNENCRYPTED_STR;
static p_char  *PARM_MULTICAST_PM_BUFFERING = PARM_DEFAULT_MULTICAST_PM_BUFFERING_STR;
static p_char  *PARM_INTRA_BSS_RELAY        = PARM_DEFAULT_INTRA_BSS_RELAY_STR;
static p_u16    PARM_RTS_THRESHOLD1         = PARM_DEFAULT_RTS_THRESHOLD;
static p_u16    PARM_RTS_THRESHOLD2         = PARM_DEFAULT_RTS_THRESHOLD;
static p_u16    PARM_RTS_THRESHOLD3         = PARM_DEFAULT_RTS_THRESHOLD;
static p_u16    PARM_RTS_THRESHOLD4         = PARM_DEFAULT_RTS_THRESHOLD;
static p_u16    PARM_RTS_THRESHOLD5         = PARM_DEFAULT_RTS_THRESHOLD;
static p_u16    PARM_RTS_THRESHOLD6         = PARM_DEFAULT_RTS_THRESHOLD;
static p_u8     PARM_TX_RATE1               = PARM_DEFAULT_TX_RATE;
static p_u8     PARM_TX_RATE2               = PARM_DEFAULT_TX_RATE;
static p_u8     PARM_TX_RATE3               = PARM_DEFAULT_TX_RATE;
static p_u8     PARM_TX_RATE4               = PARM_DEFAULT_TX_RATE;
static p_u8     PARM_TX_RATE5               = PARM_DEFAULT_TX_RATE;
static p_u8     PARM_TX_RATE6               = PARM_DEFAULT_TX_RATE;
static p_u8     PARM_WDS_ADDRESS1[ETH_ALEN] = PARM_DEFAULT_MAC_ADDRESS;
static p_u8     PARM_WDS_ADDRESS2[ETH_ALEN] = PARM_DEFAULT_MAC_ADDRESS;
static p_u8     PARM_WDS_ADDRESS3[ETH_ALEN] = PARM_DEFAULT_MAC_ADDRESS;
static p_u8     PARM_WDS_ADDRESS4[ETH_ALEN] = PARM_DEFAULT_MAC_ADDRESS;
static p_u8     PARM_WDS_ADDRESS5[ETH_ALEN] = PARM_DEFAULT_MAC_ADDRESS;
static p_u8     PARM_WDS_ADDRESS6[ETH_ALEN] = PARM_DEFAULT_MAC_ADDRESS;
#endif /* HCF_AP */


MODULE_PARM(PARM_DESIRED_SSID,          "s");
MODULE_PARM_DESC(PARM_DESIRED_SSID,             "Network Name (<string>) [ANY]");
MODULE_PARM(PARM_OWN_SSID,              "s");
MODULE_PARM_DESC(PARM_OWN_SSID,                 "Network Name (<string>) [ANY]");
MODULE_PARM(PARM_CHANNEL,               "b");
MODULE_PARM_DESC(PARM_CHANNEL,                  "Channel (0 - 14) [0]");
MODULE_PARM(PARM_SYSTEM_SCALE,          "b");
MODULE_PARM_DESC(PARM_SYSTEM_SCALE,             "Distance Between APs (1 - 3) [1]");
MODULE_PARM(PARM_TX_RATE,               "b");
MODULE_PARM_DESC(PARM_TX_RATE,                  "Transmit Rate Control (1 - 7) [3]");
MODULE_PARM(PARM_RTS_THRESHOLD,         "h");
MODULE_PARM_DESC(PARM_RTS_THRESHOLD,            "Medium Reservation (RTS/CTS Fragment Length) (256 - 2347) [2347]");
MODULE_PARM(PARM_MICROWAVE_ROBUSTNESS,  "s");
MODULE_PARM_DESC(PARM_MICROWAVE_ROBUSTNESS,     "Microwave Oven Robustness Enabled (<string> N or Y) [N]");
MODULE_PARM(PARM_OWN_NAME,              "s");
MODULE_PARM_DESC(PARM_OWN_NAME,                 "Station Name (<string>) [Linux]");

MODULE_PARM(PARM_ENABLE_ENCRYPTION,     "b");
MODULE_PARM_DESC(PARM_ENABLE_ENCRYPTION,        "Encryption Mode (0 - 7) [0]");

MODULE_PARM(PARM_KEY1,                  "s");
MODULE_PARM_DESC(PARM_KEY1,                     "Data Encryption Key 1 (<string>) []");
MODULE_PARM(PARM_KEY2,                  "s");
MODULE_PARM_DESC(PARM_KEY2,                     "Data Encryption Key 2 (<string>) []");
MODULE_PARM(PARM_KEY3,                  "s");
MODULE_PARM_DESC(PARM_KEY3,                     "Data Encryption Key 3 (<string>) []");
MODULE_PARM(PARM_KEY4,                  "s");
MODULE_PARM_DESC(PARM_KEY4,                     "Data Encryption Key 4 (<string>) []");
MODULE_PARM(PARM_TX_KEY,                "b");
MODULE_PARM_DESC(PARM_TX_KEY,                   "Transmit Key ID (1 - 4) [1]");
MODULE_PARM(PARM_MULTICAST_RATE,        "b");
MODULE_PARM_DESC(PARM_MULTICAST_RATE,           "Multicast Rate (1 - 4) [2]");
MODULE_PARM(PARM_DOWNLOAD_FIRMWARE,     "b");
MODULE_PARM_DESC(PARM_DOWNLOAD_FIRMWARE,        "Download firmware (0 - 2) [1,2]");

MODULE_PARM(PARM_AUTH_KEY_MGMT_SUITE,   "b");
MODULE_PARM_DESC(PARM_AUTH_KEY_MGMT_SUITE,      "Authentication Key Management suite (0-4) [0]");

#if (HCF_TYPE) & HCF_TYPE_STA
MODULE_PARM(PARM_PM_ENABLED,            "b");
MODULE_PARM_DESC(PARM_PM_ENABLED,               "Power Management State (0 - 2) [0]");
MODULE_PARM(PARM_PORT_TYPE,             "b");
MODULE_PARM_DESC(PARM_PORT_TYPE,                "Port Type (1 - 3) [1]");
MODULE_PARM(PARM_CREATE_IBSS,           "s");
MODULE_PARM_DESC(PARM_CREATE_IBSS,              "Create IBSS (<string> N or Y) [N]");
MODULE_PARM(PARM_RX_MULTICAST,          "s");
MODULE_PARM_DESC(PARM_RX_MULTICAST,             "Multicast Receive Enable (<string> N or Y) [Y]");
MODULE_PARM(PARM_MAX_SLEEP,             "h");
MODULE_PARM_DESC(PARM_MAX_SLEEP,                "Maximum Power Management Sleep Duration (0 - 65535) [100]");
MODULE_PARM(PARM_MAC_ADDRESS,           "6b");
MODULE_PARM_DESC(PARM_MAC_ADDRESS,              "Hardware Ethernet Address ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [<factory value>]");
MODULE_PARM(PARM_AUTHENTICATION,        "b");
MODULE_PARM_DESC(PARM_AUTHENTICATION,           "Authentication Type (0-2) [0] 0=Open 1=SharedKey 2=LEAP");
MODULE_PARM(PARM_OWN_ATIM_WINDOW,       "b");
MODULE_PARM_DESC(PARM_OWN_ATIM_WINDOW,          "ATIM Window time in TU for IBSS creation (0-100) [0]");
MODULE_PARM(PARM_PM_HOLDOVER_DURATION,  "b");
MODULE_PARM_DESC(PARM_PM_HOLDOVER_DURATION,     "Time station remains awake after MAC frame transfer when PM is on (0-65535) [100]");
MODULE_PARM(PARM_PROMISCUOUS_MODE,      "s");
MODULE_PARM_DESC(PARM_PROMISCUOUS_MODE,         "Promiscuous Mode Enable (<string> Y or N ) [N]" );
#endif /* HCF_STA */


#if (HCF_TYPE) & HCF_TYPE_AP
MODULE_PARM(PARM_OWN_DTIM_PERIOD,       "b");
MODULE_PARM_DESC(PARM_OWN_DTIM_PERIOD,          "DTIM Period (0 - 255) [1]");
MODULE_PARM(PARM_REJECT_ANY,            "s");
MODULE_PARM_DESC(PARM_REJECT_ANY,               "Closed System (<string> N or Y) [N]");
MODULE_PARM(PARM_EXCLUDE_UNENCRYPTED,   "s");
MODULE_PARM_DESC(PARM_EXCLUDE_UNENCRYPTED,      "Deny non-encrypted (<string> N or Y) [Y]");
MODULE_PARM(PARM_MULTICAST_PM_BUFFERING,"s");
MODULE_PARM_DESC(PARM_MULTICAST_PM_BUFFERING,   "Buffer MAC frames for Tx after DTIM (<string> Y or N) [Y]");
MODULE_PARM(PARM_INTRA_BSS_RELAY,       "s");
MODULE_PARM_DESC(PARM_INTRA_BSS_RELAY,          "IntraBSS Relay (<string> N or Y) [Y]");
MODULE_PARM(PARM_RTS_THRESHOLD1,        "h");
MODULE_PARM_DESC(PARM_RTS_THRESHOLD1,           "RTS Threshold, WDS Port 1 (256 - 2347) [2347]");
MODULE_PARM(PARM_RTS_THRESHOLD2,        "h");
MODULE_PARM_DESC(PARM_RTS_THRESHOLD2,           "RTS Threshold, WDS Port 2 (256 - 2347) [2347]");
MODULE_PARM(PARM_RTS_THRESHOLD3,        "h");
MODULE_PARM_DESC(PARM_RTS_THRESHOLD3,           "RTS Threshold, WDS Port 3 (256 - 2347) [2347]");
MODULE_PARM(PARM_RTS_THRESHOLD4,        "h");
MODULE_PARM_DESC(PARM_RTS_THRESHOLD4,           "RTS Threshold, WDS Port 4 (256 - 2347) [2347]");
MODULE_PARM(PARM_RTS_THRESHOLD5,        "h");
MODULE_PARM_DESC(PARM_RTS_THRESHOLD5,           "RTS Threshold, WDS Port 5 (256 - 2347) [2347]");
MODULE_PARM(PARM_RTS_THRESHOLD6,        "h");
MODULE_PARM_DESC(PARM_RTS_THRESHOLD6,           "RTS Threshold, WDS Port 6 (256 - 2347) [2347]");
MODULE_PARM(PARM_TX_RATE1,              "b");
MODULE_PARM_DESC(PARM_TX_RATE1,                 "Transmit Rate Control, WDS Port 1 (1 - 7) [3]");
MODULE_PARM(PARM_TX_RATE2,              "b");
MODULE_PARM_DESC(PARM_TX_RATE2,                 "Transmit Rate Control, WDS Port 2 (1 - 7) [3]");
MODULE_PARM(PARM_TX_RATE3,              "b");
MODULE_PARM_DESC(PARM_TX_RATE3,                 "Transmit Rate Control, WDS Port 3 (1 - 7) [3]");
MODULE_PARM(PARM_TX_RATE4,              "b");
MODULE_PARM_DESC(PARM_TX_RATE4,                 "Transmit Rate Control, WDS Port 4 (1 - 7) [3]");
MODULE_PARM(PARM_TX_RATE5,              "b");
MODULE_PARM_DESC(PARM_TX_RATE5,                 "Transmit Rate Control, WDS Port 5 (1 - 7) [3]");
MODULE_PARM(PARM_TX_RATE6,              "b");
MODULE_PARM_DESC(PARM_TX_RATE6,                 "Transmit Rate Control, WDS Port 6 (1 - 7) [3]");
MODULE_PARM(PARM_WDS_ADDRESS1,          "6b");
MODULE_PARM_DESC(PARM_WDS_ADDRESS1,             "MAC Address, WDS Port 1 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]");
MODULE_PARM(PARM_WDS_ADDRESS2,          "6b");
MODULE_PARM_DESC(PARM_WDS_ADDRESS2,             "MAC Address, WDS Port 2 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]");
MODULE_PARM(PARM_WDS_ADDRESS3,          "6b");
MODULE_PARM_DESC(PARM_WDS_ADDRESS3,             "MAC Address, WDS Port 3 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]");
MODULE_PARM(PARM_WDS_ADDRESS4,          "6b");
MODULE_PARM_DESC(PARM_WDS_ADDRESS4,             "MAC Address, WDS Port 4 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]");
MODULE_PARM(PARM_WDS_ADDRESS5,          "6b");
MODULE_PARM_DESC(PARM_WDS_ADDRESS5,             "MAC Address, WDS Port 5 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]");
MODULE_PARM(PARM_WDS_ADDRESS6,          "6b");
MODULE_PARM_DESC(PARM_WDS_ADDRESS6,             "MAC Address, WDS Port 6 ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [{0}]");
#endif /* HCF_AP */

/* END NEW PARAMETERS */


/*******************************************************************************
 * debugging specifics
 ******************************************************************************/
#if DBG

static p_u32    pc_debug = DBG_LVL;
MODULE_PARM(pc_debug, "i");
static p_u32    debug_flags = DBG_DEFAULTS;
MODULE_PARM(debug_flags, "l");

dbg_info_t   wl_info = { MODULE_NAME_EXT, 0, 0 };
dbg_info_t  *DbgInfo = &wl_info;

#endif /* DBG */


#ifdef USE_RTS

static p_char  *useRTS = "N";
MODULE_PARM( useRTS, "s" );
MODULE_PARM_DESC( useRTS, "Use RTS test interface (<string> N or Y) [N]" );

#endif  /* USE_RTS */


/*******************************************************************************
 * firmware download specifics
 ******************************************************************************/
extern struct CFG_RANGE2_STRCT BASED
    cfg_drv_act_ranges_pri; 	    // describes primary-actor range of HCF

#if (HCF_TYPE) & HCF_TYPE_AP
extern memimage ap;                 // AP firmware image to be downloaded
#endif /* HCF_AP */

#if (HCF_TYPE) & HCF_TYPE_STA
extern memimage station;            // STA firmware image to be downloaded
#endif /* HCF_STA */




/*******************************************************************************
 *	wl_insert()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      wl_insert() is scheduled to run after a CARD_INSERTION event is 
 *  received, to configure the PCMCIA socket, and to make the ethernet device 
 *  available to the system.
 *
 *  PARAMETERS:
 *
 *      dev - a pointer to the net_device struct of the wireless device 
 *
 *  RETURNS:
 *
 *      TRUE or FALSE
 *
 ******************************************************************************/
int wl_insert( struct net_device *dev )
{
    int                     result = TRUE;
    int                     hcf_status = HCF_SUCCESS;
    int                     i;
    unsigned long           flags = 0;
    struct wl_private       *lp = NULL;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_insert" );
    DBG_ENTER( DbgInfo );


    if( dev == NULL )
    {
        DBG_ERROR( DbgInfo, "Device instance is NULL\n" );
        goto failed;
    }

    /* Initialize the adapter hardware. */
    if(( lp = (struct wl_private *)dev->priv ) != NULL )
    {
        memset( &( lp->hcfCtx ), 0, sizeof( IFB_STRCT ));

        /* Initialize the adapter parameters. */
        spin_lock_init( &( lp->slock ));

        lp->dev = dev;

        DBG_PARAM( DbgInfo, "irq_mask", "0x%04x", irq_mask & 0x0FFFF );
        DBG_PARAM( DbgInfo, "irq_list", "0x%02x 0x%02x 0x%02x 0x%02x",
                   irq_list[0] & 0x0FF, irq_list[1] & 0x0FF,
                   irq_list[2] & 0x0FF, irq_list[3] & 0x0FF );

        /* PRINT A WARNING THAT ALL WILL SEE REGARDING THE DEPRECATION OF THE
           OLD PARAMETER NAMES */
        /*printk( KERN_EMERG "Note that the names of the "
                "parameters for " MODULE_NAME " have been deprecated and will "
                "be removed in the final release. Please review the man page "
                "for this module for a description of the new module parameter "
                "names.\n" );
        */

        /* THESE MODULE PARAMETERS ARE TO BE DEPRECATED IN FAVOR OF A NAMING
           CONVENTION WHICH IS INLINE WITH THE FORTHCOMING WAVELAN API */
#ifdef USE_OLD_PARMS
        DBG_PARAM( DbgInfo, "network_name", "\"%s\"", network_name );
        DBG_PARAM( DbgInfo, "channel", "%d", channel);
        DBG_PARAM( DbgInfo, "distance_between_aps", "%d", distance_between_aps );
        DBG_PARAM( DbgInfo, "transmit_rate", "%d", transmit_rate );
        DBG_PARAM( DbgInfo, "medium_reservation", "%d", medium_reservation );
        DBG_PARAM( DbgInfo, "microwave_robustness", "\"%s\"", microwave_robustness );
        DBG_PARAM( DbgInfo, "station_name", "\"%s\"", station_name );
        DBG_PARAM( DbgInfo, "key_1", "\"%s\"", key_1 );
        DBG_PARAM( DbgInfo, "key_2", "\"%s\"", key_2 );
        DBG_PARAM( DbgInfo, "key_3", "\"%s\"", key_3 );
        DBG_PARAM( DbgInfo, "key_4", "\"%s\"", key_4 );
        DBG_PARAM( DbgInfo, "transmit_key_id", "%d", transmit_key_id );
        DBG_PARAM( DbgInfo, "multicast_rate", "%d", multicast_rate );
        DBG_PARAM( DbgInfo, "download_firmware", "%d", download_firmware );
        DBG_PARAM( DbgInfo, "auth_key_mgmt_suite", "%d", auth_key_mgmt_suite );

#if (HCF_TYPE) & HCF_TYPE_STA
        DBG_PARAM( DbgInfo, "port_type", "%d", port_type );
        DBG_PARAM( DbgInfo, "card_power_management", "%d", card_power_management );
        DBG_PARAM( DbgInfo, "create_ibss", "\"%s\"", create_ibss );
        DBG_PARAM( DbgInfo, "receive_all_multicasts", "\"%s\"", receive_all_multicasts );
        DBG_PARAM( DbgInfo, "maximum_sleep_duration", "%d", maximum_sleep_duration );
        DBG_PARAM( DbgInfo, "mac_address", "\"%s\"", DbgHwAddr( mac_address ));
        DBG_PARAM( DbgInfo, "authentication", "%d", authentication );
        DBG_PARAM( DbgInfo, "atim_window", "%d", atim_window );
        DBG_PARAM( DbgInfo, "holdover_duration", "%d", holdover_duration );
        DBG_PARAM( DbgInfo, "promiscuous_mode", "\"%s\"", promiscuous_mode );
#endif /* HCF_STA */


#if (HCF_TYPE) & HCF_TYPE_AP
        DBG_PARAM( DbgInfo, "dtim_period", "%d", dtim_period );
        DBG_PARAM( DbgInfo, "closed_system", "\"%s\"", closed_system );
        DBG_PARAM( DbgInfo, "deny_nonencrypted", "\"%s\"", deny_nonencrypted );
        DBG_PARAM( DbgInfo, "multicast_pm_buffering", "\"%s\"", multicast_pm_buffering );
        DBG_PARAM( DbgInfo, "intra_bss_relay", "\"%s\"", intra_bss_relay );
        DBG_PARAM( DbgInfo, "rts_threshold_1", "%d", rts_threshold_1 );
        DBG_PARAM( DbgInfo, "rts_threshold_2", "%d", rts_threshold_2 );
        DBG_PARAM( DbgInfo, "rts_threshold_3", "%d", rts_threshold_3 );
        DBG_PARAM( DbgInfo, "rts_threshold_4", "%d", rts_threshold_4 );
        DBG_PARAM( DbgInfo, "rts_threshold_5", "%d", rts_threshold_5 );
        DBG_PARAM( DbgInfo, "rts_threshold_6", "%d", rts_threshold_6 );
        DBG_PARAM( DbgInfo, "tx_rate_control_1", "%d", tx_rate_control_1 );
        DBG_PARAM( DbgInfo, "tx_rate_control_2", "%d", tx_rate_control_2 );
        DBG_PARAM( DbgInfo, "tx_rate_control_3", "%d", tx_rate_control_3 );
        DBG_PARAM( DbgInfo, "tx_rate_control_4", "%d", tx_rate_control_4 );
        DBG_PARAM( DbgInfo, "tx_rate_control_5", "%d", tx_rate_control_5 );
        DBG_PARAM( DbgInfo, "tx_rate_control_6", "%d", tx_rate_control_6 );
        DBG_PARAM( DbgInfo, "wds_address_1", "\"%s\"", DbgHwAddr( wds_address_1 ));
        DBG_PARAM( DbgInfo, "wds_address_2", "\"%s\"", DbgHwAddr( wds_address_2 ));
        DBG_PARAM( DbgInfo, "wds_address_3", "\"%s\"", DbgHwAddr( wds_address_3 ));
        DBG_PARAM( DbgInfo, "wds_address_4", "\"%s\"", DbgHwAddr( wds_address_4 ));
        DBG_PARAM( DbgInfo, "wds_address_5", "\"%s\"", DbgHwAddr( wds_address_5 ));
        DBG_PARAM( DbgInfo, "wds_address_6", "\"%s\"", DbgHwAddr( wds_address_6 ));
#endif /* HCF_AP */

#endif /* USE_OLD_PARMS */

        /* END DEPRECATED PARAMETERS */

        /* START NEW PARAMETERS */

        DBG_PARAM( DbgInfo, PARM_NAME_DESIRED_SSID, "\"%s\"", PARM_DESIRED_SSID );
        DBG_PARAM( DbgInfo, PARM_NAME_OWN_SSID, "\"%s\"", PARM_OWN_SSID );
        DBG_PARAM( DbgInfo, PARM_NAME_CHANNEL, "%d", PARM_CHANNEL);
        DBG_PARAM( DbgInfo, PARM_NAME_SYSTEM_SCALE, "%d", PARM_SYSTEM_SCALE );
        DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE, "%d", PARM_TX_RATE );
        DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD, "%d", PARM_RTS_THRESHOLD );
        DBG_PARAM( DbgInfo, PARM_NAME_MICROWAVE_ROBUSTNESS, "\"%s\"", PARM_MICROWAVE_ROBUSTNESS );
        DBG_PARAM( DbgInfo, PARM_NAME_OWN_NAME, "\"%s\"", PARM_OWN_NAME );
        //DBG_PARAM( DbgInfo, PARM_NAME_ENABLE_ENCRYPTION, "\"%s\"", PARM_ENABLE_ENCRYPTION );
        DBG_PARAM( DbgInfo, PARM_NAME_KEY1, "\"%s\"", PARM_KEY1 );
        DBG_PARAM( DbgInfo, PARM_NAME_KEY2, "\"%s\"", PARM_KEY2 );
        DBG_PARAM( DbgInfo, PARM_NAME_KEY3, "\"%s\"", PARM_KEY3 );
        DBG_PARAM( DbgInfo, PARM_NAME_KEY4, "\"%s\"", PARM_KEY4 );
        DBG_PARAM( DbgInfo, PARM_NAME_TX_KEY, "%d", PARM_TX_KEY );
        DBG_PARAM( DbgInfo, PARM_NAME_MULTICAST_RATE, "%d", PARM_MULTICAST_RATE );
        DBG_PARAM( DbgInfo, PARM_NAME_DOWNLOAD_FIRMWARE, "%d", PARM_DOWNLOAD_FIRMWARE );

        DBG_PARAM( DbgInfo, PARM_NAME_AUTH_KEY_MGMT_SUITE, "%d",
                   PARM_AUTH_KEY_MGMT_SUITE );


#if (HCF_TYPE) & HCF_TYPE_STA
        DBG_PARAM( DbgInfo, PARM_NAME_PORT_TYPE, "%d", PARM_PORT_TYPE );
        DBG_PARAM( DbgInfo, PARM_NAME_PM_ENABLED, "%d", PARM_PM_ENABLED );
        DBG_PARAM( DbgInfo, PARM_NAME_CREATE_IBSS, "\"%s\"", PARM_CREATE_IBSS );
        DBG_PARAM( DbgInfo, PARM_NAME_RX_MULTICAST, "\"%s\"", PARM_RX_MULTICAST );
        DBG_PARAM( DbgInfo, PARM_NAME_MAX_SLEEP, "%d", PARM_MAX_SLEEP );
        DBG_PARAM( DbgInfo, PARM_NAME_MAC_ADDRESS, "\"%s\"", DbgHwAddr( PARM_MAC_ADDRESS ));
        DBG_PARAM( DbgInfo, PARM_NAME_AUTHENTICATION, "%d", PARM_AUTHENTICATION );
        DBG_PARAM( DbgInfo, PARM_NAME_OWN_ATIM_WINDOW, "%d", PARM_OWN_ATIM_WINDOW );
        DBG_PARAM( DbgInfo, PARM_NAME_PM_HOLDOVER_DURATION, "%d", PARM_PM_HOLDOVER_DURATION );
        DBG_PARAM( DbgInfo, PARM_NAME_PROMISCUOUS_MODE, "\"%s\"", PARM_PROMISCUOUS_MODE );
#endif /* HCF_STA */


#if (HCF_TYPE) & HCF_TYPE_AP
        DBG_PARAM( DbgInfo, PARM_NAME_OWN_DTIM_PERIOD, "%d", PARM_OWN_DTIM_PERIOD );
        DBG_PARAM( DbgInfo, PARM_NAME_REJECT_ANY, "\"%s\"", PARM_REJECT_ANY );
        DBG_PARAM( DbgInfo, PARM_NAME_EXCLUDE_UNENCRYPTED, "\"%s\"", PARM_EXCLUDE_UNENCRYPTED );
        DBG_PARAM( DbgInfo, PARM_NAME_MULTICAST_PM_BUFFERING, "\"%s\"", PARM_MULTICAST_PM_BUFFERING );
        DBG_PARAM( DbgInfo, PARM_NAME_INTRA_BSS_RELAY, "\"%s\"", PARM_INTRA_BSS_RELAY );
        DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD1, "%d", PARM_RTS_THRESHOLD1 );
        DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD2, "%d", PARM_RTS_THRESHOLD2 );
        DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD3, "%d", PARM_RTS_THRESHOLD3 );
        DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD4, "%d", PARM_RTS_THRESHOLD4 );
        DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD5, "%d", PARM_RTS_THRESHOLD5 );
        DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD6, "%d", PARM_RTS_THRESHOLD6 );
        DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE1, "%d", PARM_TX_RATE1 );
        DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE2, "%d", PARM_TX_RATE2 );
        DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE3, "%d", PARM_TX_RATE3 );
        DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE4, "%d", PARM_TX_RATE4 );
        DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE5, "%d", PARM_TX_RATE5 );
        DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE6, "%d", PARM_TX_RATE6 );
        DBG_PARAM( DbgInfo, PARM_WDS_ADDRESS1, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS1 ));
        DBG_PARAM( DbgInfo, PARM_WDS_ADDRESS2, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS2 ));
        DBG_PARAM( DbgInfo, PARM_WDS_ADDRESS3, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS3 ));
        DBG_PARAM( DbgInfo, PARM_WDS_ADDRESS4, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS4 ));
        DBG_PARAM( DbgInfo, PARM_WDS_ADDRESS5, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS5 ));
        DBG_PARAM( DbgInfo, PARM_WDS_ADDRESS6, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS6 ));
#endif /* HCF_AP */

        /* END NEW PARAMETERS */


        /* If the old parameters are set to anything other than the defaults,
           copy their value to the new params */
#ifdef USE_OLD_PARMS

        //DBG_TRACE( DbgInfo, "network_name: %s\n", network_name );
        if( strcmp( network_name, PARM_DEFAULT_SSID ) != 0 )
        {
            PARM_DESIRED_SSID = network_name;
            PARM_OWN_SSID = network_name;
        }

        //DBG_TRACE( DbgInfo, "channel: %d\n", channel );
        if( channel != PARM_DEFAULT_CHANNEL )
        {
            PARM_CHANNEL = channel;
        }

        //DBG_TRACE( DbgInfo, "distance_between_aps: %d\n", distance_between_aps );
        if( distance_between_aps != PARM_DEFAULT_SYSTEM_SCALE )
        {
            PARM_SYSTEM_SCALE = distance_between_aps;
        }

        //DBG_TRACE( DbgInfo, "transmit_rate: %d\n", transmit_rate );
        if( transmit_rate != PARM_DEFAULT_TX_RATE )
        {
            PARM_TX_RATE = transmit_rate;
        }

        //DBG_TRACE( DbgInfo, "medium_reservation: %d\n", medium_reservation );
        if( medium_reservation != PARM_DEFAULT_RTS_THRESHOLD )
        {
            PARM_RTS_THRESHOLD = medium_reservation;
        }

        //DBG_TRACE( DbgInfo, "microwave_robustness: %s\n", microwave_robustness );
        if( strcmp( microwave_robustness, PARM_DEFAULT_MICROWAVE_ROBUSTNESS_STR ) != 0 )
        {
            PARM_MICROWAVE_ROBUSTNESS = microwave_robustness;
        }

        //DBG_TRACE( DbgInfo, "mac_address: %s\n", DbgHwAddr( mac_address ));
        if( WVLAN_VALID_MAC_ADDRESS( mac_address ))
        {
            memcpy( PARM_MAC_ADDRESS, mac_address, ETH_ALEN );
        }

        //DBG_TRACE( DbgInfo, "station_name: %s\n", station_name );
        if( strcmp( station_name, PARM_DEFAULT_OWN_NAME ) != 0 )
        {
            PARM_OWN_NAME = station_name;
        }

        if( enable_encryption != PARM_DEFAULT_ENABLE_ENCRYPTION )
        {
            PARM_ENABLE_ENCRYPTION = enable_encryption;
        }

        //DBG_TRACE( DbgInfo, "key_1: %s\n", key_1 );
        if( strcmp( key_1, "" ) != 0 )
        {
            PARM_KEY1 = key_1;
        }

        //DBG_TRACE( DbgInfo, "key_2: %s\n", key_2 );
        if( strcmp( key_2, "" ) != 0 )
        {
            PARM_KEY2 = key_2;
        }

        //DBG_TRACE( DbgInfo, "key_3: %s\n", key_3 );
        if( strcmp( key_3, "" ) != 0 )
        {
            PARM_KEY3 = key_3;
        }

        //DBG_TRACE( DbgInfo, "key_4: %s\n", key_4 );
        if( strcmp( key_4, "" ) != 0 )
        {
            PARM_KEY4 = key_4;
        }

        //DBG_TRACE( DbgInfo, "transmit_key_id: %d\n", transmit_key_id );
        if( transmit_key_id != PARM_DEFAULT_TX_KEY )
        {
            PARM_TX_KEY = transmit_key_id;
        }

        //DBG_TRACE( DbgInfo, "multicast_rate: %d\n", multicast_rate );
        if( multicast_rate != PARM_DEFAULT_MULTICAST_RATE )
        {
            PARM_MULTICAST_RATE = multicast_rate;
        }

        if( auth_key_mgmt_suite != PARM_DEFAULT_AUTH_KEY_MGMT_SUITE )
        {
            PARM_AUTH_KEY_MGMT_SUITE = auth_key_mgmt_suite;
        }


#if (HCF_TYPE) & HCF_TYPE_STA

        //DBG_TRACE( DbgInfo, "card_power_management: %d\n", card_power_management );
        if( card_power_management != WVLAN_PM_STATE_DISABLED )
        {
            PARM_PM_ENABLED = card_power_management;
        }

        //DBG_TRACE( DbgInfo, "port_type: %d\n", port_type );
        if( port_type != PARM_DEFAULT_PORT_TYPE )
        {
            PARM_PORT_TYPE = port_type;
        }

        //DBG_TRACE( DbgInfo, "create_ibss: %s\n", create_ibss );
        if( strcmp( create_ibss, PARM_DEFAULT_CREATE_IBSS_STR ) != 0 )
        {
            PARM_CREATE_IBSS = create_ibss;
        }

        //DBG_TRACE( DbgInfo, "receive_all_multicasts: %s\n", receive_all_multicasts );
        if( strcmp( receive_all_multicasts, PARM_DEFAULT_RX_MULTICAST_STR ) != 0 )
        {
            PARM_RX_MULTICAST = receive_all_multicasts;
        } 

        //DBG_TRACE( DbgInfo, "maximum_sleep_duration: %d\n", maximum_sleep_duration );
        if( maximum_sleep_duration != PARM_DEFAULT_MAX_PM_SLEEP )
        {
            PARM_MAX_SLEEP = maximum_sleep_duration;
        }

        //DBG_TRACE( DbgInfo, "authentication: %d\n", authentication );
        if( authentication != PARM_DEFAULT_AUTHENTICATION )
        {
            PARM_AUTHENTICATION = authentication;
        }

        //DBG_TRACE( DbgInfo, "atim_window: %d\n", atim_window );
        if( atim_window != PARM_DEFAULT_OWN_ATIM_WINDOW )
        {
            PARM_OWN_ATIM_WINDOW = atim_window;
        }

        //DBG_TRACE( DbgInfo, "holdover_duration: %d\n", holdover_duration );
        if( holdover_duration != PARM_DEFAULT_PM_HOLDOVER_DURATION )
        {
            PARM_PM_HOLDOVER_DURATION = holdover_duration;
        }

        //DBG_TRACE( DbgInfo, "promiscuous_mode: %s\n", promiscuous_mode );
        if( strcmp( promiscuous_mode, PARM_DEFAULT_PROMISCUOUS_MODE_STR ) != 0 )
        {
            PARM_PROMISCUOUS_MODE = promiscuous_mode;
        }
#endif /* HCF_STA */

        //DBG_TRACE( DbgInfo, "download_firmware: %d\n", download_firmware );
        PARM_DOWNLOAD_FIRMWARE = download_firmware;

#if (HCF_TYPE) & HCF_TYPE_AP

        //DBG_TRACE( DbgInfo, "dtim_period: %d\n", dtim_period );
        if( dtim_period != PARM_DEFAULT_OWN_DTIM_PERIOD )
        {
            PARM_OWN_DTIM_PERIOD = dtim_period;
        } 

        //DBG_TRACE( DbgInfo, "closed_system: %s\n", closed_system );
        if( strcmp( closed_system, PARM_DEFAULT_REJECT_ANY_STR ) != 0 )
        {
            PARM_REJECT_ANY = closed_system;
        }

        //DBG_TRACE( DbgInfo, "deny_nonencrypted: %s\n", deny_nonencrypted );
        if( strcmp( deny_nonencrypted, PARM_DEFAULT_EXCLUDE_UNENCRYPTED_STR ) != 0 )
        {
            PARM_EXCLUDE_UNENCRYPTED = deny_nonencrypted;
        }

        //DBG_TRACE( DbgInfo, "multicast_pm_buffering: %s\n", multicast_pm_buffering );
        if( strcmp( multicast_pm_buffering, PARM_DEFAULT_MULTICAST_PM_BUFFERING_STR ) != 0 )
        {
            PARM_MULTICAST_PM_BUFFERING = multicast_pm_buffering;
        }

        //DBG_TRACE( DbgInfo, "intra_bss_relay: %s\n", intra_bss_relay );
        if( strcmp( intra_bss_relay, PARM_DEFAULT_INTRA_BSS_RELAY_STR ) != 0 )
        {
            PARM_INTRA_BSS_RELAY = intra_bss_relay;
        }

        //DBG_TRACE( DbgInfo, "rts_threshold_1: %d\n", rts_threshold_1 );
        if( rts_threshold_1 != PARM_DEFAULT_RTS_THRESHOLD )
        {
            PARM_RTS_THRESHOLD = rts_threshold_1;
        }

        //DBG_TRACE( DbgInfo, "rts_threshold_2: %d\n", rts_threshold_2 );
        if( rts_threshold_2 != PARM_DEFAULT_RTS_THRESHOLD )
        {
            PARM_RTS_THRESHOLD = rts_threshold_2;
        }

        //DBG_TRACE( DbgInfo, "rts_threshold_3: %d\n", rts_threshold_3 );
        if( rts_threshold_3 != PARM_DEFAULT_RTS_THRESHOLD )
        {
            PARM_RTS_THRESHOLD = rts_threshold_3;
        }

        //DBG_TRACE( DbgInfo, "rts_threshold_4: %d\n", rts_threshold_4 );
        if( rts_threshold_4 != PARM_DEFAULT_RTS_THRESHOLD )
        {
            PARM_RTS_THRESHOLD = rts_threshold_4;
        }

        //DBG_TRACE( DbgInfo, "rts_threshold_5: %d\n", rts_threshold_5 );
        if( rts_threshold_5 != PARM_DEFAULT_RTS_THRESHOLD )
        {
            PARM_RTS_THRESHOLD = rts_threshold_5;
        }

        //DBG_TRACE( DbgInfo, "rts_threshold_6: %d\n", rts_threshold_6 );
        if( rts_threshold_6 != PARM_DEFAULT_RTS_THRESHOLD )
        {
            PARM_RTS_THRESHOLD = rts_threshold_6;
        }

        //DBG_TRACE( DbgInfo, "tx_rate_control_1: %d\n", tx_rate_control_1 );
        if( tx_rate_control_1 != PARM_DEFAULT_TX_RATE )
        {
            PARM_TX_RATE = tx_rate_control_1;
        }

        //DBG_TRACE( DbgInfo, "tx_rate_control_2: %d\n", tx_rate_control_2 );
        if( tx_rate_control_2 != PARM_DEFAULT_TX_RATE )
        {
            PARM_TX_RATE = tx_rate_control_2;
        }

        //DBG_TRACE( DbgInfo, "tx_rate_control_3: %d\n", tx_rate_control_3 );
        if( tx_rate_control_3 != PARM_DEFAULT_TX_RATE )
        {
            PARM_TX_RATE = tx_rate_control_3;
        }

        //DBG_TRACE( DbgInfo, "tx_rate_control_4: %d\n", tx_rate_control_4 );
        if( tx_rate_control_4 != PARM_DEFAULT_TX_RATE )
        {
            PARM_TX_RATE = tx_rate_control_4;
        }

        //DBG_TRACE( DbgInfo, "tx_rate_control_5: %d\n", tx_rate_control_5 );
        if( tx_rate_control_5 != PARM_DEFAULT_TX_RATE )
        {
            PARM_TX_RATE = tx_rate_control_5;
        }

        //DBG_TRACE( DbgInfo, "tx_rate_control_6: %d\n", tx_rate_control_6 );
        if( tx_rate_control_6 != PARM_DEFAULT_TX_RATE )
        {
            PARM_TX_RATE = tx_rate_control_6;
        }

        //DBG_TRACE( DbgInfo, "wds_address_1: %s\n", DbgHwAddr( wds_address_1 ));
        if( WVLAN_VALID_MAC_ADDRESS( wds_address_1 ))
        {
            memcpy( PARM_WDS_ADDRESS1, wds_address_1, ETH_ALEN );
        }

        //DBG_TRACE( DbgInfo, "wds_address_2: %s\n", DbgHwAddr( wds_address_2 ));
        if( WVLAN_VALID_MAC_ADDRESS( wds_address_2 ))
        {
            memcpy( PARM_WDS_ADDRESS2, wds_address_2, ETH_ALEN );
        }

        //DBG_TRACE( DbgInfo, "wds_address_3: %s\n", DbgHwAddr( wds_address_3 ));
        if( WVLAN_VALID_MAC_ADDRESS( wds_address_3 ))
        {
            memcpy( PARM_WDS_ADDRESS3, wds_address_3, ETH_ALEN );
        }

        //DBG_TRACE( DbgInfo, "wds_address_4: %s\n", DbgHwAddr( wds_address_4 ));
        if( WVLAN_VALID_MAC_ADDRESS( wds_address_4 ))
        {
            memcpy( PARM_WDS_ADDRESS4, wds_address_4, ETH_ALEN );
        }

        //DBG_TRACE( DbgInfo, "wds_address_5: %s\n", DbgHwAddr( wds_address_5 ));
        if( WVLAN_VALID_MAC_ADDRESS( wds_address_5 ))
        {
            memcpy( PARM_WDS_ADDRESS5, wds_address_5, ETH_ALEN );
        }

        //DBG_TRACE( DbgInfo, "wds_address_6: %s\n", DbgHwAddr( wds_address_6 ));
        if( WVLAN_VALID_MAC_ADDRESS( wds_address_6 ))
        {
            memcpy( PARM_WDS_ADDRESS6, wds_address_6, ETH_ALEN );
        }


#endif /* HCF_AP */
#endif /* USE_OLD_PARMS */

        /* START NEW PARAMETERS */

        /* Now that any old parameters used have been copied to the new
           parameter names, validate the parameters */

        VALID_PARAM( !PARM_DESIRED_SSID || ( strlen( PARM_DESIRED_SSID ) <= PARM_MAX_NAME_LEN ));
        VALID_PARAM( !PARM_OWN_SSID || ( strlen( PARM_OWN_SSID ) <= PARM_MAX_NAME_LEN ));
        VALID_PARAM(( PARM_CHANNEL <= PARM_MAX_CHANNEL ));
        VALID_PARAM(( PARM_SYSTEM_SCALE >= PARM_MIN_SYSTEM_SCALE ) && ( PARM_SYSTEM_SCALE <= PARM_MAX_SYSTEM_SCALE ));
        VALID_PARAM(( PARM_TX_RATE >= PARM_MIN_TX_RATE ) && ( PARM_TX_RATE <= PARM_MAX_TX_RATE ));
        VALID_PARAM(( PARM_RTS_THRESHOLD <= PARM_MAX_RTS_THRESHOLD ));
        VALID_PARAM( !PARM_MICROWAVE_ROBUSTNESS || strchr( "NnYy", PARM_MICROWAVE_ROBUSTNESS[0] ) != NULL );
        VALID_PARAM( !PARM_OWN_NAME || ( strlen( PARM_NAME_OWN_NAME ) <= PARM_MAX_NAME_LEN ));
        VALID_PARAM(( PARM_ENABLE_ENCRYPTION <= PARM_MAX_ENABLE_ENCRYPTION ));       
        VALID_PARAM( is_valid_key_string( PARM_KEY1 ));
        VALID_PARAM( is_valid_key_string( PARM_KEY2 ));
        VALID_PARAM( is_valid_key_string( PARM_KEY3 ));
        VALID_PARAM( is_valid_key_string( PARM_KEY4 ));
        VALID_PARAM(( PARM_TX_KEY >= PARM_MIN_TX_KEY ) && ( PARM_TX_KEY <= PARM_MAX_TX_KEY ));
        

        /* Allowed multicast rate depends on distance between APs */
        switch( PARM_SYSTEM_SCALE )
        {
        case 1:

            VALID_PARAM(( PARM_MULTICAST_RATE >= PARM_MIN_MULTICAST_RATE ) && 
                        ( PARM_MULTICAST_RATE <= 2 ));
            break;


        case 2:

            VALID_PARAM(( PARM_MULTICAST_RATE >= PARM_MIN_MULTICAST_RATE ) && 
                        ( PARM_MULTICAST_RATE <= 3 ));
            break;


        default:
            VALID_PARAM(( PARM_MULTICAST_RATE >= PARM_MIN_MULTICAST_RATE ) && 
                        ( PARM_MULTICAST_RATE <= PARM_MAX_MULTICAST_RATE ));
        }

        VALID_PARAM(( PARM_DOWNLOAD_FIRMWARE < WVLAN_DRV_MODE_MAX ));
        VALID_PARAM(( PARM_AUTH_KEY_MGMT_SUITE < PARM_MAX_AUTH_KEY_MGMT_SUITE ));


#if (HCF_TYPE) & HCF_TYPE_STA
        VALID_PARAM(( PARM_PORT_TYPE >= PARM_MIN_PORT_TYPE ) && ( PARM_PORT_TYPE <= PARM_MAX_PORT_TYPE ));
        VALID_PARAM( PARM_PM_ENABLED <= WVLAN_PM_STATE_STANDARD );
        VALID_PARAM( !PARM_CREATE_IBSS || strchr( "NnYy", PARM_CREATE_IBSS[0] ) != NULL );
        VALID_PARAM( !PARM_RX_MULTICAST || strchr( "NnYy", PARM_RX_MULTICAST[0] ) != NULL );
        VALID_PARAM(( PARM_MAX_SLEEP <= PARM_MAX_MAX_PM_SLEEP ));
        VALID_PARAM(( PARM_AUTHENTICATION <= PARM_MAX_AUTHENTICATION ));
        VALID_PARAM(( PARM_OWN_ATIM_WINDOW <= PARM_MAX_OWN_ATIM_WINDOW ));
        VALID_PARAM(( PARM_PM_HOLDOVER_DURATION <= PARM_MAX_PM_HOLDOVER_DURATION ));
        VALID_PARAM( !PARM_PROMISCUOUS_MODE || strchr( "NnYy", PARM_PROMISCUOUS_MODE[0] ) != NULL );
#endif /* HCF_STA */


#if (HCF_TYPE) & HCF_TYPE_AP
        VALID_PARAM(( PARM_OWN_DTIM_PERIOD >= PARM_MIN_OWN_DTIM_PERIOD ));
        VALID_PARAM( !PARM_REJECT_ANY || strchr( "NnYy", PARM_REJECT_ANY[0] ) != NULL );
        VALID_PARAM( !PARM_EXCLUDE_UNENCRYPTED || strchr( "NnYy", PARM_EXCLUDE_UNENCRYPTED[0] ) != NULL );
        VALID_PARAM( !PARM_MULTICAST_PM_BUFFERING || strchr( "NnYy", PARM_MULTICAST_PM_BUFFERING[0] ) != NULL );
        VALID_PARAM( !PARM_INTRA_BSS_RELAY || strchr( "NnYy", PARM_INTRA_BSS_RELAY[0] ) != NULL );
        VALID_PARAM(( PARM_RTS_THRESHOLD1 <= PARM_MAX_RTS_THRESHOLD ));
        VALID_PARAM(( PARM_RTS_THRESHOLD2 <= PARM_MAX_RTS_THRESHOLD ));
        VALID_PARAM(( PARM_RTS_THRESHOLD3 <= PARM_MAX_RTS_THRESHOLD ));
        VALID_PARAM(( PARM_RTS_THRESHOLD4 <= PARM_MAX_RTS_THRESHOLD ));
        VALID_PARAM(( PARM_RTS_THRESHOLD5 <= PARM_MAX_RTS_THRESHOLD ));
        VALID_PARAM(( PARM_RTS_THRESHOLD6 <= PARM_MAX_RTS_THRESHOLD ));
        VALID_PARAM(( PARM_TX_RATE1 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE1 <= PARM_MAX_TX_RATE ));
        VALID_PARAM(( PARM_TX_RATE2 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE2 <= PARM_MAX_TX_RATE ));
        VALID_PARAM(( PARM_TX_RATE3 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE3 <= PARM_MAX_TX_RATE ));
        VALID_PARAM(( PARM_TX_RATE4 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE4 <= PARM_MAX_TX_RATE ));
        VALID_PARAM(( PARM_TX_RATE5 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE5 <= PARM_MAX_TX_RATE ));
        VALID_PARAM(( PARM_TX_RATE6 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE6 <= PARM_MAX_TX_RATE ));
#endif /* HCF_AP */

        /* END NEW PARAMETERS */

        /* Set the driver parameters from the passed in parameters. */

        /* THESE MODULE PARAMETERS ARE TO BE DEPRECATED IN FAVOR OF A NAMING CONVENTION
           WHICH IS INLINE WITH THE FORTHCOMING WAVELAN API */

        /* START NEW PARAMETERS */

        lp->Channel             = PARM_CHANNEL;
        lp->DistanceBetweenAPs  = PARM_SYSTEM_SCALE;
        lp->TxRateControl       = PARM_TX_RATE;
        lp->RTSThreshold        = PARM_RTS_THRESHOLD;
        lp->MulticastRate       = PARM_MULTICAST_RATE;

        if( strchr( "Yy", PARM_MICROWAVE_ROBUSTNESS[0] ) != NULL )
        {
            lp->MicrowaveRobustness = 1;
        }
        else
        {
            lp->MicrowaveRobustness = 0;
        }


        if( PARM_DESIRED_SSID && ( strlen( PARM_DESIRED_SSID ) <= HCF_MAX_NAME_LEN ))
        {
            strcpy( lp->NetworkName, PARM_DESIRED_SSID );
        }


        if( PARM_OWN_SSID && ( strlen( PARM_OWN_SSID ) <= HCF_MAX_NAME_LEN ))
        {
            strcpy( lp->NetworkName, PARM_OWN_SSID );
        }


        if( PARM_OWN_NAME && ( strlen( PARM_OWN_NAME ) <= HCF_MAX_NAME_LEN ))
        {
            strcpy( lp->StationName, PARM_OWN_NAME );
        }


        lp->EnableEncryption = PARM_ENABLE_ENCRYPTION;


        if( PARM_KEY1 && ( strlen( PARM_KEY1 ) <= MAX_KEY_LEN ))
        {
            strcpy( lp->Key1, PARM_KEY1 );
        }


        if( PARM_KEY2 && ( strlen( PARM_KEY2 ) <= MAX_KEY_LEN ))
        {
            strcpy( lp->Key2, PARM_KEY2 );
        }


        if( PARM_KEY3 && ( strlen( PARM_KEY3 ) <= MAX_KEY_LEN ))
        {
            strcpy( lp->Key3, PARM_KEY3 );
        }


        if( PARM_KEY4 && ( strlen( PARM_KEY4 ) <= MAX_KEY_LEN ))
        {
            strcpy( lp->Key4, PARM_KEY4 );
        }

        lp->TransmitKeyID = PARM_TX_KEY;

        key_string2key( lp->Key1, &(lp->DefaultKeys.key[0] ));
        key_string2key( lp->Key2, &(lp->DefaultKeys.key[1] ));
        key_string2key( lp->Key3, &(lp->DefaultKeys.key[2] ));
        key_string2key( lp->Key4, &(lp->DefaultKeys.key[3] ));
        
        lp->DownloadFirmware = PARM_DOWNLOAD_FIRMWARE;
        lp->AuthKeyMgmtSuite = PARM_AUTH_KEY_MGMT_SUITE;


#if (HCF_TYPE) & HCF_TYPE_STA
        lp->PortType            = PARM_PORT_TYPE;
        lp->MaxSleepDuration    = PARM_MAX_SLEEP;
        lp->authentication      = PARM_AUTHENTICATION;
        lp->atimWindow          = PARM_OWN_ATIM_WINDOW;
        lp->holdoverDuration    = PARM_PM_HOLDOVER_DURATION;
        lp->PMEnabled           = PARM_PM_ENABLED;


        if( strchr( "Yy", PARM_CREATE_IBSS[0] ) != NULL )
        {
            lp->CreateIBSS = 1;
        }
        else
        {
            lp->CreateIBSS = 0;
        }


        if( strchr( "Nn", PARM_RX_MULTICAST[0] ) != NULL )
        {
            lp->MulticastReceive = 0;
        }
        else
        {
            lp->MulticastReceive = 1;
        }


        if( strchr( "Yy", PARM_PROMISCUOUS_MODE[0] ) != NULL )
        {
            lp->promiscuousMode = 1;
        }
        else
        {
            lp->promiscuousMode = 0;
        }


        for( i = 0; i < ETH_ALEN; i++ )
        {
           lp->MACAddress[i] = PARM_MAC_ADDRESS[i];
        }
#endif /* HCF_STA */


#if (HCF_TYPE) & HCF_TYPE_AP
        lp->DTIMPeriod = PARM_OWN_DTIM_PERIOD;

        if( strchr( "Yy", PARM_REJECT_ANY[0] ) != NULL )
        {
            lp->RejectAny = 1;
        }
        else
        {
            lp->RejectAny = 0;
        }


        if( strchr( "Nn", PARM_EXCLUDE_UNENCRYPTED[0] ) != NULL )
        {
            lp->ExcludeUnencrypted = 0;
        }
        else
        {
            lp->ExcludeUnencrypted = 1;
        }


        if( strchr( "Yy", PARM_MULTICAST_PM_BUFFERING[0] ) != NULL )
        {
            lp->multicastPMBuffering = 1;
        }
        else
        {
            lp->multicastPMBuffering = 0;
        }


        if( strchr( "Yy", PARM_INTRA_BSS_RELAY[0] ) != NULL )
        {
            lp->intraBSSRelay = 1;
        }
        else
        {
            lp->intraBSSRelay = 0;
        }


#ifdef USE_WDS
        lp->wds_port[0].rtsThreshold    = PARM_RTS_THRESHOLD1;
        lp->wds_port[1].rtsThreshold    = PARM_RTS_THRESHOLD2;
        lp->wds_port[2].rtsThreshold    = PARM_RTS_THRESHOLD3;
        lp->wds_port[3].rtsThreshold    = PARM_RTS_THRESHOLD4;
        lp->wds_port[4].rtsThreshold    = PARM_RTS_THRESHOLD5;
        lp->wds_port[5].rtsThreshold    = PARM_RTS_THRESHOLD6;
        lp->wds_port[0].txRateCntl      = PARM_TX_RATE1;
        lp->wds_port[1].txRateCntl      = PARM_TX_RATE2;
        lp->wds_port[2].txRateCntl      = PARM_TX_RATE3;
        lp->wds_port[3].txRateCntl      = PARM_TX_RATE4;
        lp->wds_port[4].txRateCntl      = PARM_TX_RATE5;
        lp->wds_port[5].txRateCntl      = PARM_TX_RATE6;

        for( i = 0; i < ETH_ALEN; i++ )
        {
            lp->wds_port[0].wdsAddress[i] = PARM_WDS_ADDRESS1[i];
        }


        for( i = 0; i < ETH_ALEN; i++ )
        {
            lp->wds_port[1].wdsAddress[i] = PARM_WDS_ADDRESS2[i];
        }


        for( i = 0; i < ETH_ALEN; i++ )
        {
            lp->wds_port[2].wdsAddress[i] = PARM_WDS_ADDRESS3[i];
        }


        for( i = 0; i < ETH_ALEN; i++ )
        {
            lp->wds_port[3].wdsAddress[i] = PARM_WDS_ADDRESS4[i];
        }


        for( i = 0; i < ETH_ALEN; i++ )
        {
            lp->wds_port[4].wdsAddress[i] = PARM_WDS_ADDRESS5[i];
        }


        for( i = 0; i < ETH_ALEN; i++ )
        {
            lp->wds_port[5].wdsAddress[i] = PARM_WDS_ADDRESS6[i];
        }  
#endif  /* USE_WDS */
#endif  /* HCF_AP */


#ifdef USE_RTS
        if( strchr( "Yy", useRTS[0] ) != NULL )
        {
            lp->useRTS = 1;
        }
        else
        {
            lp->useRTS = 0;
        }
#endif  /* USE_RTS */
        

        /* END NEW PARAMETERS */
        

        spin_lock_irqsave( &( lp->slock ), flags );
        
        /* Initialize the portState variable */
        lp->portState = WVLAN_PORT_STATE_DISABLED;

        /* Initialize the ScanResult struct */
        memset( &( lp->scan_results ), 0, sizeof( lp->scan_results ));
        lp->scan_results.scan_complete = FALSE;

        /* Initialize the ProbeResult struct */
        memset( &( lp->probe_results ), 0, sizeof( lp->probe_results ));
        lp->probe_results.scan_complete = FALSE;
        lp->probe_num_aps = 0;


        /* Initialize Tx queue stuff */
        memset( lp->txList, 0, sizeof( lp->txList ));

        INIT_LIST_HEAD( &( lp->txFree ));

        lp->txF.skb  = NULL;
        lp->txF.port = 0;

        
        for( i = 0; i < DEFAULT_NUM_TX_FRAMES; i++ )
        {
            list_add_tail( &( lp->txList[i].node ), &( lp->txFree ));
        }
        

        for( i = 0; i < WVLAN_MAX_TX_QUEUES; i++ ) 
        {
            INIT_LIST_HEAD( &( lp->txQ[i] ));
        }

        lp->netif_queue_on = TRUE;
        lp->txQ_count = 0;


        /* Register the ISR handler information here, so that it's not done
           repeatedly in the ISR */
        lp->task.routine = (void (*)(void *))wl_isr_handler;
        lp->task.data = lp;
        

        /* Connect to the adapter */
        DBG_TRACE( DbgInfo, "Calling hcf_connect()...\n" );
        hcf_status = hcf_connect( &( lp->hcfCtx ), dev->base_addr );


#if (HCF_TYPE) & HCF_TYPE_HII
        if( hcf_status != HCF_SUCCESS )
#else
        if(( hcf_status != HCF_SUCCESS ) &&
           ( hcf_status != HCF_ERR_INCOMP_FW ))
#endif  // (HCF_TYPE) & HCF_TYPE_HII
        {

            DBG_ERROR( DbgInfo, "hcf_connect() failed, status: 0x%x\n", hcf_status );

            spin_unlock_irqrestore( &( lp->slock ), flags );
            goto hcf_failed;
        }
        

        /* Fill in the driver information structure */
        lp->driverInfo.len = ( sizeof( lp->driverInfo ) / sizeof( hcf_16 )) - 1;
        lp->driverInfo.typ = CFG_DRV_INFO;

        strcpy( lp->driverInfo.driver_name, DRIVER_NAME );

        lp->driverInfo.driver_version   = ( DRV_MAJOR_VERSION << 8 ) | DRV_MINOR_VERSION;
        lp->driverInfo.IO_address       = dev->base_addr;
        lp->driverInfo.IO_range         = HCF_NUM_IO_PORTS;
        lp->driverInfo.IRQ_number       = dev->irq;
        lp->driverInfo.card_stat        = lp->hcfCtx.IFB_CardStat;
        
        /* Fill in the driver identity structure */
        lp->driverIdentity.len              = ( sizeof( lp->driverIdentity ) / sizeof( hcf_16 )) - 1;
        lp->driverIdentity.typ              = CFG_DRV_IDENTITY;
        lp->driverIdentity.comp_id          = DRV_IDENTITY;
        lp->driverIdentity.variant          = DRV_VARIANT;
        lp->driverIdentity.version_major    = DRV_MAJOR_VERSION;
        lp->driverIdentity.version_minor    = DRV_MINOR_VERSION;


        /* Start the card here - This needs to be done in order to get the
           MAC address for the network layer */
        DBG_TRACE( DbgInfo, "Calling wvlan_go() to perform a card reset...\n" );
        hcf_status = wl_go( lp );

        if( hcf_status != HCF_SUCCESS )
        {
            DBG_ERROR( DbgInfo, "wl_go() failed\n" );
            spin_unlock_irqrestore( &( lp->slock ), flags );
            goto hcf_failed;
        }


        /* Fill out the MAC address information in the net_device struct */
        memcpy( lp->dev->dev_addr, lp->MACAddress, ETH_ALEN );
        dev->addr_len = ETH_ALEN;


        /* Register the root net device */
        if( register_netdev( dev ) != 0 )
        {
            DBG_ERROR( DbgInfo, "register_netdev() failed\n" );
            spin_unlock_irqrestore( &( lp->slock ), flags );
            goto failed;
        }

        lp->is_registered = TRUE;


#ifdef USE_PROFILE
        /* Parse the config file for the sake of creating WDS ports if WDS is
           configured there but not in the module options */
        parse_config( dev );
#endif  /* USE_PROFILE */


        /* If we're going into AP Mode, register the "virtual" ethernet devices
           needed for WDS */
        WL_WDS_NETDEV_REGISTER( lp );


        /* Reset the DownloadFirmware variable in the private struct. If the
           config file is not used, this will not matter; if it is used, it
           will be reparsed in wl_open(). This is done because logic in wl_open
           used to check if a firmware download is needed is broken by parsing
           the file here; however, this parsing is needed to register WDS ports
           in AP mode, if they are configured */
        lp->DownloadFirmware = download_firmware;


#ifdef USE_RTS
        if( lp->useRTS == 1 )     
        {
            DBG_TRACE( DbgInfo, "ENTERING RTS MODE...\n" );

            wl_disable( lp, HCF_PORT_0 );
            hcf_action( &( lp->hcfCtx ), HCF_ACT_INT_OFF );
            hcf_disconnect( &( lp->hcfCtx ));
        }
#endif  /* USE_RTS */

        spin_unlock_irqrestore( &( lp->slock ), flags );
    }

    DBG_TRACE( DbgInfo, "%s: Wireless, io_addr %#03lx, irq %d, ""mac_address ",
               dev->name, dev->base_addr, dev->irq );

    for( i = 0; i < ETH_ALEN; i++ )
    {
        printk( "%02X%c", dev->dev_addr[i], (( i < ( ETH_ALEN-1 )) ? ':' : '\n' ));
    }
   
    
    DBG_LEAVE( DbgInfo );
    return result;

hcf_failed:
    wl_hcf_error( dev, hcf_status );

failed:

    DBG_ERROR( DbgInfo, "wl_insert() FAILED\n" );

    if( lp->is_registered == TRUE )
    {
        unregister_netdev( dev );

        lp->is_registered = FALSE;
    }

    WL_WDS_NETDEV_DEREGISTER( lp );
   
    result = FALSE;

    
    DBG_LEAVE( DbgInfo );
    return result;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_reset()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Reset the adapter.
 *
 *  PARAMETERS:
 *
 *      dev - a pointer to the net_device struct of the wireless device 
 *
 *  RETURNS:
 *
 *      an HCF status code
 *
 ******************************************************************************/
int wl_reset(struct net_device *dev)
{
    struct wl_private  *lp = NULL;
    int                     hcfStatus = HCF_SUCCESS;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_reset" );
    DBG_ENTER( DbgInfo );
    DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
    DBG_PARAM( DbgInfo, "dev->base_addr", "(%#03lx)", dev->base_addr );


    if(( lp = (struct wl_private *)dev->priv ) != NULL )
    {
        unsigned long   flags;

        spin_lock_irqsave( &( lp->slock ), flags );

        DBG_TRACE( DbgInfo, "Device Base Address: %#03lx\n", dev->base_addr );
        if( dev->base_addr )
        {
            /* Shutdown the adapter. */
            hcf_disconnect( &( lp->hcfCtx ));

            /* Reset the driver information. */
            lp->txBytes = 0;

            /* Restart the adapter. */
            hcf_connect(&( lp->hcfCtx ), dev->base_addr );
            wl_go( lp );

            /* Enable Interrupts */
            hcf_action( &( lp->hcfCtx ), HCF_ACT_INT_FORCE_ON );
        }
        else
        {
            DBG_ERROR( DbgInfo, "Device Base Address INVALID!!!\n" );
        }

        spin_unlock_irqrestore( &( lp->slock ), flags );
    }
    else
    {
        DBG_ERROR( DbgInfo, "pointer to lp is NULL!!!\n" );
    }

    DBG_LEAVE( DbgInfo );
    return hcfStatus;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_go()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Reset the adapter.
 *
 *  PARAMETERS:
 *
 *      dev - a pointer to the net_device struct of the wireless device 
 *
 *  RETURNS:
 *
 *      an HCF status code
 *
 ******************************************************************************/
int wl_go( struct wl_private *lp )
{
    int hcfStatus = HCF_SUCCESS;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_go" );
    DBG_ENTER( DbgInfo );


    if( lp == NULL )
    {
        DBG_ERROR( DbgInfo, "private adapter struct invalid\n" );
        return -1;
    }


    /* Disable the ports */
    wl_disable( lp, HCF_PORT_0 );

#if (HCF_TYPE) & HCF_TYPE_AP
    wl_disable_wds_ports( lp );
#endif  /* (HCF_TYPE) & HCF_TYPE_AP */


#if !((HCF_TYPE) & HCF_TYPE_HII )
     /* this is necessary due to the HCF much newer than the DHF. The HCF 
        stopped using CARD_STAT_PRESENT, but the DHF performs a check on
        this field when doing a download...for Hermes-I only. */
    lp->hcfCtx.IFB_CardStat |= CARD_STAT_PRESENT;
#endif /* ! HCF_TYPE_HII */


    /* load the appropriate firmware image, depending on driver mode */
    lp->ltvRecord.len   = ( sizeof( CFG_RANGE20_STRCT ) / sizeof( hcf_16 )) - 1;
    lp->ltvRecord.typ   = CFG_DRV_ACT_RANGES_PRI;

    hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    switch( lp->DownloadFirmware )
    {

#if (HCF_TYPE) & HCF_TYPE_AP
    case WVLAN_DRV_MODE_AP:

        DBG_TRACE( DbgInfo, "Downloading AP firmware...\n" );
       
        /*hcfStatus = dhf_download_firmware( &lp->hcfCtx,
                                           NULL, 
                                           &ap,
                                           TRUE );
        */
        
        hcfStatus = dhf_download_firmware( &lp->hcfCtx,
                                           NULL,
                                           (CFG_RANGE20_STRCT *)&lp->ltvRecord, 
                                           &ap,
                                           TRUE,
                                           FALSE );
        break;
#endif /* (HCF_TYPE) & HCF_TYPE_AP */

#if (HCF_TYPE) & HCF_TYPE_STA
    case WVLAN_DRV_MODE_STA:
        
        DBG_TRACE( DbgInfo, "Downloading STA firmware...\n" );
       
        /*hcfStatus = dhf_download_firmware( &lp->hcfCtx,
                                           NULL, 
                                           &station,
                                           TRUE );
        */
        
        hcfStatus = dhf_download_firmware( &lp->hcfCtx,
                                           NULL,
                                           (CFG_RANGE20_STRCT *)&lp->ltvRecord, 
                                           &station,
                                           TRUE,
                                           FALSE );
        break;

#ifndef HERMES2
    case WVLAN_DRV_MODE_NO_DOWNLOAD:

        DBG_TRACE( DbgInfo, "No firmware download performed\n" );
        hcfStatus = HCF_SUCCESS;

        break;
#endif /* HERMES2 */
#endif /* (HCF_TYPE) & HCF_TYPE_STA */


    default:
        
        hcfStatus = HCF_FAILURE;
        break;

    }

    if( hcfStatus != HCF_SUCCESS )
    {
        DBG_ERROR( DbgInfo, "Firmware Download failed\n" );
        DBG_LEAVE( DbgInfo );
        return hcfStatus;
    }

    /* Report the FW versions */
    wl_get_pri_records( lp );

    /* now we wil get the MAC address of the card */
    lp->ltvRecord.len = 4;

#ifdef HCF_TYPE_AP
    if( lp->DownloadFirmware == WVLAN_DRV_MODE_AP )
    {
        lp->ltvRecord.typ = CFG_NIC_MAC_ADDR;
    }
    else
#endif /* HCF_TYPE_AP */
    {
        lp->ltvRecord.typ = CFG_CNF_OWN_MAC_ADDR;
    }

    hcfStatus = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    if( hcfStatus != HCF_SUCCESS )
    {
        DBG_ERROR( DbgInfo, "Could not retrieve MAC address\n" );
        DBG_LEAVE( DbgInfo );
        return hcfStatus;
    }

        memcpy( lp->MACAddress, &lp->ltvRecord.u.u8[0], ETH_ALEN );
    DBG_TRACE( DbgInfo, "Card MAC Address: %s\n", DbgHwAddr( lp->MACAddress ));
    

    /* write out default parameters to the device */
    wl_put_ltv( lp );


    /* enable the ports */
    if( wl_adapter_is_open( lp->dev ))
    {
        /* Enable the ports */
        hcfStatus = wl_enable( lp, HCF_PORT_0 );

        if( hcfStatus != HCF_SUCCESS )
        {
            DBG_TRACE( DbgInfo, "Enable port 0 failed: 0x%x\n", hcfStatus );
        }

#if (HCF_TYPE) & HCF_TYPE_AP
        wl_enable_wds_ports( lp );
#endif  /* (HCF_TYPE) & HCF_TYPE_AP */

    }

    DBG_LEAVE( DbgInfo );
    return hcfStatus;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_set_wep_keys()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Write TxKeyID and WEP keys to the adapter. This is separated from 
 *  wl_apply() to allow dynamic WEP key updates through the wireless
 *  extensions.
 *
 *  PARAMETERS:
 *
 *      lp  - a pointer to the wireless adapter's private structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void wl_set_wep_keys( struct wl_private *lp )
{
    int count = 0;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_set_wep_keys" );
    DBG_ENTER( DbgInfo );
    DBG_PARAM( DbgInfo, "lp", "%s (0x%p)", lp->dev->name, lp );


    if( lp->EnableEncryption )
    {
        /* NOTE: CFG_CNF_ENCRYPTION is set in wl_put_ltv() as it's a static
                 RID */

        /* set TxKeyID */
        lp->ltvRecord.len = 2;
        lp->ltvRecord.typ       = CFG_TX_KEY_ID;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE(lp->TransmitKeyID - 1);

        hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "Key 1 len: %d\n", lp->DefaultKeys.key[0].len );
        DBG_TRACE( DbgInfo, "Key 2 len: %d\n", lp->DefaultKeys.key[1].len );
        DBG_TRACE( DbgInfo, "Key 3 len: %d\n", lp->DefaultKeys.key[2].len );
        DBG_TRACE( DbgInfo, "Key 4 len: %d\n", lp->DefaultKeys.key[3].len );

        /* write keys */
        lp->DefaultKeys.len = sizeof( lp->DefaultKeys ) / sizeof( hcf_16 ) - 1;
        lp->DefaultKeys.typ = CFG_DEFAULT_KEYS;

        /* endian translate the appropriate key information */
	    for( count = 0; count < MAX_KEYS; count++ )
        {
            lp->DefaultKeys.key[count].len = CNV_INT_TO_LITTLE( lp->DefaultKeys.key[count].len );
        }

        hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->DefaultKeys ));

        /* Reverse the above endian translation, since these keys are accessed
           elsewhere */
	    for( count = 0; count < MAX_KEYS; count++ )
        {
            lp->DefaultKeys.key[count].len = CNV_INT_TO_LITTLE( lp->DefaultKeys.key[count].len );
        }

        DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID );
        DBG_NOTICE( DbgInfo, "set key: %s(%d) [%d]\n", lp->DefaultKeys.key[lp->TransmitKeyID-1].key, lp->DefaultKeys.key[lp->TransmitKeyID-1].len, lp->TransmitKeyID-1 );
    }

    DBG_LEAVE( DbgInfo );
}
/*============================================================================*/




/*******************************************************************************
 *	wl_apply()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Write the parameters to the adapter. (re-)enables the card if device is
 *  open. Returns hcfStatus of hcf_enable().
 *
 *  PARAMETERS:
 *
 *      lp  - a pointer to the wireless adapter's private structure
 *
 *  RETURNS:
 *
 *      an HCF status code
 *
 ******************************************************************************/
int wl_apply(struct wl_private *lp)
{
    int hcfStatus = HCF_SUCCESS;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_apply" );
    DBG_ENTER( DbgInfo );
    DBG_PARAM( DbgInfo, "lp", "%s (0x%p)", lp->dev->name, lp );

    DBG_ASSERT(lp != NULL);


    if( !( lp->flags & WVLAN2_UIL_BUSY ))
    {
        /* The adapter parameters have changed:
                disable card
                reload parameters
                enable card
        */

        if( wl_adapter_is_open( lp->dev ))
        {
            /* Disable the ports */
            wl_disable( lp, HCF_PORT_0 );

#if (HCF_TYPE) & HCF_TYPE_AP
            wl_disable_wds_ports( lp );
#endif  /* (HCF_TYPE) & HCF_TYPE_AP */


            hcfStatus = wl_put_ltv( lp );

            /* Enable the ports */
            hcfStatus = wl_enable( lp, HCF_PORT_0 );

            if( hcfStatus != HCF_SUCCESS )
            {
                DBG_TRACE( DbgInfo, "Enable port 0 failed: 0x%x\n", hcfStatus );
            }

#if (HCF_TYPE) & HCF_TYPE_AP
            wl_enable_wds_ports( lp );
#endif  /* (HCF_TYPE) & HCF_TYPE_AP */
        }
    }

    DBG_LEAVE( DbgInfo );
    return hcfStatus;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_put_ltv()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Used by wvlan_apply() and wvlan_go to set the card's configuration.
 *
 *  PARAMETERS:
 *
 *      lp  - a pointer to the wireless adapter's private structure
 *
 *  RETURNS:
 *
 *      an HCF status code
 *
 ******************************************************************************/
int wl_put_ltv( struct wl_private *lp )
{
    int len;
    int hcfStatus;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_put_ltv" );
    DBG_ENTER( DbgInfo );


    if( lp->DownloadFirmware == WVLAN_DRV_MODE_AP )
    {
        lp->maxPort = 6;
    }
    else
    {
        lp->maxPort = 0;
    }


    if( lp == NULL )
    {
        DBG_ERROR( DbgInfo, "lp pointer is NULL\n" );
        return -1;
    }

    
    /* Send our configuration to the card. Perform any endian translation
       necessary */


    /* Register the Mailbox; VxWorks does this elsewhere; why? */
    lp->ltvRecord.len       = 4;
    lp->ltvRecord.typ       = CFG_REG_MB;
    lp->ltvRecord.u.u32[0]  = (u_long)&( lp->mailbox );
    lp->ltvRecord.u.u16[2]  = ( MB_SIZE / sizeof( hcf_16 ));

    hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    DBG_TRACE( DbgInfo, "CFG_REG_MB                        : 0x%p\n", 
               &( lp->mailbox ));
    DBG_TRACE( DbgInfo, "CFG_REG_MB result                 : 0x%04x\n",
               hcfStatus );


    /* Max Data Length */
    lp->ltvRecord.len       = 2;
    lp->ltvRecord.typ       = CFG_CNF_MAX_DATA_LEN;
    lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( HCF_MAX_PACKET_SIZE );

    hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    DBG_TRACE( DbgInfo, "CFG_CNF_MAX_DATA_LEN              : 0x%04x\n", 
               HCF_MAX_PACKET_SIZE );
    DBG_TRACE( DbgInfo, "CFG_CNF_MAX_DATA_LEN result       : 0x%04x\n", 
               hcfStatus );


    /* System Scale / Distance between APs */
    lp->ltvRecord.len       = 2;
    lp->ltvRecord.typ       = CFG_CNF_SYSTEM_SCALE;
    lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->DistanceBetweenAPs );

    hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    DBG_TRACE( DbgInfo, "CFG_CNF_SYSTEM_SCALE              : 0x%04x\n",
               lp->DistanceBetweenAPs );
    DBG_TRACE( DbgInfo, "CFG_CNF_SYSTEM_SCALE result       : 0x%04x\n", 
               hcfStatus );


    /* Channel */
    if( lp->CreateIBSS && ( lp->Channel == 0 ))
    {
        DBG_TRACE( DbgInfo, "Create IBSS" );
        lp->Channel = 10;
    }

    lp->ltvRecord.len       = 2;
    lp->ltvRecord.typ       = CFG_CNF_OWN_CHANNEL;
    lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->Channel );

    hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    DBG_TRACE( DbgInfo, "CFG_CNF_OWN_CHANNEL               : 0x%04x\n", 
               lp->Channel );
    DBG_TRACE( DbgInfo, "CFG_CNF_OWN_CHANNEL result        : 0x%04x\n", 
               hcfStatus );


    /* Microwave Robustness */
    lp->ltvRecord.len       = 2;
    lp->ltvRecord.typ       = CFG_CNF_MICRO_WAVE;
    lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->MicrowaveRobustness );

    hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    DBG_TRACE( DbgInfo, "CFG_CNF_MICRO_WAVE                : 0x%04x\n",
               lp->MicrowaveRobustness );
    DBG_TRACE( DbgInfo, "CFG_CNF_MICRO_WAVE result         : 0x%04x\n", 
               hcfStatus );


    /* Multicast Rate */
    lp->ltvRecord.len       = 2;
    lp->ltvRecord.typ       = CFG_CNF_MCAST_RATE;
    lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->MulticastRate );

    hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    DBG_TRACE( DbgInfo, "CFG_CNF_MCAST_RATE                : 0x%04x\n",
               lp->MulticastRate );
    DBG_TRACE( DbgInfo, "CFG_CNF_MCAST_RATE result         : 0x%04x\n", 
               hcfStatus );


    /* Own Name (Station Nickname) */
    if(( len = ( strlen( lp->StationName ) + 1 ) & ~0x01 ) != 0 )
    {
        DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME                  : %s\n",
                   lp->StationName );

        lp->ltvRecord.len       = 2 + ( len / sizeof( hcf_16 ));
        lp->ltvRecord.typ       = CFG_CNF_OWN_NAME;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( strlen( lp->StationName ));

        memcpy( &( lp->ltvRecord.u.u8[2] ), lp->StationName, len );  
    }
    else
    {
        DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME                  : EMPTY\n" );

        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_OWN_NAME;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0 );
    }
    
    hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME result           : 0x%04x\n", 
               hcfStatus );


    if( lp->DownloadFirmware != WVLAN_DRV_MODE_AP )
    {
        /* The following are set in STA mode only */
#if (HCF_TYPE) & HCF_TYPE_STA

        /* RTS Threshold */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_RTS_THRH;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->RTSThreshold );
        
        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_RTS_THRH                      : 0x%04x\n",
                   lp->RTSThreshold );
        DBG_TRACE( DbgInfo, "CFG_RTS_THRH result               : 0x%04x\n", 
                   hcfStatus );


        /* Port Type */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_PORT_TYPE;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->PortType );
        
        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_PORT_TYPE                 : 0x%04x\n",
                   lp->PortType );
        DBG_TRACE( DbgInfo, "CFG_CNF_PORT_TYPE result          : 0x%04x\n", 
                   hcfStatus );

        
        /* Tx Rate Control */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_TX_RATE_CNTL;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->TxRateControl );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL                  : 0x%04x\n",
                   lp->TxRateControl );
        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL result           : 0x%04x\n", 
                   hcfStatus );


        /* Power Management */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_PM_ENABLED;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->PMEnabled );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_PM_ENABLED                : 0x%04x\n",
                   lp->PMEnabled );
        DBG_TRACE( DbgInfo, "CFG_CNF_PM_ENABLED result         : 0x%04x\n", 
                   hcfStatus );


        /* Multicast Receive */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_MCAST_RX;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->MulticastReceive );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_MCAST_RX                  : 0x%04x\n",
                   lp->MulticastReceive );
        DBG_TRACE( DbgInfo, "CFG_CNF_MCAST_RX result           : 0x%04x\n", 
                   hcfStatus );


        /* Max Sleep Duration */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_MAX_SLEEP_DURATION;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->MaxSleepDuration );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_MAX_SLEEP_DURATION        : 0x%04x\n",
                   lp->MaxSleepDuration );
        DBG_TRACE( DbgInfo, "CFG_CNF_MAX_SLEEP_DURATION result : 0x%04x\n",
                   hcfStatus );

        
        /* Create IBSS */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CREATE_IBSS;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->CreateIBSS );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CREATE_IBSS                   : 0x%04x\n",
                   lp->CreateIBSS );
        DBG_TRACE( DbgInfo, "CFG_CREATE_IBSS result            : 0x%04x\n",
                   hcfStatus );


        /* Desired SSID */
        if ((( len = ( strlen( lp->NetworkName ) + 1 ) & ~0x01 ) != 0 ) &&
             ( strcmp( lp->NetworkName, "ANY" ) != 0 ) &&
             ( strcmp( lp->NetworkName, "any" ) != 0 ))
        {
            DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID                  : %s\n",
                       lp->NetworkName );

            lp->ltvRecord.len       = 2 + (len / sizeof(hcf_16));
            lp->ltvRecord.typ       = CFG_DESIRED_SSID;
            lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( strlen( lp->NetworkName ));

            memcpy( &( lp->ltvRecord.u.u8[2] ), lp->NetworkName, len );
        }
        else
        {
            DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID                  : ANY\n" );

            lp->ltvRecord.len       = 2;
            lp->ltvRecord.typ       = CFG_DESIRED_SSID;
            lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0 );
        }
        
        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID result           : 0x%04x\n",
                   hcfStatus );


        /* Own ATIM window */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_OWN_ATIM_WINDOW;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->atimWindow );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        
        DBG_TRACE( DbgInfo, "CFG_CNF_OWN_ATIM_WINDOW           : 0x%04x\n",
                   lp->atimWindow );
        DBG_TRACE( DbgInfo, "CFG_CNF_OWN_ATIM_WINDOW result    : 0x%04x\n",
                   hcfStatus );


        /* Holdover Duration */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_HOLDOVER_DURATION;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->holdoverDuration );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_HOLDOVER_DURATION         : 0x%04x\n",
                   lp->holdoverDuration );
        DBG_TRACE( DbgInfo, "CFG_CNF_HOLDOVER_DURATION result  : 0x%04x\n",
                   hcfStatus );


        /* Promiscuous Mode */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_PROMISCUOUS_MODE;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->promiscuousMode );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_PROMISCUOUS_MODE              : 0x%04x\n",
                   lp->promiscuousMode );
        DBG_TRACE( DbgInfo, "CFG_PROMISCUOUS_MODE result       : 0x%04x\n",
                   hcfStatus );


        /* Authentication */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_AUTHENTICATION;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->authentication );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_AUTHENTICATION            : 0x%04x\n",
                   lp->authentication );
        DBG_TRACE( DbgInfo, "CFG_CNF_AUTHENTICATION result     : 0x%04x\n",
                   hcfStatus );


#endif  // (HCF_TYPE) & HCF_TYPE_STA
    }
    else
    {
        /* The following are set in AP mode only */
#if (HCF_TYPE) & HCF_TYPE_AP

        /* DTIM Period */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_OWN_DTIM_PERIOD;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->DTIMPeriod );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_OWN_DTIM_PERIOD           : 0x%04x\n",
                   lp->DTIMPeriod );
        DBG_TRACE( DbgInfo, "CFG_CNF_OWN_DTIM_PERIOD result    : 0x%04x\n",
                   hcfStatus );


        /* Multicast PM Buffering */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_MCAST_PM_BUF;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->multicastPMBuffering );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_MCAST_PM_BUF              : 0x%04x\n",
                   lp->multicastPMBuffering );
        DBG_TRACE( DbgInfo, "CFG_CNF_MCAST_PM_BUF result       : 0x%04x\n", 
                   hcfStatus );


        /* Reject ANY - Closed System */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_REJECT_ANY;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->RejectAny );
        
        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_REJECT_ANY                : 0x%04x\n",
                   lp->RejectAny );
        DBG_TRACE( DbgInfo, "CFG_CNF_REJECT_ANY result         : 0x%04x\n",
                   hcfStatus );


        /* Exclude Unencrypted */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_EXCL_UNENCRYPTED;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->ExcludeUnencrypted );
        
        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_EXCL_UNENCRYPTED          : 0x%04x\n",
                   lp->ExcludeUnencrypted );
        DBG_TRACE( DbgInfo, "CFG_CNF_EXCL_UNENCRYPTED result   : 0x%04x\n",
                   hcfStatus );


        /* IntraBSS Relay */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_INTRA_BSS_RELAY;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->intraBSSRelay );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_INTRA_BSS_RELAY           : 0x%04x\n",
                   lp->intraBSSRelay );
        DBG_TRACE( DbgInfo, "CFG_CNF_INTRA_BSS_RELAY result    : 0x%04x\n",
                   hcfStatus );


        /* RTS Threshold 0 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_RTS_THRH0;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->RTSThreshold );
        
        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_RTS_THRH0                     : 0x%04x\n",
                   lp->RTSThreshold );
        DBG_TRACE( DbgInfo, "CFG_RTS_THRH0 result              : 0x%04x\n",
                   hcfStatus );


        /* Tx Rate Control 0 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_TX_RATE_CNTL0;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->TxRateControl );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL0                 : 0x%04x\n",
                   lp->TxRateControl );
        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL0 result          : 0x%04x\n",
                   hcfStatus );


#ifdef USE_WDS

        /* RTS Threshold 1 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_RTS_THRH1;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->wds_port[0].rtsThreshold );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_RTS_THRH1                     : 0x%04x\n",
                   lp->wds_port[0].rtsThreshold );
        DBG_TRACE( DbgInfo, "CFG_RTS_THRH1 result              : 0x%04x\n",
                   hcfStatus );


        /* RTS Threshold 2 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_RTS_THRH2;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->wds_port[1].rtsThreshold );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_RTS_THRH2                     : 0x%04x\n",
                   lp->wds_port[1].rtsThreshold );
        DBG_TRACE( DbgInfo, "CFG_RTS_THRH2 result              : 0x%04x\n",
                   hcfStatus );



        /* RTS Threshold 3 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_RTS_THRH3;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->wds_port[2].rtsThreshold );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_RTS_THRH3                     : 0x%04x\n",
                   lp->wds_port[2].rtsThreshold );
        DBG_TRACE( DbgInfo, "CFG_RTS_THRH3 result              : 0x%04x\n",
                   hcfStatus );



        /* RTS Threshold 4 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_RTS_THRH4;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->wds_port[3].rtsThreshold );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_RTS_THRH4                     : 0x%04x\n",
                   lp->wds_port[3].rtsThreshold );
        DBG_TRACE( DbgInfo, "CFG_RTS_THRH4 result              : 0x%04x\n",
                   hcfStatus );



        /* RTS Threshold 5 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_RTS_THRH5;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->wds_port[4].rtsThreshold );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_RTS_THRH5                     : 0x%04x\n",
                   lp->wds_port[4].rtsThreshold );
        DBG_TRACE( DbgInfo, "CFG_RTS_THRH5 result              : 0x%04x\n",
                   hcfStatus );


        /* RTS Threshold 6 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_RTS_THRH6;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->wds_port[5].rtsThreshold );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_RTS_THRH6                     : 0x%04x\n",
                   lp->wds_port[5].rtsThreshold );
        DBG_TRACE( DbgInfo, "CFG_RTS_THRH6 result              : 0x%04x\n",
                   hcfStatus );


        /* TX Rate Control 1 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_TX_RATE_CNTL1;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->wds_port[0].txRateCntl );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL1                 : 0x%04x\n",
                   lp->wds_port[0].txRateCntl );
        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL1 result          : 0x%04x\n",
                   hcfStatus );


        /* TX Rate Control 2 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_TX_RATE_CNTL2;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->wds_port[1].txRateCntl );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL2                 : 0x%04x\n",
                   lp->wds_port[1].txRateCntl );
        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL2 result          : 0x%04x\n",
                   hcfStatus );


        /* TX Rate Control 3 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_TX_RATE_CNTL3;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->wds_port[2].txRateCntl );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL3                 : 0x%04x\n",
                   lp->wds_port[2].txRateCntl );
        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL3 result          : 0x%04x\n",
                   hcfStatus );


        /* TX Rate Control 4 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_TX_RATE_CNTL4;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->wds_port[3].txRateCntl );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL4                 : 0x%04x\n",
                   lp->wds_port[3].txRateCntl );
        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL4 result          : 0x%04x\n",
                   hcfStatus );


        /* TX Rate Control 5 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_TX_RATE_CNTL5;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->wds_port[4].txRateCntl );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL5                 : 0x%04x\n",
                   lp->wds_port[4].txRateCntl );
        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL5 result          : 0x%04x\n",
                   hcfStatus );


        /* TX Rate Control 6 */
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_TX_RATE_CNTL6;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->wds_port[5].txRateCntl );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL6                 : 0x%04x\n",
                   lp->wds_port[5].txRateCntl );
        DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL6 result          : 0x%04x\n",
                   hcfStatus );


        /* WDS addresses.  It's okay to blindly send these parameters, because 
           the port needs to be enabled, before anything is done with it. */

        /* WDS Address 1 */
        lp->ltvRecord.len      = 4;
        lp->ltvRecord.typ      = CFG_CNF_WDS_ADDR1;

        memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[0].wdsAddress, ETH_ALEN );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_WDS_ADDR1                 : %s\n",
                   DbgHwAddr( lp->wds_port[0].wdsAddress ));
        DBG_TRACE( DbgInfo, "CFG_CNF_WDS_ADDR1 result          : 0x%04x\n",
                   hcfStatus );


        /* WDS Address 2 */
        lp->ltvRecord.len      = 4;
        lp->ltvRecord.typ      = CFG_CNF_WDS_ADDR2;

        memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[1].wdsAddress, ETH_ALEN );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_WDS_ADDR2                 : %s\n",
                   DbgHwAddr( lp->wds_port[1].wdsAddress ));
        DBG_TRACE( DbgInfo, "CFG_CNF_WDS_ADDR2 result          : 0x%04x\n",
                   hcfStatus );


        /* WDS Address 3 */
        lp->ltvRecord.len      = 4;
        lp->ltvRecord.typ      = CFG_CNF_WDS_ADDR3;

        memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[2].wdsAddress, ETH_ALEN );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_WDS_ADDR3                 : %s\n",
                   DbgHwAddr( lp->wds_port[2].wdsAddress ));
        DBG_TRACE( DbgInfo, "CFG_CNF_WDS_ADDR3 result          : 0x%04x\n",
                   hcfStatus );


        /* WDS Address 4 */
        lp->ltvRecord.len      = 4;
        lp->ltvRecord.typ      = CFG_CNF_WDS_ADDR4;

        memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[3].wdsAddress, ETH_ALEN );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_WDS_ADDR4                 : %s\n",
                   DbgHwAddr( lp->wds_port[3].wdsAddress ));
        DBG_TRACE( DbgInfo, "CFG_CNF_WDS_ADDR4 result          : 0x%04x\n",
                   hcfStatus );


        /* WDS Address 5 */
        lp->ltvRecord.len      = 4;
        lp->ltvRecord.typ      = CFG_CNF_WDS_ADDR5;

        memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[4].wdsAddress, ETH_ALEN );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_WDS_ADDR5                 : %s\n",
                   DbgHwAddr( lp->wds_port[4].wdsAddress ));
        DBG_TRACE( DbgInfo, "CFG_CNF_WDS_ADDR5 result          : 0x%04x\n",
                   hcfStatus );


        /* WDS Address 6 */
        lp->ltvRecord.len      = 4;
        lp->ltvRecord.typ      = CFG_CNF_WDS_ADDR6;

        memcpy( &lp->ltvRecord.u.u8[0], lp->wds_port[5].wdsAddress, ETH_ALEN );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

        DBG_TRACE( DbgInfo, "CFG_CNF_WDS_ADDR6                 : %s\n",
                   DbgHwAddr( lp->wds_port[5].wdsAddress ));
        DBG_TRACE( DbgInfo, "CFG_CNF_WDS_ADDR6 result          : 0x%04x\n",
                   hcfStatus );

#endif  /* USE_WDS */
#endif  /* (HCF_TYPE) & HCF_TYPE_AP */
    }

    /* Own MAC Address */
    DBG_TRACE( DbgInfo, "MAC Address                       : %s\n",
               DbgHwAddr( lp->MACAddress ));

    if( WVLAN_VALID_MAC_ADDRESS( lp->MACAddress ))
    {
        /* Make the MAC address valid by:
                Clearing the multicast bit
                Setting the local MAC address bit
        */

        //lp->MACAddress[0] &= ~0x03;
        //lp->MACAddress[0] |= 0x02;

        lp->ltvRecord.len = 1 + ( ETH_ALEN / sizeof( hcf_16 ));

        if( lp->DownloadFirmware != WVLAN_DRV_MODE_AP )
        {
            DBG_TRACE( DbgInfo, "CFG_CNF_OWN_MAC_ADDR\n" );
            lp->ltvRecord.typ = CFG_CNF_OWN_MAC_ADDR;
        }
        else
        {
            DBG_TRACE( DbgInfo, "CFG_NIC_MAC_ADDR\n" );
            lp->ltvRecord.typ = CFG_NIC_MAC_ADDR;
        }
 
        /* MAC address is byte aligned, no endian conversion needed */
        memcpy( &( lp->ltvRecord.u.u8[0] ), lp->MACAddress, ETH_ALEN );

        hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
        DBG_TRACE( DbgInfo, "CFG_XXX_MAC_ADDR result           : 0x%04x\n",
                   hcfStatus );

        /* Update the MAC address in the netdevice struct */
        memcpy( lp->dev->dev_addr, lp->MACAddress, ETH_ALEN );
    }


    /* Own SSID */
    if ((( len = ( strlen( lp->NetworkName ) + 1 ) & ~0x01 ) != 0 ) &&
                 ( strcmp( lp->NetworkName, "ANY" ) != 0 ) &&
                 ( strcmp( lp->NetworkName, "any" ) != 0 ))
    {
        DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID                  : %s\n",
                   lp->NetworkName );
        lp->ltvRecord.len       = 2 + (len / sizeof(hcf_16));
        lp->ltvRecord.typ       = CFG_CNF_OWN_SSID;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( strlen( lp->NetworkName ));
        
        memcpy( &( lp->ltvRecord.u.u8[2] ), lp->NetworkName, len );
    }
    else
    {
        DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID                  : ANY\n" );
        lp->ltvRecord.len       = 2;
        lp->ltvRecord.typ       = CFG_CNF_OWN_SSID;
        lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0 );
    }


    hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID result           : 0x%04x\n",
               hcfStatus );


    /* enable/disable encryption */
    lp->ltvRecord.len       = 2;
    lp->ltvRecord.typ       = CFG_CNF_ENCRYPTION;
    lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->EnableEncryption );

    hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    DBG_TRACE( DbgInfo, "CFG_CNF_ENCRYPTION                : 0x%04x\n",
                   lp->EnableEncryption );
    DBG_TRACE( DbgInfo, "CFG_CNF_ENCRYPTION result         : 0x%04x\n",
                hcfStatus );


    /* Set the Authentication Key Management Suite */
    lp->ltvRecord.len       = 2;
    lp->ltvRecord.typ       = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
    lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->AuthKeyMgmtSuite );

    hcfStatus = hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    DBG_TRACE( DbgInfo, "CFG_SET_WPA_AUTH_KEY_MGMT_SUITE   : 0x%04x\n",
               lp->AuthKeyMgmtSuite );
    DBG_TRACE( DbgInfo, "CFG_SET_WPA_AUTH_KEY_MGMT_SUITE result: 0x%04x\n",
               hcfStatus );

    /* WEP Keys */
    wl_set_wep_keys( lp );

    /* Country Code */
    /* countryInfo, ltvCountryInfo, CFG_CNF_COUNTRY_INFO */

    DBG_LEAVE( DbgInfo );
    return hcfStatus;
}
/*============================================================================*/




/*******************************************************************************
 *	init_module()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Load the kernel module.
 *
 *  PARAMETERS:
 *
 *      N/A
 *
 *  RETURNS:
 *
 *      0 on success
 *      an errno value otherwise
 *
 ******************************************************************************/

//int __init init_module( void )
int init_module( void )
{
    int result;
    /*------------------------------------------------------------------------*/

    
    DBG_FUNC( "init_module" );

#if DBG
    DbgInfo->dbgFlags = debug_flags;

    /* Convert the pc_debug to a reasonable Debug Info value. NOTE: The values
       all fall through to the lower values. */
    switch( pc_debug )
    {
    case 7:
        DbgInfo->dbgFlags |= ( DBG_RX_ON | DBG_TX_ON );


    case 6:
        DbgInfo->dbgFlags |= DBG_PARAM_ON;


    case 5:
        DbgInfo->dbgFlags |= DBG_TRACE_ON;


    case 4:
        DbgInfo->dbgFlags |= DBG_VERBOSE_ON;


    default:
        break;
    }
#endif /* DBG */

    DBG_ENTER( DbgInfo );
    DBG_PRINT( "%s\n", VERSION_INFO );


    /* Print out the STA/AP mode support in the build */
#if (HCF_TYPE) & HCF_TYPE_STA
    DBG_PRINT( "Station Mode (STA) Support: YES\n" );
#else
    DBG_PRINT( "Station Mode (STA) Support: NO\n" );
#endif /* (HCF_TYPE) & HCF_TYPE_STA */

#if (HCF_TYPE) & HCF_TYPE_AP
    DBG_PRINT( "Access Point Mode (AP) Support: YES\n" );
#else
    DBG_PRINT( "Access Point Mode (AP) Support: NO\n" );
#endif /* (HCF_TYPE) & HCF_TYPE_AP */


    result = wl_adapter_init_module( );

    DBG_LEAVE( DbgInfo );
    return result;
}
/*============================================================================*/




/*******************************************************************************
 *	cleanup_module()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Unload the kernel module.
 *
 *  PARAMETERS:
 *
 *      N/A
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
//void __exit cleanup_module( void )
void cleanup_module( void )
{
    DBG_FUNC("cleanup_module");
    DBG_ENTER(DbgInfo);


    wl_adapter_cleanup_module( );


    DBG_LEAVE( DbgInfo );
    return;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_isr()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      The Interrupt Service Routine for the driver.
 *
 *  PARAMETERS:
 *
 *      irq     -   the irq the interrupt came in on
 *      dev_id  -   a buffer containing information about the request
 *      regs    - 
 * 
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void wl_isr( int irq, void *dev_id, struct pt_regs *regs )
{
    int                 events;
    struct net_device   *dev = (struct net_device *) dev_id;
    struct wl_private   *lp = NULL;
    /*------------------------------------------------------------------------*/


    if(( dev == NULL ) || ( !netif_device_present( dev )))
    {
        return;
    }

    /* Set the wl_private pointer (lp), now that we know that dev is non-null */
    lp = (struct wl_private *)dev->priv;

    if( lp != NULL )
    {

#ifdef USE_RTS
        if( lp->useRTS == 1 )
        {
            DBG_PRINT( "EXITING ISR, IN RTS MODE...\n" );
            return;
        }
#endif  /* USE_RTS */

        /* If we have interrupts pending, then put them on a system task
           queue. Otherwise turn interrupts back on */
        events = hcf_action( &( lp->hcfCtx ), HCF_ACT_INT_OFF );

        if( events == HCF_INT_PENDING )
        {
            /* Schedule the ISR handler as a bottom-half task in the
               tq_immediate queue */
            queue_task( &( lp->task ), &tq_immediate );
            mark_bh( IMMEDIATE_BH );
        }
        else
        {
            hcf_action( &( lp->hcfCtx ), HCF_ACT_INT_ON );
        }
    }

    return;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_isr_handler()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      The ISR handler, scheduled to run in a deferred context by the ISR. This
 *      is where the ISR's work actually gets done.
 *
 *  PARAMETERS:
 *
 *      lp  - a pointer to the device's private adapter structure
 * 
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void wl_isr_handler( struct wl_private *lp )
{
    struct net_device       *dev;
    unsigned long           flags;
    bool_t                  done;
    int                     count;
    int                     result;
    /*------------------------------------------------------------------------*/


#define WVLAN_MAX_INT_SERVICES  50

    if( lp != NULL )
    {
        spin_lock_irqsave( &( lp->slock ), flags );

        dev = (struct net_device *)lp->dev;
        
        count = 0;
        
        if( dev != NULL && netif_device_present( dev ))
        {
            for( count = 0; count < WVLAN_MAX_INT_SERVICES; count++ )
            {
                done = TRUE;
            
                result = hcf_service_nic( &( lp->hcfCtx ),
                                          (wci_bufp)lp->lookAheadBuf,
                                          sizeof( lp->lookAheadBuf ));

                if( result == HCF_ERR_MIC )
                {
                    /* Send an event that MIC failed */
                    wl_wext_event_mic_failed( dev );
                }

#ifndef USE_MBOX_SYNC
                /* Check to see if there is anything in the mailbox */
                if( lp->hcfCtx.IFB_MBInfoLen != 0 )
                {
                    wl_mbx( lp );

                    done = FALSE;
                }
#endif

                /* Check for Rx packets */
                if( lp->hcfCtx.IFB_RxLen != 0 )
                {
                    wl_rx( dev );

                    done = FALSE;
                }

                /* Make sure that queued frames get sent */ 
                if( wl_send( lp ))
                {
                    done = FALSE;
                }                 
                    
                if( done )
                {
                    break;
                }
            }
        }

        /* We're done, so turn interrupts back on */
        hcf_action( &(lp->hcfCtx), HCF_ACT_INT_ON );

        spin_unlock_irqrestore( &( lp->slock ), flags );
    }
    else
    {
        DBG_PRINT( "wl_isr_handler  lp adapter pointer is NULL!!!\n" );
    }

    return;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_remove()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Notify the adapter that it has been removed. Since the adapter is gone,
 *  we should no longer try to talk to it.
 *
 *  PARAMETERS:
 *
 *      dev - a pointer to the device's net_device structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void wl_remove( struct net_device *dev )
{
    struct wl_private   *lp = NULL;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_remove" );
    DBG_ENTER( DbgInfo );

    DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
    

    unregister_netdev( dev );

    if(( lp = ( struct wl_private * ) dev->priv ) != NULL )
    {
        unsigned long   flags;

        spin_lock_irqsave( &( lp->slock ), flags );

        /* Mark the device as unregistered */
        lp->is_registered = FALSE;


        /* Deregister the WDS ports as well */
        WL_WDS_NETDEV_DEREGISTER( lp );


#ifdef USE_RTS
        if( lp->useRTS == 1 )
        {
            spin_unlock_irqrestore( &( lp->slock ), flags );
            
            DBG_LEAVE( DbgInfo );
            return;
        }
#endif  /* USE_RTS */

        /* Inform the HCF that the card has been removed */
        hcf_disconnect( &( lp->hcfCtx ));

        spin_unlock_irqrestore( &( lp->slock ), flags );
    }


    DBG_LEAVE( DbgInfo );
    return;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_suspend()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Power-down and halt the adapter.
 *
 *  PARAMETERS:
 *
 *      dev - a pointer to the device's net_device structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void wl_suspend( struct net_device *dev )
{
    struct wl_private  *lp = NULL;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_suspend" );
    DBG_ENTER( DbgInfo );

    DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );


    if(( lp = (struct wl_private *)dev->priv ) != NULL )
    {
        unsigned long   flags;

        /* The adapter is suspended:
                Stop the adapter
                Power down
        */
        spin_lock_irqsave( &( lp->slock ), flags );

        hcf_disconnect( &( lp->hcfCtx ));

        spin_unlock_irqrestore( &( lp->slock ), flags );
    }

    DBG_LEAVE( DbgInfo );
    return;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_resume()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Resume a previously suspended adapter.
 *
 *  PARAMETERS:
 *
 *      dev - a pointer to the device's net_device structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void wl_resume(struct net_device *dev)
{
    struct wl_private  *lp = NULL;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_resume" );
    DBG_ENTER( DbgInfo );

    DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );


    if(( lp = (struct wl_private *)dev->priv ) != NULL )
    {
        unsigned long   flags;


        spin_lock_irqsave( &( lp->slock ), flags );

        hcf_connect( &( lp->hcfCtx ), dev->base_addr );

        spin_unlock_irqrestore( &( lp->slock ), flags );
    }

    DBG_LEAVE( DbgInfo );
    return;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_release()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      This function perfroms a check on the device and calls wl_remove() if
 *  necessary. This function can be used for all bus types, but exists mostly
 *  for the benefit of the Card Services driver, as there are times when
 *  wl_remove() does not get called.
 *
 *  PARAMETERS:
 *
 *      dev - a pointer to the device's net_device structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void wl_release( struct net_device *dev )
{
    struct wl_private  *lp = NULL;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_release" );
    DBG_ENTER( DbgInfo );

    DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );


    if(( lp = (struct wl_private *)dev->priv ) != NULL )
    {
        /* If wl_remove() hasn't been called (i.e. when Card Services is shut
           down with the card in the slot), then call it */    
        if( lp->is_registered == TRUE )
        {
            DBG_TRACE( DbgInfo, "Calling unregister_netdev(), as it wasn't called yet\n" );
            wl_remove( dev );

            lp->is_registered = FALSE;
        }
    }

    DBG_LEAVE( DbgInfo );
    return;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_get_irq_mask()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Accessor function to retrieve the irq_mask module parameter
 *
 *  PARAMETERS:
 *
 *      N/A
 *
 *  RETURNS:
 *
 *      The irq_mask module parameter
 *
 ******************************************************************************/
p_u16 wl_get_irq_mask( void )
{
    return irq_mask;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_get_irq_list()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Accessor function to retrieve the irq_list module parameter
 *
 *  PARAMETERS:
 *
 *      N/A
 *
 *  RETURNS:
 *
 *      The irq_list module parameter
 *
 ******************************************************************************/
p_s8 * wl_get_irq_list( void )
{
    return irq_list;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_get_pri_records()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      gets information on the firmware
 *
 *  PARAMETERS:
 *
 *      lp - pointer to the device's private adapter structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void wl_get_pri_records( struct wl_private *lp )
{
    int hcfStatus;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wvlanGetPriRecords" );
    DBG_ENTER( DbgInfo );


	/* obtain STA IDENT here. */
	lp->PrimaryIdentity.len = ( sizeof( CFG_PRI_IDENTITY_STRCT ) / sizeof( hcf_16 )) - 1 ;
	lp->PrimaryIdentity.typ = CFG_FW_IDENTITY;
	
    hcfStatus = hcf_get_info( &lp->hcfCtx, (LTVP)&lp->PrimaryIdentity );

	DBG_TRACE( DbgInfo, "PRI %d variant %d version %d.%02d hcfStatus = %d\n", 
                CNV_INT_TO_LITTLE( lp->PrimaryIdentity.comp_id ), 
                CNV_INT_TO_LITTLE( lp->PrimaryIdentity.variant ), 
                CNV_INT_TO_LITTLE( lp->PrimaryIdentity.version_major ), 
                CNV_INT_TO_LITTLE( lp->PrimaryIdentity.version_minor ), 
                hcfStatus );

    /* change the RID back to original value */
	lp->PrimaryIdentity.typ = CFG_PRI_IDENTITY;


	/* obtain NIC IDENT here. */
	lp->NICIdentity.len = ( sizeof( CFG_NIC_IDENTITY_STRCT ) / sizeof( hcf_16 )) - 1 ;
	lp->NICIdentity.typ = CFG_NIC_IDENTITY ;
	
    hcfStatus = hcf_get_info( &lp->hcfCtx, (LTVP)&lp->NICIdentity );

	DBG_TRACE( DbgInfo, "NIC %d variant %d version %d.%02d hcfStatus = %d\n", 
                CNV_INT_TO_LITTLE( lp->NICIdentity.comp_id ), 
                CNV_INT_TO_LITTLE( lp->NICIdentity.variant ), 
                CNV_INT_TO_LITTLE( lp->NICIdentity.version_major ), 
                CNV_INT_TO_LITTLE( lp->NICIdentity.version_minor ), 
                hcfStatus );


    DBG_LEAVE( DbgInfo );
    return;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_enable()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Used to enable MAC ports
 *
 *  PARAMETERS:
 *
 *      lp      - pointer to the device's private adapter structure
 *      port    - the MAC port to enable
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
int wl_enable( struct wl_private *lp, hcf_16 port )
{
    int hcf_status;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_enable" );
    DBG_ENTER( DbgInfo );


    if(( port != HCF_PORT_0 ) && ( lp->DownloadFirmware != WVLAN_DRV_MODE_AP ))
    {
        DBG_LEAVE( DbgInfo );
        return HCF_FAILURE;
    }

    if(( port == HCF_PORT_0 ) && ( lp->portState == WVLAN_PORT_STATE_ENABLED ))
    {
        DBG_LEAVE( DbgInfo );
        return HCF_SUCCESS;
    }

    //hcf_status = hcf_cntl_port( &( lp->hcfCtx ), HCF_PORT_ENABLE | port );
    hcf_status = hcf_cntl( &( lp->hcfCtx ), HCF_CNTL_ENABLE | port );

    if( hcf_status == HCF_SUCCESS )
    {
        /* Set the status of the port to enabled */
        lp->portState = WVLAN_PORT_STATE_ENABLED;
    }

    DBG_LEAVE( DbgInfo );
    return hcf_status;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_enable_wds_ports()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Used to enable the WDS MAC ports 1-6
 *
 *  PARAMETERS:
 *
 *      lp      - pointer to the device's private adapter structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void wl_enable_wds_ports( struct wl_private * lp )
{

    DBG_FUNC( "wl_enable_wds_ports" );
    DBG_ENTER( DbgInfo );


#ifdef USE_WDS
    if( lp->DownloadFirmware == WVLAN_DRV_MODE_AP )
    {
        if( WVLAN_VALID_MAC_ADDRESS( lp->wds_port[0].wdsAddress ))
        {
            wl_enable( lp, HCF_PORT_1 );
        }

        if( WVLAN_VALID_MAC_ADDRESS( lp->wds_port[1].wdsAddress ))
        {
            wl_enable( lp, HCF_PORT_2 );
        }

        if( WVLAN_VALID_MAC_ADDRESS( lp->wds_port[2].wdsAddress ))
        {
            wl_enable( lp, HCF_PORT_3 );
        }

        if( WVLAN_VALID_MAC_ADDRESS( lp->wds_port[3].wdsAddress ))
        {
            wl_enable( lp, HCF_PORT_4 );
        }

        if( WVLAN_VALID_MAC_ADDRESS( lp->wds_port[4].wdsAddress ))
        {
            wl_enable( lp, HCF_PORT_5 );
        }

        if( WVLAN_VALID_MAC_ADDRESS( lp->wds_port[5].wdsAddress ))
        {
            wl_enable( lp, HCF_PORT_6 );
        }
    }
#endif  /* USE_WDS */

    DBG_LEAVE( DbgInfo );
    return;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_disable()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Used to disable MAC ports
 *
 *  PARAMETERS:
 *
 *      lp      - pointer to the device's private adapter structure
 *      port    - the MAC port to disable
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
int wl_disable( struct wl_private *lp, hcf_16 port )
{
    int hcf_status;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_disable" );
    DBG_ENTER( DbgInfo );


    if(( port != HCF_PORT_0 ) && ( lp->DownloadFirmware != WVLAN_DRV_MODE_AP ))
    {
        DBG_LEAVE( DbgInfo );
        return HCF_FAILURE;
    }

    if(( port == HCF_PORT_0 ) && ( lp->portState == WVLAN_PORT_STATE_DISABLED ))
    {
        DBG_LEAVE( DbgInfo );
        return HCF_SUCCESS;
    }

    //hcf_status = hcf_cntl_port( &( lp->hcfCtx ), HCF_PORT_DISABLE | port );
    hcf_status = hcf_cntl( &( lp->hcfCtx ), HCF_CNTL_DISABLE | port );

    if( hcf_status == HCF_SUCCESS )
    {
        /* Set the status of the port to disabled */
        lp->portState = WVLAN_PORT_STATE_DISABLED;
    }

    DBG_LEAVE( DbgInfo );
    return hcf_status;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_disable_wds_ports()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Used to disable the WDS MAC ports 1-6
 *
 *  PARAMETERS:
 *
 *      lp      - pointer to the device's private adapter structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void wl_disable_wds_ports( struct wl_private * lp )
{

    DBG_FUNC( "wl_disable_wds_ports" );
    DBG_ENTER( DbgInfo );

#if (HCF_TYPE) & HCF_TYPE_AP
    if( lp->DownloadFirmware == WVLAN_DRV_MODE_AP )
    {
        wl_disable( lp, HCF_PORT_1 );
        wl_disable( lp, HCF_PORT_2 );
        wl_disable( lp, HCF_PORT_3 );
        wl_disable( lp, HCF_PORT_4 );
        wl_disable( lp, HCF_PORT_5 );
        wl_disable( lp, HCF_PORT_6 );
    }
#endif /* (HCF_TYPE) & HCF_TYPE_AP */

    DBG_LEAVE( DbgInfo );
    return;
}
/*============================================================================*/




#ifndef USE_MBOX_SYNC
/*******************************************************************************
 *	wl_mbx()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *      This function is used to read and process a mailbox message.
 *      
 *
 *  PARAMETERS:
 *
 *      lp      - pointer to the device's private adapter structure
 *
 *  RETURNS:
 *
 *      an HCF status code
 *
 ******************************************************************************/
int wl_mbx( struct wl_private *lp )
{
    int hcfStatus = HCF_SUCCESS;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_mbx" );
    DBG_ENTER( DbgInfo );


    DBG_TRACE( DbgInfo, "Mailbox Info: IFB_MBInfoLen: %d\n", 
               lp->hcfCtx.IFB_MBInfoLen );

    memset( &( lp->ltvRecord ), 0, sizeof( ltv_t ));

    lp->ltvRecord.len = MB_SIZE;
    lp->ltvRecord.typ = CFG_MB_INFO;

    hcfStatus = hcf_get_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));

    if( hcfStatus != HCF_SUCCESS )
    {
        DBG_ERROR( DbgInfo, "hcf_get_info returned 0x%x\n", hcfStatus );

        DBG_LEAVE( DbgInfo );
        return hcfStatus;
    }

    if( lp->ltvRecord.typ == CFG_MB_INFO )
    {
        DBG_LEAVE( DbgInfo );
        return hcfStatus;
    }


    /* Endian translate the mailbox data, then process the message */
    wl_endian_translate_mailbox( &( lp->ltvRecord ));
    wl_process_mailbox( lp );


    DBG_LEAVE( DbgInfo );
    return hcfStatus;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_endian_translate_mailbox()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      This function will perform the tedious task of endian translating all 
 *  fields withtin a mailbox message which need translating.
 *
 *  PARAMETERS:
 *
 *      ltv - pointer to the LTV to endian translate
 *
 *  RETURNS:
 *
 *      none
 *
 ******************************************************************************/
void wl_endian_translate_mailbox( ltv_t *ltv )
{

    DBG_FUNC( "wl_endian_translate_mailbox" );
    DBG_ENTER( DbgInfo );


    switch( ltv->typ )
    {
    case CFG_TALLIES:
        break;

    case CFG_SCAN:
        {
            int num_aps;
            SCAN_RS_STRCT *aps = (SCAN_RS_STRCT *)&ltv->u.u8[0];

            num_aps = (hcf_16)(( (size_t)(ltv->len - 1 ) * 2 ) /
                                 ( sizeof( SCAN_RS_STRCT )));

            while( num_aps >= 1 )
            {
                num_aps--;

                aps[num_aps].channel_id = 
                    CNV_LITTLE_TO_INT( aps[num_aps].channel_id );

                aps[num_aps].noise_level = 
                    CNV_LITTLE_TO_INT( aps[num_aps].noise_level );

                aps[num_aps].signal_level = 
                    CNV_LITTLE_TO_INT( aps[num_aps].signal_level );

                aps[num_aps].beacon_interval_time = 
                    CNV_LITTLE_TO_INT( aps[num_aps].beacon_interval_time );

                aps[num_aps].capability = 
                    CNV_LITTLE_TO_INT( aps[num_aps].capability );

                aps[num_aps].ssid_len = 
                    CNV_LITTLE_TO_INT( aps[num_aps].ssid_len );

                aps[num_aps].ssid_val[aps[num_aps].ssid_len] = 0;
            }
        }
        break;

    case CFG_ACS_SCAN:
        break;

    case CFG_LINK_STAT:
        {
            LINK_STATUS_STRCT *ls = (LINK_STATUS_STRCT *)ltv;

            ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
        }
        break;

    case CFG_ASSOC_STAT:
        {
            ASSOC_STATUS_STRCT *as = (ASSOC_STATUS_STRCT *)ltv;

            as->assocStatus = CNV_LITTLE_TO_INT( as->assocStatus );
        }
        break;

    case CFG_SECURITY_STAT:
        {
            SECURITY_STATUS_STRCT *ss = (SECURITY_STATUS_STRCT *)ltv;

            ss->securityStatus  = CNV_LITTLE_TO_INT( ss->securityStatus );
            ss->reason          = CNV_LITTLE_TO_INT( ss->reason );
        }
        break;

    case CFG_WMP:
        break;

    case CFG_NULL:
        break;

    default:
        break;
    }

    DBG_LEAVE( DbgInfo );
    return;
}
/*============================================================================*/





/*******************************************************************************
 *	wl_process_mailbox()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      This function will process the mailbox data.
 *
 *  PARAMETERS:
 *
 *      ltv - pointer to the LTV to be processed.
 *
 *  RETURNS:
 *
 *      none
 *
 ******************************************************************************/
void wl_process_mailbox( struct wl_private *lp )
{
    ltv_t   *ltv;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_process_mailbox" );
    DBG_ENTER( DbgInfo );


    ltv = &( lp->ltvRecord );
    
    switch( ltv->typ )
    {

    case CFG_TALLIES:
        DBG_TRACE( DbgInfo, "CFG_TALLIES\n" );
        break;


    case CFG_SCAN:
        DBG_TRACE( DbgInfo, "CFG_SCAN\n" );

        {
            int num_aps;
            SCAN_RS_STRCT *aps = (SCAN_RS_STRCT *)&ltv->u.u8[0];

            num_aps = (hcf_16)(( (size_t)(ltv->len - 1 ) * 2 ) /
                                 ( sizeof( SCAN_RS_STRCT )));

            lp->scan_results.num_aps = num_aps;
            
            DBG_TRACE( DbgInfo, "Number of APs: %d\n", num_aps );

            while( num_aps >= 1 )
            {
                num_aps--;

                DBG_TRACE( DbgInfo, "AP              : %d\n", num_aps );
                DBG_TRACE( DbgInfo, "=========================\n" );
                DBG_TRACE( DbgInfo, "Channel ID      : 0x%04x\n", 
                           aps[num_aps].channel_id );
                DBG_TRACE( DbgInfo, "Noise Level     : 0x%04x\n", 
                           aps[num_aps].noise_level );
                DBG_TRACE( DbgInfo, "Signal Level    : 0x%04x\n", 
                           aps[num_aps].signal_level );
                DBG_TRACE( DbgInfo, "Beacon Interval : 0x%04x\n", 
                           aps[num_aps].beacon_interval_time );
                DBG_TRACE( DbgInfo, "Capability      : 0x%04x\n", 
                           aps[num_aps].capability );
                DBG_TRACE( DbgInfo, "SSID Length     : 0x%04x\n", 
                           aps[num_aps].ssid_len );
                DBG_TRACE( DbgInfo, "BSSID           : %s\n",
                           DbgHwAddr( aps[num_aps].bssid ));

                if( aps[num_aps].ssid_len != 0 )
                {
                    DBG_TRACE( DbgInfo, "SSID            : %s.\n", 
                               aps[num_aps].ssid_val );
                }
                else
                {
                    DBG_TRACE( DbgInfo, "SSID            : %s.\n", "ANY" );
                }

                DBG_TRACE( DbgInfo, "\n" );

                /* Copy the info to the ScanResult structure in the private
                   adapter struct */
                memcpy( &( lp->scan_results.APTable[num_aps]), &( aps[num_aps] ),
                        sizeof( SCAN_RS_STRCT ));
            }

            /* Set scan result to true so that any scan requests will
               complete */
            lp->scan_results.scan_complete = TRUE;
        }

        break;


    case CFG_ACS_SCAN:
        DBG_TRACE( DbgInfo, "CFG_ACS_SCAN\n" );

        {
            PROBE_RESP  *probe_rsp = (PROBE_RESP *)ltv;
            hcf_8       *wpa_ie = NULL;
            hcf_16      wpa_ie_len = 0;

            DBG_TRACE( DbgInfo, "(%s) =========================\n", 
                       lp->dev->name );

            DBG_TRACE( DbgInfo, "(%s) length      : 0x%04x.\n", 
                       lp->dev->name, probe_rsp->length );

            if( probe_rsp->length > 1 )
            {
                DBG_TRACE( DbgInfo, "(%s) infoType    : 0x%04x.\n", 
                           lp->dev->name, probe_rsp->infoType );

                DBG_TRACE( DbgInfo, "(%s) signal      : 0x%02x.\n", 
                           lp->dev->name, probe_rsp->signal );

                DBG_TRACE( DbgInfo, "(%s) silence     : 0x%02x.\n", 
                           lp->dev->name, probe_rsp->silence );

                DBG_TRACE( DbgInfo, "(%s) rxFlow      : 0x%02x.\n", 
                           lp->dev->name, probe_rsp->rxFlow );

                DBG_TRACE( DbgInfo, "(%s) rate        : 0x%02x.\n", 
                           lp->dev->name, probe_rsp->rate );

                DBG_TRACE( DbgInfo, "(%s) frame cntl  : 0x%04x.\n", 
                           lp->dev->name, probe_rsp->frameControl );

                DBG_TRACE( DbgInfo, "(%s) durID       : 0x%04x.\n", 
                           lp->dev->name, probe_rsp->durID );

                DBG_TRACE( DbgInfo, "(%s) address1    : %s\n",
                           lp->dev->name, DbgHwAddr( probe_rsp->address1 ));

                DBG_TRACE( DbgInfo, "(%s) address2    : %s\n",
                           lp->dev->name, DbgHwAddr( probe_rsp->address2 ));
                    
                DBG_TRACE( DbgInfo, "(%s) BSSID       : %s\n",
                           lp->dev->name, DbgHwAddr( probe_rsp->BSSID ));

                DBG_TRACE( DbgInfo, "(%s) sequence    : 0x%04x.\n", 
                           lp->dev->name, probe_rsp->sequence );
                
                DBG_TRACE( DbgInfo, "(%s) address4    : %s\n",
                           lp->dev->name, DbgHwAddr( probe_rsp->address4 ));
                
                DBG_TRACE( DbgInfo, "(%s) datalength  : 0x%04x.\n", 
                           lp->dev->name, probe_rsp->dataLength );

                DBG_TRACE( DbgInfo, "(%s) DA          : %s\n",
                           lp->dev->name, DbgHwAddr( probe_rsp->DA ));

                DBG_TRACE( DbgInfo, "(%s) SA          : %s\n",
                           lp->dev->name, DbgHwAddr( probe_rsp->SA ));

                DBG_TRACE( DbgInfo, "(%s) lenType     : 0x%04x.\n", 
                           lp->dev->name, probe_rsp->lenType );

                DBG_TRACE( DbgInfo, "(%s) timeStamp   : %s\n",
                           lp->dev->name, DbgHwAddr( probe_rsp->timeStamp ));

                DBG_TRACE( DbgInfo, "(%s) beaconInt   : 0x%04x.\n", 
                           lp->dev->name, probe_rsp->beaconInterval );

                DBG_TRACE( DbgInfo, "(%s) capability  : 0x%04x.\n", 
                           lp->dev->name, probe_rsp->capability );

                DBG_TRACE( DbgInfo, "(%s) SSID len    : 0x%04x.\n", 
                           lp->dev->name, probe_rsp->rawData[1] );

                if( probe_rsp->rawData[1] > 0 )
                {
                    char ssid[HCF_MAX_NAME_LEN];

                    memset( ssid, 0, sizeof( ssid ));
                    strncpy( ssid, &probe_rsp->rawData[2],
                             probe_rsp->rawData[1] );

                    DBG_TRACE( DbgInfo, "(%s) SSID        : %s\n",
                               lp->dev->name, ssid );
                }

                /* Parse out the WPA-IE, if one exists */
                wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
                if( wpa_ie != NULL )
                {
                    DBG_TRACE( DbgInfo, "(%s) WPA-IE      : %s\n", 
                    lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
                }

                DBG_TRACE( DbgInfo, "(%s) flags       : 0x%04x.\n", 
                           lp->dev->name, probe_rsp->flags );
            }

            DBG_TRACE( DbgInfo, "\n\n" );


            /* If probe response length is 1, then the scan is complete */
            if( probe_rsp->length == 1 )
            {
                DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
                lp->probe_results.num_aps = lp->probe_num_aps;
                lp->probe_results.scan_complete = TRUE;

                /* Reset the counter for the next scan request */
                lp->probe_num_aps = 0;

                /* Send a wireless extensions event that the scan completed */
                wl_wext_event_scan_complete( lp->dev );
            }
            else
            {
                /* Only copy to the table if the entry is unique; APs sometimes
                   respond more than once to a probe */
                if( lp->probe_num_aps == 0 )
                {
                    /* Copy the info to the ScanResult structure in the private
                    adapter struct */
                    memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
                            probe_rsp, sizeof( PROBE_RESP ));

                    /* Increment the number of APs detected */
                    lp->probe_num_aps++;
                }
                else
                {
                    int count;
                    int unique = 1;

                    for( count = 0; count < lp->probe_num_aps; count++ )
                    {
                        if( memcmp( &( probe_rsp->BSSID ),
                            lp->probe_results.ProbeTable[count].BSSID, 
                            ETH_ALEN ) == 0 )
                        {
                            unique = 0;
                        }
                    }

                    if( unique )
                    {
                        /* Copy the info to the ScanResult structure in the
                        private adapter struct. Only copy if there's room in the
                        table */
                        if( lp->probe_num_aps < MAX_NAPS )
                        {
                            memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
                                    probe_rsp, sizeof( PROBE_RESP ));
                        }
                        else
                        {
                            DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
                        }

                        /* Increment the number of APs detected. Note I do this
                           here even when I don't copy the probe response to the
                           buffer in order to detect the overflow condition */
                        lp->probe_num_aps++;
                    }
                }
            }
        }

        break;

    case CFG_LINK_STAT:
        DBG_TRACE( DbgInfo, "CFG_LINK_STAT\n" );

        {
            LINK_STATUS_STRCT *ls = (LINK_STATUS_STRCT *)ltv;

            switch( ls->linkStatus )
            {
            case 1:
                DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
                wl_wext_event_ap( lp->dev );
                break;

            case 2:
                DBG_TRACE( DbgInfo, "Link Status : Disconnected\n"  );
                break;

            case 3:
                DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
                break;

            case 4:
                DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
                break;

            case 5:
                DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
                break;

            default:
                DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n",
                           ls->linkStatus );
                break;
            }
        }

        break;

    case CFG_ASSOC_STAT:
        DBG_TRACE( DbgInfo, "CFG_ASSOC_STAT\n" );

        {
            ASSOC_STATUS_STRCT *as = (ASSOC_STATUS_STRCT *)ltv;

            switch( as->assocStatus )
            {
            case 1:
                DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
                break;

            case 2:
                DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
                break;

            case 3:
                DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
                break;

            default:
                DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n", 
                           as->assocStatus );
                break;
            }

            DBG_TRACE( DbgInfo, "STA Address        : %s\n",
                       DbgHwAddr( as->staAddr ));

            if(( as->assocStatus == 2 )  && ( as->len == 8 ))
            {
                DBG_TRACE( DbgInfo, "Old AP Address     : %s\n",
                           DbgHwAddr( as->oldApAddr ));
            }
        }

        break;

    case CFG_SECURITY_STAT:
        DBG_TRACE( DbgInfo, "CFG_SECURITY_STAT\n" );

        {
            SECURITY_STATUS_STRCT *ss = (SECURITY_STATUS_STRCT *)ltv;

            switch( ss->securityStatus )
            {
            case 1:
                DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
                break;

            case 2:
                DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
                break;

            case 3:
                DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
                break;

            case 4:
                DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
                break;

            case 5:
                DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
                break;

            default:
                DBG_TRACE( DbgInfo, "Security Status : UNKNOWN %d\n",
                           ss->securityStatus );
                break;
            }

            DBG_TRACE( DbgInfo, "STA Address     : %s\n", DbgHwAddr( ss->staAddr ));

            DBG_TRACE( DbgInfo, "Reason          : 0x%04x \n", ss->reason );
        }

        break;

    case CFG_WMP:
        DBG_TRACE( DbgInfo, "CFG_WMP, size is %d bytes\n", ltv->len );
        {
            WMP_RSP_STRCT *wmp_rsp = (WMP_RSP_STRCT *)ltv;

            DBG_TRACE( DbgInfo, "CFG_WMP, pdu type is 0x%x\n", 
                       wmp_rsp->wmpRsp.wmpHdr.type );

            switch( wmp_rsp->wmpRsp.wmpHdr.type )
            {
            case WVLAN_WMP_PDU_TYPE_LT_RSP:
                {
                    LINKTEST_RSP_STRCT  *lt_rsp = (LINKTEST_RSP_STRCT *)ltv;


                    DBG_TRACE( DbgInfo, "LINK TEST RESULT\n" );
                    DBG_TRACE( DbgInfo, "================\n" );
                    DBG_TRACE( DbgInfo, "Length        : %d.\n",     lt_rsp->len );

                    DBG_TRACE( DbgInfo, "Name          : %s.\n",     lt_rsp->ltRsp.ltRsp.name );
                    DBG_TRACE( DbgInfo, "Signal Level  : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.signal );
                    DBG_TRACE( DbgInfo, "Noise  Level  : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.noise );
                    DBG_TRACE( DbgInfo, "Receive Flow  : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.rxFlow );
                    DBG_TRACE( DbgInfo, "Data Rate     : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.dataRate );
                    DBG_TRACE( DbgInfo, "Protocol      : 0x%04x.\n", lt_rsp->ltRsp.ltRsp.protocol );
                    DBG_TRACE( DbgInfo, "Station       : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.station );
                    DBG_TRACE( DbgInfo, "Data Rate Cap : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.dataRateCap );

                    DBG_TRACE( DbgInfo, "Power Mgmt    : 0x%02x 0x%02x 0x%02x 0x%02x.\n", 
                                lt_rsp->ltRsp.ltRsp.powerMgmt[0], 
                                lt_rsp->ltRsp.ltRsp.powerMgmt[1], 
                                lt_rsp->ltRsp.ltRsp.powerMgmt[2], 
                                lt_rsp->ltRsp.ltRsp.powerMgmt[3] );

                    DBG_TRACE( DbgInfo, "Robustness    : 0x%02x 0x%02x 0x%02x 0x%02x.\n",
                                lt_rsp->ltRsp.ltRsp.robustness[0], 
                                lt_rsp->ltRsp.ltRsp.robustness[1], 
                                lt_rsp->ltRsp.ltRsp.robustness[2], 
                                lt_rsp->ltRsp.ltRsp.robustness[3] );

                    DBG_TRACE( DbgInfo, "Scaling       : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.scaling );
                }   

                break;

            default:
                break;
            }
        }

        break;

    case CFG_NULL:
        DBG_TRACE( DbgInfo, "CFG_NULL\n" );
        break;

    default:
        DBG_TRACE( DbgInfo, "CFG_TALLIES\n" );
        break;
    }


    DBG_LEAVE( DbgInfo );
    return;
}
/*============================================================================*/
#endif  /* ifndef USE_MBOX_SYNC */



#ifdef USE_WDS
/*******************************************************************************
 *	wl_wds_netdev_register()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      This function registers net_device structures with the system's network
 *      layer for use with the WDS ports.
 *      
 *
 *  PARAMETERS:
 *
 *      lp      - pointer to the device's private adapter structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void wl_wds_netdev_register( struct wl_private *lp )
{
    int count;
    /*------------------------------------------------------------------------*/


    DBG_FUNC( "wl_wds_netdev_register" );
    DBG_ENTER( DbgInfo );


    if( lp->DownloadFirmware == WVLAN_DRV_MODE_AP )
    {
        for( count = 0; count < NUM_WDS_PORTS; count++ )
        {
            if( WVLAN_VALID_MAC_ADDRESS( lp->wds_port[count].wdsAddress ))
            {
                if( register_netdev( lp->wds_port[count].dev ) != 0 )
                {
                    DBG_WARNING( DbgInfo, "net device for WDS port %d could not be registered\n",
                                ( count + 1 ));
                }

                lp->wds_port[count].is_registered = TRUE;

                /* Fill out the net_device structs with the MAC addr */
                memcpy( lp->wds_port[count].dev->dev_addr, lp->MACAddress, 
                        ETH_ALEN );
                lp->wds_port[count].dev->addr_len = ETH_ALEN;
            }
        }
    }

    DBG_LEAVE( DbgInfo );
    return;
}
/*============================================================================*/




/*******************************************************************************
 *	wl_wds_netdev_deregister()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      This function deregisters the WDS net_device structures used by the 
 *      system's network layer.
 *      
 *
 *  PARAMETERS:
 *
 *      lp      - pointer to the device's private adapter structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void wl_wds_netdev_deregister( struct wl_private *lp )
{
    int count;
    /*------------------------------------------------------------------------*/

    
    DBG_FUNC( "wl_wds_netdev_deregister" );
    DBG_ENTER( DbgInfo );


    if( lp->DownloadFirmware == WVLAN_DRV_MODE_AP )
    {
        for( count = 0; count < NUM_WDS_PORTS; count++ )
        {
            if( WVLAN_VALID_MAC_ADDRESS( lp->wds_port[count].wdsAddress ))
            {
                unregister_netdev( lp->wds_port[count].dev );
            }

            lp->wds_port[count].is_registered = FALSE;
        }
    }

    DBG_LEAVE( DbgInfo );
    return;
}
/*============================================================================*/
#endif  /* USE_WDS */

