/*******************************************************************************
 * 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: nico $
 * $Date: 2004/08/06 11:25:37 $
 * $Revision: 1.14 $
 * $Source: /usr/local/cvs/wl_lkm/wireless/wl_main.c,v $
 *
 ******************************************************************************/

/*******************************************************************************
 *  constant definitions
 ******************************************************************************/

/* Allow support for calling system fcns to access F/W iamge file */
#define __KERNEL_SYSCALLS__

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

#include <linux/module.h>
#include <linux/proc_fs.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/unistd.h>
#include <asm/uaccess.h>

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

#define BIN_DL 1
#if BIN_DL
#include <linux/vmalloc.h>
#endif // BIN_DL


#include <hcf/debug.h>

#include <hcf.h>
#include <dhf.h>
//in order to get around:: wl_main.c:2229: `HREG_EV_RDMAD' undeclared (first use in this function)
#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 );

#if 1 //SCULL_USE_PROC /* don't waste space if unused */
//int scull_read_procmem(char *buf, char **start, off_t offset, int len, int unused);
int scull_read_procmem(char *buf, char **start, off_t offset, int len, int *eof, void *data );
static int write_int(struct file *file, const char *buffer, unsigned long count, void *data);
static void proc_write(const char *name, write_proc_t *w, void *data);
	
#endif /* SCULL_USE_PROC */

/*******************************************************************************
 * 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>]");

static p_u8     PARM_AUTHENTICATION        	= PARM_DEFAULT_AUTHENTICATION;
static p_u16    PARM_AUTH_KEY_MGMT_SUITE   	= PARM_DEFAULT_AUTH_KEY_MGMT_SUITE;
static p_u16    PARM_BRSC_2GHZ             	= PARM_DEFAULT_BRSC_2GHZ;
static p_u16    PARM_BRSC_5GHZ             	= PARM_DEFAULT_BRSC_5GHZ;
static p_u16    PARM_COEXISTENCE           	= PARM_DEFAULT_COEXISTENCE;
static p_u16    PARM_CONNECTION_CONTROL    	= PARM_DEFAULT_CONNECTION_CONTROL;  //;?rename and move
static p_char  *PARM_CREATE_IBSS           	= PARM_DEFAULT_CREATE_IBSS_STR;
static p_char  *PARM_DESIRED_SSID          	= PARM_DEFAULT_SSID;
static p_char  *PARM_DOWNLOAD_FIRMWARE      = "";
static p_u16    PARM_ENABLE_ENCRYPTION     	= PARM_DEFAULT_ENABLE_ENCRYPTION;
static p_char  *PARM_EXCLUDE_UNENCRYPTED   	= PARM_DEFAULT_EXCLUDE_UNENCRYPTED_STR;
static p_char  *PARM_INTRA_BSS_RELAY       	= PARM_DEFAULT_INTRA_BSS_RELAY_STR;
static p_char  *PARM_KEY1                  	= "";
static p_char  *PARM_KEY2                  	= "";
static p_char  *PARM_KEY3                  	= "";
static p_char  *PARM_KEY4                  	= "";
static p_char  *PARM_LOAD_BALANCING        	= PARM_DEFAULT_LOAD_BALANCING_STR;
static p_u16    PARM_MAX_SLEEP             	= PARM_DEFAULT_MAX_PM_SLEEP;
static p_char  *PARM_MEDIUM_DISTRIBUTION   	= PARM_DEFAULT_MEDIUM_DISTRIBUTION_STR;
static p_char  *PARM_MICROWAVE_ROBUSTNESS  	= PARM_DEFAULT_MICROWAVE_ROBUSTNESS_STR;
static p_char  *PARM_MULTICAST_PM_BUFFERING	= PARM_DEFAULT_MULTICAST_PM_BUFFERING_STR;
static p_u16    PARM_MULTICAST_RATE        	= PARM_DEFAULT_MULTICAST_RATE_2GHZ;
static p_char  *PARM_MULTICAST_RX          	= PARM_DEFAULT_MULTICAST_RX_STR;
static p_u8     PARM_NETWORK_ADDR[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
static p_u16    PARM_OWN_ATIM_WINDOW       	= PARM_DEFAULT_OWN_ATIM_WINDOW;
static p_u16    PARM_OWN_BEACON_INTERVAL   	= PARM_DEFAULT_OWN_BEACON_INTERVAL;
static p_u8     PARM_OWN_CHANNEL           	= PARM_DEFAULT_OWN_CHANNEL;
static p_u8     PARM_OWN_DTIM_PERIOD       	= PARM_DEFAULT_OWN_DTIM_PERIOD;
static p_char  *PARM_OWN_NAME              	= PARM_DEFAULT_OWN_NAME;
static p_char  *PARM_OWN_SSID              	= PARM_DEFAULT_SSID;
static p_u16	PARM_PM_ENABLED            	= WVLAN_PM_STATE_DISABLED;
static p_u16    PARM_PM_HOLDOVER_DURATION  	= PARM_DEFAULT_PM_HOLDOVER_DURATION;
static p_u8     PARM_PORT_TYPE             	= PARM_DEFAULT_PORT_TYPE;
static p_char  *PARM_PROMISCUOUS_MODE      	= PARM_DEFAULT_PROMISCUOUS_MODE_STR;
static p_char  *PARM_REJECT_ANY            	= PARM_DEFAULT_REJECT_ANY_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_u16    PARM_RTS_THRESHOLD         	= PARM_DEFAULT_RTS_THRESHOLD;
static p_u16    PARM_SRSC_2GHZ             	= PARM_DEFAULT_SRSC_2GHZ;
static p_u16    PARM_SRSC_5GHZ             	= PARM_DEFAULT_SRSC_5GHZ;
static p_u8     PARM_SYSTEM_SCALE          	= PARM_DEFAULT_SYSTEM_SCALE;
static p_u8     PARM_TX_KEY                	= PARM_DEFAULT_TX_KEY;
static p_u16    PARM_TX_POW_LEVEL          	= PARM_DEFAULT_TX_POW_LEVEL;
static p_u16    PARM_TX_RATE1              	= PARM_DEFAULT_TX_RATE_2GHZ;
static p_u16    PARM_TX_RATE2              	= PARM_DEFAULT_TX_RATE_2GHZ;
static p_u16    PARM_TX_RATE3              	= PARM_DEFAULT_TX_RATE_2GHZ;
static p_u16    PARM_TX_RATE4              	= PARM_DEFAULT_TX_RATE_2GHZ;
static p_u16    PARM_TX_RATE5              	= PARM_DEFAULT_TX_RATE_2GHZ;
static p_u16    PARM_TX_RATE6              	= PARM_DEFAULT_TX_RATE_2GHZ;
static p_u16    PARM_TX_RATE               	= PARM_DEFAULT_TX_RATE_2GHZ;
static p_u8     PARM_WDS_ADDRESS1[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
static p_u8     PARM_WDS_ADDRESS2[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
static p_u8     PARM_WDS_ADDRESS3[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
static p_u8     PARM_WDS_ADDRESS4[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
static p_u8     PARM_WDS_ADDRESS5[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
static p_u8     PARM_WDS_ADDRESS6[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;


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_OWN_CHANNEL,           "b");
MODULE_PARM_DESC(PARM_OWN_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");
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");
MODULE_PARM(PARM_DOWNLOAD_FIRMWARE,     "s");
MODULE_PARM_DESC(PARM_DOWNLOAD_FIRMWARE,        "filename of firmware image");

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

MODULE_PARM(PARM_LOAD_BALANCING,        "s");
MODULE_PARM_DESC(PARM_LOAD_BALANCING,           "Load Balancing Enabled (<string> N or Y) [Y]");
MODULE_PARM(PARM_MEDIUM_DISTRIBUTION,   "s");
MODULE_PARM_DESC(PARM_MEDIUM_DISTRIBUTION,      "Medium Distribution Enabled (<string> N or Y) [Y]");
MODULE_PARM(PARM_TX_POW_LEVEL,          "b");
MODULE_PARM_DESC(PARM_TX_POW_LEVEL,             "Transmit Power (0 - 6) [3]");
MODULE_PARM(PARM_SRSC_2GHZ,             "b");
MODULE_PARM_DESC(PARM_SRSC_2GHZ,                "Supported Rate Set Control 2.4 GHz");
MODULE_PARM(PARM_SRSC_5GHZ,             "b");
MODULE_PARM_DESC(PARM_SRSC_5GHZ,                "Supported Rate Set Control 5.0 GHz");
MODULE_PARM(PARM_BRSC_2GHZ,             "b");
MODULE_PARM_DESC(PARM_BRSC_2GHZ,                "Basic Rate Set Control 2.4 GHz");
MODULE_PARM(PARM_BRSC_5GHZ,             "b");
MODULE_PARM_DESC(PARM_BRSC_5GHZ,                "Basic Rate Set Control 5.0 GHz");
#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
//;?seems reasonable that even an AP-only driver could afford this small additional footprint
MODULE_PARM(PARM_PM_ENABLED,            "h");
MODULE_PARM_DESC(PARM_PM_ENABLED,               "Power Management State (0 - 2, 8001 - 8002) [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_MULTICAST_RX,          "s");
//;?MODULE_PARM_DESC(PARM_MULTICAST_RX,             "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_NETWORK_ADDR,          "6b");
//;?MODULE_PARM_DESC(PARM_NETWORK_ADDR,             "Hardware Ethernet Address ([0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff],[0x00-0xff]) [<factory value>]");
//;?MODULE_PARM(PARM_AUTHENTICATION,        "b");
//
//tracker 12448
//;?MODULE_PARM_DESC(PARM_AUTHENTICATION,           "Authentication Type (0-2) [0] 0=Open 1=SharedKey 2=LEAP");
//;?MODULE_PARM_DESC(authentication,         "Authentication Type (1-2) [1] 1=Open 2=SharedKey");
//tracker 12448
//
//;?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]" );
//;?
MODULE_PARM(PARM_CONNECTION_CONTROL,    "b");
MODULE_PARM_DESC(PARM_CONNECTION_CONTROL,       "Connection Control (0 - 3) [2]");
#endif /* HCF_STA */
#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
					//;?should we restore this to allow smaller memory footprint
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}]");

MODULE_PARM(PARM_OWN_BEACON_INTERVAL,   "b");
MODULE_PARM_DESC(PARM_OWN_BEACON_INTERVAL,      "Own Beacon Interval (20 - 200) [100]");
MODULE_PARM(PARM_COEXISTENCE,   "b");
MODULE_PARM_DESC(PARM_COEXISTENCE,      "Coexistence (0-7) [0]");

#endif /* HCF_AP */

/* END NEW PARAMETERS */
/*******************************************************************************
 * debugging specifics
 ******************************************************************************/
#if DBG

static p_u32    pc_debug = DBG_LVL;
MODULE_PARM(pc_debug, "i");
/*static ;?conflicts with my understanding of CL parameters and breaks now I moved 
 * the correspondig logic to wl_profile
 */ p_u32    DebugFlag = ~0; //recognizable "undefined value" rather then DBG_DEFAULTS;
MODULE_PARM(DebugFlag, "l");

dbg_info_t   wl_info = { DBG_MOD_NAME, 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 0 //;? (HCF_TYPE) & HCF_TYPE_AP
extern memimage ap;                 // AP firmware image to be downloaded
#endif /* HCF_AP */

#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
//extern memimage station;            // STA firmware image to be downloaded
extern memimage fw_image;            // 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 );
		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_OWN_CHANNEL, "%d", PARM_OWN_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, "\"%s\"", PARM_DOWNLOAD_FIRMWARE );
		DBG_PARAM( DbgInfo, PARM_NAME_AUTH_KEY_MGMT_SUITE, "%d", PARM_AUTH_KEY_MGMT_SUITE );
//;?#if (HCF_TYPE) & HCF_TYPE_STA
					//;?should we make this code conditional depending on in STA mode
//;?        DBG_PARAM( DbgInfo, PARM_NAME_PORT_TYPE, "%d", PARM_PORT_TYPE );
		DBG_PARAM( DbgInfo, PARM_NAME_PM_ENABLED, "%04x", PARM_PM_ENABLED );
//;?        DBG_PARAM( DbgInfo, PARM_NAME_CREATE_IBSS, "\"%s\"", PARM_CREATE_IBSS );
//;?        DBG_PARAM( DbgInfo, PARM_NAME_MULTICAST_RX, "\"%s\"", PARM_MULTICAST_RX );
//;?        DBG_PARAM( DbgInfo, PARM_NAME_MAX_SLEEP, "%d", PARM_MAX_SLEEP );
//;?        DBG_PARAM( DbgInfo, PARM_NAME_NETWORK_ADDR, "\"%s\"", DbgHwAddr( PARM_NETWORK_ADDR ));
//;?        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 1 //;? (HCF_TYPE) & HCF_TYPE_AP
		//;?should we restore this to allow smaller memory footprint
		//;?I guess: no, since this is Debug mode only
		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_NAME_WDS_ADDRESS1, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS1 ));
		DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS2, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS2 ));
		DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS3, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS3 ));
		DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS4, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS4 ));
		DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS5, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS5 ));
		DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS6, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS6 ));
#endif /* HCF_AP */

		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_OWN_CHANNEL <= PARM_MAX_OWN_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 ));
		
		VALID_PARAM(( PARM_MULTICAST_RATE >= PARM_MIN_MULTICAST_RATE ) && 
						( PARM_MULTICAST_RATE <= PARM_MAX_MULTICAST_RATE ));

		VALID_PARAM( !PARM_DOWNLOAD_FIRMWARE || ( strlen( PARM_DOWNLOAD_FIRMWARE ) <= 255 /*;?*/ ));
		VALID_PARAM(( PARM_AUTH_KEY_MGMT_SUITE < PARM_MAX_AUTH_KEY_MGMT_SUITE ));

		VALID_PARAM( !PARM_LOAD_BALANCING || strchr( "NnYy", PARM_LOAD_BALANCING[0] ) != NULL );
		VALID_PARAM( !PARM_MEDIUM_DISTRIBUTION || strchr( "NnYy", PARM_MEDIUM_DISTRIBUTION[0] ) != NULL );
		VALID_PARAM(( PARM_TX_POW_LEVEL <= PARM_MAX_TX_POW_LEVEL ));

 		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 ||
					 ( PARM_PM_ENABLED & 0x7FFF ) <= WVLAN_PM_STATE_STANDARD );
 		VALID_PARAM( !PARM_CREATE_IBSS || strchr( "NnYy", PARM_CREATE_IBSS[0] ) != NULL );
 		VALID_PARAM( !PARM_MULTICAST_RX || strchr( "NnYy", PARM_MULTICAST_RX[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 );
		VALID_PARAM(( PARM_CONNECTION_CONTROL <= PARM_MAX_CONNECTION_CONTROL ));

		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 ));

		VALID_PARAM(( PARM_OWN_BEACON_INTERVAL >= PARM_MIN_OWN_BEACON_INTERVAL ) && ( PARM_OWN_BEACON_INTERVAL <= PARM_MAX_OWN_BEACON_INTERVAL ));
		VALID_PARAM(( PARM_COEXISTENCE <= PARM_COEXISTENCE ));

		/* 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_OWN_CHANNEL;
		lp->DistanceBetweenAPs  = PARM_SYSTEM_SCALE;

		/* Need to determine how to handle the new bands for 5GHz */
		lp->TxRateControl[0]    = PARM_DEFAULT_TX_RATE_2GHZ;
		lp->TxRateControl[1]    = PARM_DEFAULT_TX_RATE_5GHZ;

		lp->RTSThreshold        = PARM_RTS_THRESHOLD;

		/* Need to determine how to handle the new bands for 5GHz */
		lp->MulticastRate[0]    = PARM_DEFAULT_MULTICAST_RATE_2GHZ;
		lp->MulticastRate[1]    = PARM_DEFAULT_MULTICAST_RATE_5GHZ;

		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 = 1 ; //;?to be upgraded PARM_DOWNLOAD_FIRMWARE;
		lp->AuthKeyMgmtSuite = PARM_AUTH_KEY_MGMT_SUITE;

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

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

		lp->txPowLevel = PARM_TX_POW_LEVEL;

		lp->srsc[0] = PARM_SRSC_2GHZ;
		lp->srsc[1] = PARM_SRSC_5GHZ;
		lp->brsc[0] = PARM_BRSC_2GHZ;
		lp->brsc[1] = PARM_BRSC_5GHZ;
#if 1 //;? (HCF_TYPE) & HCF_TYPE_STA
//;?seems reasonable that even an AP-only driver could afford this small additional footprint
		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_MULTICAST_RX[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_NETWORK_ADDR[i];
		}

		lp->connectionControl = PARM_CONNECTION_CONTROL;

#endif /* HCF_STA */
#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
		//;?should we restore this to allow smaller memory footprint
		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;
		}

		lp->ownBeaconInterval = PARM_OWN_BEACON_INTERVAL;
		lp->coexistence       = PARM_COEXISTENCE;

#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/connectState variables */
		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;
		/* Initialize the use_dma element in the adapter structure. Not sure if
		   this should be a compile-time or run-time configurable. So for now,
		   implement as run-time and just define here */
#ifdef WARP 
#ifdef ENABLE_DMA
		DBG_TRACE( DbgInfo, "HERMES 2.5 BUSMASTER DMA MODE\n" );
		lp->use_dma = 1;
#else
		DBG_TRACE( DbgInfo, "HERMES 2.5 PORT I/O MODE\n" );
		lp->use_dma = 0;
#endif // ENABLE_DA
#endif // WARP

		/* 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 );
		//HCF_ERR_INCOMP_FW is acceptable, because download must still take place
		//HCF_ERR_INCOMP_PRI is not acceptable
		if ( hcf_status != HCF_SUCCESS && hcf_status != HCF_ERR_INCOMP_FW ) {
			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 );	//;?should be limited to 8 chars

		lp->driverInfo.driver_version   = ( DRV_MAJOR_VERSION << 8 ) | DRV_MINOR_VERSION;
		//;?should set HCF_version and how about driver_stat
		lp->driverInfo.IO_address       = dev->base_addr;
		lp->driverInfo.IO_range         = HCF_NUM_IO_PORTS;	//;?conditionally 0x40 or 0x80 seems better
		lp->driverInfo.IRQ_number       = dev->irq;
		lp->driverInfo.card_stat        = lp->hcfCtx.IFB_CardStat;
		//;? what happened to frame_type
		
		/* 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;
		}

		/* Certain RIDs must be set before enabling the ports */
		wl_put_ltv_init( lp );

#if 0 //;?why was this already commented out in wl_lkm_720
		/* Enable the ports */
		if ( wl_adapter_is_open( lp->dev )) {
			/* Enable the ports */
			DBG_TRACE( DbgInfo, "Enabling Port 0\n" );
			hcf_status = wl_enable( lp );

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

#if (HCF_TYPE) & HCF_TYPE_AP
			DBG_TRACE( DbgInfo, "Enabling WDS Ports\n" );
			//wl_enable_wds_ports( lp );
#endif  /* (HCF_TYPE) & HCF_TYPE_AP */

		}
#endif
		
		/* 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 = WVLAN_DRV_MODE_STA; //;?download_firmware;

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

			wl_disable( lp );
			hcf_action( &lp->hcfCtx, HCF_ACT_INT_OFF );
			hcf_connect( &lp->hcfCtx, HCF_DISCONNECT );
		}
#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' ));
	}
   
#if 1 //SCULL_USE_PROC /* don't waste space if unused */
	create_proc_read_entry( "wlags", 0, NULL, scull_read_procmem, dev );
    proc_mkdir("driver/wlags49", 0);
	proc_write("driver/wlags49/wlags49_type", write_int, &lp->wlags49_type);
#endif /* SCULL_USE_PROC */
	
	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_insert
/*============================================================================*/


/*******************************************************************************
 *	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                 hcf_status = 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_connect( &lp->hcfCtx, HCF_DISCONNECT );

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

			/* Reset PortStatus */  
			lp->portState = WVLAN_PORT_STATE_DISABLED;

			/* 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 hcf_status;
} // wl_reset
/*============================================================================*/


/*******************************************************************************
 *	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  			hcf_status = HCF_SUCCESS;
char			*cp = NULL;					//fw_image
	/*------------------------------------------------------------------------*/
	DBG_FUNC( "wl_go" );
	DBG_ENTER( DbgInfo );
	if ( lp == NULL ) {
		DBG_ERROR( DbgInfo, "private adapter struct invalid\n" );
		DBG_LEAVE( DbgInfo );
		return -1;
	}
	/* Disconnect and disable if necessary */
	hcf_status = wl_disconnect( lp );
	if ( hcf_status != HCF_SUCCESS ) {
		DBG_ERROR( DbgInfo, "Disconnect failed\n" );
		DBG_LEAVE( DbgInfo );
		return -1;
	}
	hcf_status = wl_disable( lp );
	if ( hcf_status != HCF_SUCCESS ) {
		DBG_TRACE( DbgInfo, "Disable port 0 failed: 0x%x\n", hcf_status );
	}
#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
	DBG_TRACE( DbgInfo, "Disabling WDS Ports\n" );
	//wl_disable_wds_ports( lp );
#endif  /* (HCF_TYPE) & HCF_TYPE_AP */

//;?what was the purpose of this
// 	/* 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 )); 

#if BIN_DL
	if ( strlen( lp->fw_image_filename ) ) {
mm_segment_t	fs;
int		    	file_desc;
int 			rc;

		DBG_TRACE( DbgInfo, "F/W image:%s:\n", lp->fw_image_filename );
		/* Obtain a user-space process context, storing the original context */
		fs = get_fs( );
		set_fs( get_ds( ));
		file_desc = open( lp->fw_image_filename, O_RDONLY, 0 );
		if ( file_desc == -1 ) {
			DBG_ERROR( DbgInfo, "No image file found\n" );
		} else {
			DBG_TRACE( DbgInfo, "F/W image file found\n" );
#define DHF_ALLOC_SIZE 96000			//just below 96K, let's hope it suffices for now and for the future
			cp = (char*)vmalloc( DHF_ALLOC_SIZE );
			if ( cp == NULL ) {
				DBG_ERROR( DbgInfo, "error in vmalloc\n" );
			} else {
				rc = read( file_desc, cp, DHF_ALLOC_SIZE );
				if ( rc == DHF_ALLOC_SIZE ) {
					DBG_ERROR( DbgInfo, "buffer too small, %d\n", DHF_ALLOC_SIZE );
				} else if ( rc > 0 ) {
					DBG_TRACE( DbgInfo, "read O.K.: %d bytes  %.12s\n", rc, cp );
					rc = read( file_desc, &cp[rc], 1 );
					if ( rc == 0 ) { //;/change to an until-loop at rc<=0
						DBG_TRACE( DbgInfo, "no more to read\n" );
					}
				}
				if ( rc != 0 ) {
					DBG_ERROR( DbgInfo, "file not read in one swoop or other error"\
										", give up, too complicated, rc = %0X\n", rc );
					DBG_ERROR( DbgInfo, "still have to change code to get a real download now !!!!!!!!\n" );
				} else {
					DBG_TRACE( DbgInfo, "before dhf_download_binary\n" );
					hcf_status = dhf_download_binary( (memimage *)cp );
					DBG_TRACE( DbgInfo, "after dhf_download_binary, before dhf_download_fw\n" );
					//;?improve error flow/handling
					hcf_status = dhf_download_fw( &lp->hcfCtx, (memimage *)cp );
					DBG_TRACE( DbgInfo, "after dhf_download_fw\n" );
				}
				vfree( cp );
			}
			close( file_desc );
		}
		set_fs( fs );			/* Return to the original context */
	}
#endif // BIN_DL
	if ( cp == NULL ) {
		DBG_TRACE( DbgInfo, "Downloading STA firmware...\n" );
//		hcf_status = dhf_download_fw( &lp->hcfCtx, &station );
		hcf_status = dhf_download_fw( &lp->hcfCtx, &fw_image );
	}
	if ( hcf_status != HCF_SUCCESS ) {
		DBG_ERROR( DbgInfo, "Firmware Download failed\n" );
		DBG_LEAVE( DbgInfo );
		return hcf_status;
	}
	/* Report the FW versions */
	//;?obsolete, use the available IFB info:: wl_get_pri_records( lp );
	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA  ) {
		DBG_TRACE( DbgInfo, "downloaded station F/W\n" );
	} else if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
		DBG_TRACE( DbgInfo, "downloaded AP F/W\n" );
	} else {
		DBG_ERROR( DbgInfo, "unknown F/W type\n" );
	}
	DBG_TRACE( DbgInfo, "ComponentID:%04x variant:%04x major:%04x minor:%04x\n",
				CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ), 
				CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.variant ), 
				CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.version_major ), 
				CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.version_minor ));

	/* now we wil get the MAC address of the card */
	lp->ltvRecord.len = 4;
	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
		lp->ltvRecord.typ = CFG_NIC_MAC_ADDR;
	} else
	{
		lp->ltvRecord.typ = CFG_CNF_OWN_MAC_ADDR;
	}
	hcf_status = hcf_get_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
	if ( hcf_status != HCF_SUCCESS ) {
		DBG_ERROR( DbgInfo, "Could not retrieve MAC address\n" );
		DBG_LEAVE( DbgInfo );
		return hcf_status;
	}
	memcpy( lp->MACAddress, &lp->ltvRecord.u.u8[0], ETH_ALEN );
	DBG_TRACE( DbgInfo, "Card MAC Address: %s\n", DbgHwAddr( lp->MACAddress ));

	/* Write out configuration to the device, enable, and reconnect. However,
	   only reconnect if in AP mode. For STA mode, need to wait for passive scan
	   completion before a connect can be issued */
	wl_put_ltv( lp );
	/* Enable the ports */
	hcf_status = wl_enable( lp );

	if ( lp->DownloadFirmware == WVLAN_DRV_MODE_AP ) {
#ifdef USE_WDS
		wl_enable_wds_ports( lp );
#endif // USE_WDS
		hcf_status = wl_connect( lp );
	}
	DBG_LEAVE( DbgInfo );
	return hcf_status;
} // wl_go
/*============================================================================*/


/*******************************************************************************
 *	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_set_wep_keys
/*============================================================================*/


/*******************************************************************************
 *	wl_apply()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Write the parameters to the adapter. (re-)enables the card if device is
 *  open. Returns hcf_status 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 hcf_status = HCF_SUCCESS;
	/*------------------------------------------------------------------------*/
	DBG_FUNC( "wl_apply" );
	DBG_ENTER( DbgInfo );
	DBG_ASSERT( lp != NULL);
	DBG_PARAM( DbgInfo, "lp", "%s (0x%p)", lp->dev->name, lp );

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

		if ( wl_adapter_is_open( lp->dev )) {
			/* Disconnect and disable if necessary */
			hcf_status = wl_disconnect( lp );
			if ( hcf_status != HCF_SUCCESS ) {
				DBG_ERROR( DbgInfo, "Disconnect failed\n" );
				DBG_LEAVE( DbgInfo );
				return -1;
			}
			hcf_status = wl_disable( lp );
			if ( hcf_status != HCF_SUCCESS ) {
				return -1;
			} else {
				/* Write out configuration to the device, enable, and reconnect.
				   However, only reconnect if in AP mode. For STA mode, need to
				   wait for passive scan completion before a connect can be
				   issued */
				hcf_status = wl_put_ltv( lp );

				if ( hcf_status == HCF_SUCCESS ) {
					hcf_status = wl_enable( lp );

					if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
						hcf_status = wl_connect( lp );
					}
				} else {
					DBG_WARNING( DbgInfo, "wl_put_ltv() failed\n" );
				}
			}
		}
	}

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


/*******************************************************************************
 *	wl_put_ltv_init()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Used to set basic parameters for card initialization. 
 *
 *  PARAMETERS:
 *
 *      lp  - a pointer to the wireless adapter's private structure
 *
 *  RETURNS:
 *
 *      an HCF status code
 *
 ******************************************************************************/
int wl_put_ltv_init( struct wl_private *lp )
{
	int i;
	int hcf_status;
	CFG_RID_LOG_STRCT *RidLog;
	/*------------------------------------------------------------------------*/
	DBG_FUNC( "wl_put_ltv_init" );
	DBG_ENTER( DbgInfo );
	if ( lp == NULL ) {
		DBG_ERROR( DbgInfo, "lp pointer is NULL\n" );
		DBG_LEAVE( DbgInfo );
		return -1;
	}
	/* DMA/IO */
	lp->ltvRecord.len = 2;
	lp->ltvRecord.typ = CFG_CNTL_OPT;

	/* The Card Services build must ALWAYS configure for 16-bit I/O. PCI or
	   CardBus can be set to either 16/32 bit I/O, or Bus Master DMA, but only
	   for Hermes-2.5 */
#ifdef BUS_PCMCIA
	lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( USE_16BIT );
#else
	if ( lp->use_dma ) {
		lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( USE_DMA );
	} else {
		lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
	}
	
#endif
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
	DBG_TRACE( DbgInfo, "CFG_CNTL_OPT                      : 0x%04x\n",
			   lp->ltvRecord.u.u16[0] );
	DBG_TRACE( DbgInfo, "CFG_CNTL_OPT result               : 0x%04x\n", 
			   hcf_status );

	/* Register the list of RIDs on which asynchronous notification is
	   required. Note that this mechanism replaces the mailbox, so the mailbox
	   can be queried by the host (if desired) without contention from us */
	i=0;

	lp->RidList[i].len     = sizeof( lp->ProbeResp );
	lp->RidList[i].typ     = CFG_ACS_SCAN;
	lp->RidList[i].bufp    = (wci_recordp)&lp->ProbeResp;
	//lp->ProbeResp.infoType = 0xFFFF;
	i++;

	lp->RidList[i].len     = sizeof( lp->assoc_stat );
	lp->RidList[i].typ     = CFG_ASSOC_STAT;
	lp->RidList[i].bufp    = (wci_recordp)&lp->assoc_stat;
	lp->assoc_stat.len     = 0xFFFF;
	i++;

	lp->RidList[i].len     = 4;
	lp->RidList[i].typ     = CFG_UPDATED_INFO_RECORD;
	lp->RidList[i].bufp    = (wci_recordp)&lp->updatedRecord;
	lp->updatedRecord.len  = 0xFFFF;
	i++;

	lp->RidList[i].len     = sizeof( lp->sec_stat );
	lp->RidList[i].typ     = CFG_SECURITY_STAT;
	lp->RidList[i].bufp    = (wci_recordp)&lp->sec_stat;
	lp->sec_stat.len       = 0xFFFF;
	i++;

	lp->RidList[i].typ     = 0;    // Terminate List

	RidLog = (CFG_RID_LOG_STRCT *)&lp->ltvRecord;
	RidLog->len     = 3;
	RidLog->typ     = CFG_REG_INFO_LOG;
	RidLog->recordp = (RID_LOGP)&lp->RidList[0];
	
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
	DBG_TRACE( DbgInfo, "CFG_REG_INFO_LOG\n" );
	DBG_TRACE( DbgInfo, "CFG_REG_INFO_LOG result           : 0x%04x\n", 
			   hcf_status );
	DBG_LEAVE( DbgInfo );
	return hcf_status;
} // wl_put_ltv_init
/*============================================================================*/


/*******************************************************************************
 *	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 hcf_status;
	/*------------------------------------------------------------------------*/
	DBG_FUNC( "wl_put_ltv" );
	DBG_ENTER( DbgInfo );
	
	if ( lp == NULL ) {
		DBG_ERROR( DbgInfo, "lp pointer is NULL\n" );
		return -1;
	}
	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
		lp->maxPort = 6;			//;?why set this here and not as part of download process
	} else {
		lp->maxPort = 0;
	}
	
	/* 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 ));
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

	/* 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 );
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

	/* 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 );
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

	/* 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 );
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

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

	/* Load Balancing */
	lp->ltvRecord.len       = 2;
	lp->ltvRecord.typ       = CFG_CNF_LOAD_BALANCING;
	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->loadBalancing );
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

	/* Medium Distribution */
	lp->ltvRecord.len       = 2;
	lp->ltvRecord.typ       = CFG_CNF_MEDIUM_DISTRIBUTION;
	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->mediumDistribution );
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
	/* Country Code */

#ifdef WARP 
	/* Tx Power Level (for supported cards) */
	lp->ltvRecord.len       = 2;
	lp->ltvRecord.typ       = CFG_CNF_TX_POW_LVL;
	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->txPowLevel );
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

	/* Short Retry Limit */
	/*lp->ltvRecord.len       = 2;
	lp->ltvRecord.typ       = 0xFC32;
	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->shortRetryLimit );
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
	*/

	/* Long Retry Limit */
	/*lp->ltvRecord.len       = 2;
	lp->ltvRecord.typ       = 0xFC33;
	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->longRetryLimit );
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
	*/

	/* Supported Rate Set Control */
	lp->ltvRecord.len       = 3;
	lp->ltvRecord.typ       = CFG_SUPPORTED_RATE_SET_CNTL; //0xFC88;
	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->srsc[0] );
	lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( lp->srsc[1] );
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

	/* Basic Rate Set Control */
	lp->ltvRecord.len       = 3;
	lp->ltvRecord.typ       = CFG_BASIC_RATE_SET_CNTL; //0xFC89;
	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->brsc[0] );
	lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( lp->brsc[1] );
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

	/* Frame Burst Limit */
	/* Defined, but not currently available in Firmware */

#endif // WARP
	
#ifdef WARP 
	/* Multicast Rate */
	lp->ltvRecord.len       = 3;
	lp->ltvRecord.typ       = CFG_CNF_MCAST_RATE;
	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->MulticastRate[0] );
	lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( lp->MulticastRate[1] );
#else
	lp->ltvRecord.len       = 2;
	lp->ltvRecord.typ       = CFG_CNF_MCAST_RATE;
	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->MulticastRate[0] );
#endif // WARP
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

	/* 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 );
	}
	
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

	//DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME result           : 0x%04x\n", 
	//           hcf_status );
	
	/* The following are set in STA mode only */
	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA  ) {

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

		/* Port Type */
		lp->ltvRecord.len       = 2;
		lp->ltvRecord.typ       = CFG_CNF_PORT_TYPE;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->PortType );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
		
		/* Tx Rate Control */
#ifdef WARP 
		lp->ltvRecord.len       = 3;
		lp->ltvRecord.typ       = CFG_TX_RATE_CNTL;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->TxRateControl[0] );
		lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( lp->TxRateControl[1] );
#else
		lp->ltvRecord.len       = 2;
		lp->ltvRecord.typ       = CFG_TX_RATE_CNTL;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->TxRateControl[0] );
#endif  // WARP

//;?skip temporarily to see whether the RID or something else is the probelm hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL 2.4GHz           : 0x%04x\n",
				   lp->TxRateControl[0] );
		DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL 5.0GHz           : 0x%04x\n",
				   lp->TxRateControl[1] );
		DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL result           : 0x%04x\n", 
				   hcf_status );
		/* Power Management */
		lp->ltvRecord.len       = 2;
		lp->ltvRecord.typ       = CFG_CNF_PM_ENABLED;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->PMEnabled );
//		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0x8001 );
		DBG_TRACE( DbgInfo, "CFG_CNF_PM_ENABLED                : 0x%04x\n", lp->PMEnabled );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
		/* Multicast Receive */
		lp->ltvRecord.len       = 2;
		lp->ltvRecord.typ       = CFG_CNF_MCAST_RX;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->MulticastReceive );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
		
		/* Create IBSS */
		lp->ltvRecord.len       = 2;
		lp->ltvRecord.typ       = CFG_CREATE_IBSS;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->CreateIBSS );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		}
		
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		//DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID result           : 0x%04x\n",
		//           hcf_status );
		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

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

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

		/* Authentication */
		lp->ltvRecord.len       = 2;
		lp->ltvRecord.typ       = CFG_CNF_AUTHENTICATION;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->authentication );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
#ifdef WARP 
		/* Connection Control */
		lp->ltvRecord.len       = 2;
		lp->ltvRecord.typ       = CFG_CNF_CONNECTION_CNTL;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->connectionControl );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

	

		/* Probe data rate */
		/*lp->ltvRecord.len       = 3;
		lp->ltvRecord.typ       = CFG_PROBE_DATA_RATE;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->probeDataRates[0] );
		lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( lp->probeDataRates[1] );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		DBG_TRACE( DbgInfo, "CFG_PROBE_DATA_RATE 2.4GHz        : 0x%04x\n",
				   lp->probeDataRates[0] );
		DBG_TRACE( DbgInfo, "CFG_PROBE_DATA_RATE 5.0GHz        : 0x%04x\n",
				   lp->probeDataRates[1] );
		DBG_TRACE( DbgInfo, "CFG_PROBE_DATA_RATE result        : 0x%04x\n",
				   hcf_status );*/
#endif // WARP
	} else {
		/* The following are set in AP mode only */
#if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
		//;?should we restore this to allow smaller memory footprint

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

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

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

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

		/* Tx Rate Control 0 */
#ifdef WARP 
		lp->ltvRecord.len       = 3;
		lp->ltvRecord.typ       = CFG_TX_RATE_CNTL0;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->TxRateControl[0] );
		lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( lp->TxRateControl[1] );
#else
		lp->ltvRecord.len       = 2;
		lp->ltvRecord.typ       = CFG_TX_RATE_CNTL0;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->TxRateControl[0] );
#endif  // WARP

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

		/* Own Beacon Interval */
		lp->ltvRecord.len       = 2;
		lp->ltvRecord.typ       = 0xFC31;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->ownBeaconInterval );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* Co-Existence Behavior */
		lp->ltvRecord.len       = 2;
		lp->ltvRecord.typ       = 0xFCC7;
		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->coexistence );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

#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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));


		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));


		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));


		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
#if 0
		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

#endif

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

		/* 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 );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
#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;  //;?why is this commented out already in 720
		//lp->MACAddress[0] |= 0x02;

		lp->ltvRecord.len = 1 + ( ETH_ALEN / sizeof( hcf_16 ));
		if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
			//DBG_TRACE( DbgInfo, "CFG_NIC_MAC_ADDR\n" );
			lp->ltvRecord.typ = CFG_NIC_MAC_ADDR;
		} else {
			//DBG_TRACE( DbgInfo, "CFG_CNF_OWN_MAC_ADDR\n" );
			lp->ltvRecord.typ = CFG_CNF_OWN_MAC_ADDR;
		}
		/* MAC address is byte aligned, no endian conversion needed */
		memcpy( &( lp->ltvRecord.u.u8[0] ), lp->MACAddress, ETH_ALEN );
		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
		//DBG_TRACE( DbgInfo, "CFG_XXX_MAC_ADDR result           : 0x%04x\n",
		//           hcf_status );

		/* Update the MAC address in the netdevice struct */
		memcpy( lp->dev->dev_addr, lp->MACAddress, ETH_ALEN ); //;?what is the purpose of this seemingly complex logic
	}
	/* 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 );
	}

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

	//DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID result           : 0x%04x\n",
	//           hcf_status );
	/* enable/disable encryption */
	lp->ltvRecord.len       = 2;
	lp->ltvRecord.typ       = CFG_CNF_ENCRYPTION;
	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->EnableEncryption );
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

	/* 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 );
	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
	/* WEP Keys */
	wl_set_wep_keys( lp );

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

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


/*******************************************************************************
 *	init_module()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Load the kernel module.
 *
 *  PARAMETERS:
 *
 *      N/A
 *
 *  RETURNS:
 *
 *      0 on success
 *      an errno value otherwise
 *
 ******************************************************************************/
int init_module( void ) 
{
	int result;
	/*------------------------------------------------------------------------*/

	DBG_FUNC( "init_module" );

#if DBG
	/* Convert "standard" PCMCIA parameter pc_debug to a reasonable DebugFlag value. 
	 * NOTE: The values all fall through to the lower values. */
	DbgInfo->DebugFlag = 0;
	DbgInfo->DebugFlag = DBG_TRACE_ON;		//;?get this mess resolved one day
	if ( pc_debug ) switch( pc_debug ) {
	  case 8:
		DbgInfo->DebugFlag |= DBG_DS_ON;
	  case 7:
		DbgInfo->DebugFlag |= DBG_RX_ON | DBG_TX_ON;
	  case 6:
		DbgInfo->DebugFlag |= DBG_PARAM_ON;
	  case 5:
		DbgInfo->DebugFlag |= DBG_TRACE_ON;
	  case 4:
		DbgInfo->DebugFlag |= DBG_VERBOSE_ON;
	  default:
		break;
	}
#endif /* DBG */

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

// ;?#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;
} // init_module
/*============================================================================*/


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

	wl_adapter_cleanup_module( );
	remove_proc_entry( "wlags", NULL );		//;?why so a-symmetric compared to location of create_proc_read_entry

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


/*******************************************************************************
 *	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 {
			//DBG_PRINT( "NOT OUR INTERRUPT\n" );
			hcf_action( &lp->hcfCtx, HCF_ACT_INT_ON );
		}
	}

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


/*******************************************************************************
 *	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
 *
 ******************************************************************************/
#define WVLAN_MAX_INT_SERVICES  50

void wl_isr_handler( struct wl_private *lp )
{
	struct net_device       *dev;
	unsigned long           flags;
	bool_t                  stop = TRUE;
	int                     count;
	int                     result;
	/*------------------------------------------------------------------------*/

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

		dev = (struct net_device *)lp->dev;
		if ( dev != NULL && netif_device_present( dev ) ) stop = FALSE;
		for( count = 0; stop == FALSE && count < WVLAN_MAX_INT_SERVICES; count++ ) {
			stop = TRUE;
			result = hcf_service_nic( &lp->hcfCtx,
									  (wci_bufp)lp->lookAheadBuf,
									  sizeof( lp->lookAheadBuf ));
			if ( result == HCF_ERR_MIC ) {
				wl_wext_event_mic_failed( dev ); 	/* Send an event that MIC failed */
				//;?this seems wrong if HCF_ERR_MIC coincides with another event, stop gets FALSE
				//so why not do it always ;?
			}

#ifndef USE_MBOX_SYNC
			if ( lp->hcfCtx.IFB_MBInfoLen != 0 ) {	/* anything in the mailbox */
				wl_mbx( lp );
				stop = FALSE;
			}
#endif
			/* Check for a Link status event */
			if ( lp->hcfCtx.IFB_DSLinkStat & CFG_LINK_STAT_CHANGE ) {
				wl_process_link_status( lp );
				stop = FALSE;
			}
			/* Check for probe response events */
			if ( lp->ProbeResp.infoType != 0 && 
				lp->ProbeResp.infoType != 0xFFFF ) {
				wl_process_probe_response( lp );
				memset( &lp->ProbeResp, 0, sizeof( lp->ProbeResp ));
				lp->ProbeResp.infoType = 0xFFFF;
				stop = FALSE;
			}
			/* Check for updated record events */
			if ( lp->updatedRecord.len != 0xFFFF ) {
				wl_process_updated_record( lp );
				lp->updatedRecord.len = 0xFFFF;
				stop = FALSE;
			}
			/* Check for association status events */
			if ( lp->assoc_stat.len != 0xFFFF ) {
				wl_process_assoc_status( lp );
				lp->assoc_stat.len = 0xFFFF;
				stop = FALSE;
			}
			/* Check for security status events */
			if ( lp->sec_stat.len != 0xFFFF ) {
				wl_process_security_status( lp );
				lp->sec_stat.len = 0xFFFF;
				stop = FALSE;
			}
		
#ifdef ENABLE_DMA
			if ( lp->use_dma ) {
				/* Check for DMA Rx packets */
				if ( lp->hcfCtx.IFB_DmaPackets & HREG_EV_RDMAD ) {
					wl_rx_dma( dev );
					stop = FALSE;
				}
				/* Return Tx DMA descriptors to host */ 
				if ( lp->hcfCtx.IFB_DmaPackets & HREG_EV_TDMAD ) {
					wl_pci_dma_hcf_reclaim_tx( lp );
					stop = FALSE;
				}
			}
			else
#endif // ENABLE_DMA
			{
				/* Check for Rx packets */
				if ( lp->hcfCtx.IFB_RxLen != 0 ) {
					wl_rx( dev );
					stop = FALSE;
				}
				/* Make sure that queued frames get sent */ 
				if ( wl_send( lp )) {
					stop = FALSE;
				}
			}
				}
		/* We're done, so turn interrupts which were turned off in wl_isr, back on */
		hcf_action( &lp->hcfCtx, HCF_ACT_INT_ON );
		spin_unlock_irqrestore( &( lp->slock ), flags );
	}
	return;
} // wl_isr_handler
/*============================================================================*/


/*******************************************************************************
 *	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 );
		/* Disable the ports */
		wl_disable( lp );

#if 0 //;? (HCF_TYPE) & HCF_TYPE_AP
#ifdef USE_WDS
		//wl_disable_wds_ports( lp );
#endif // USE_WDS
#endif  /* (HCF_TYPE) & HCF_TYPE_AP */

		/* 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_connect( &lp->hcfCtx, HCF_DISCONNECT );

		spin_unlock_irqrestore( &( lp->slock ), flags );
	}
	DBG_LEAVE( DbgInfo );
	return;
} // wl_remove
/*============================================================================*/


/*******************************************************************************
 *	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_connect( &lp->hcfCtx, HCF_DISCONNECT );

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

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


/*******************************************************************************
 *	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_resume
/*============================================================================*/


/*******************************************************************************
 *	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_release
/*============================================================================*/


/*******************************************************************************
 *	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_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_irq_list
/*============================================================================*/



/*******************************************************************************
 *	wl_enable()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Used to enable MAC ports
 *
 *  PARAMETERS:
 *
 *      lp      - pointer to the device's private adapter structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
int wl_enable( struct wl_private *lp )
{
	int hcf_status = HCF_SUCCESS;
	/*------------------------------------------------------------------------*/
	DBG_FUNC( "wl_enable" );
	DBG_ENTER( DbgInfo );

	if ( lp->portState == WVLAN_PORT_STATE_ENABLED ) {
		DBG_TRACE( DbgInfo, "No action: Card already enabled\n" );
	} else if ( lp->portState == WVLAN_PORT_STATE_CONNECTED ) {
		//;?suspicuous logic, how can you be connected without being enabled so this is probably dead code
		DBG_TRACE( DbgInfo, "No action: Card already connected\n" );
	} else {
		hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_ENABLE );
		if ( hcf_status == HCF_SUCCESS ) {
			/* Set the status of the NIC to enabled */
			lp->portState = WVLAN_PORT_STATE_ENABLED;   //;?bad mnemonic, NIC iso PORT
#ifdef ENABLE_DMA
			if ( lp->use_dma ) {
				wl_pci_dma_hcf_supply( lp );  //;?always succes?
			}
#endif
		}
	}
	if ( hcf_status != HCF_SUCCESS ) {  //;?make this an assert
		DBG_TRACE( DbgInfo, "failed: 0x%x\n", hcf_status );
	}
	DBG_LEAVE( DbgInfo );
	return hcf_status;
} // wl_enable
/*============================================================================*/


#ifdef USE_WDS
/*******************************************************************************
 *	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 );
	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ){
		DBG_ERROR( DbgInfo, "!!!!;? someone misunderstood something !!!!!\n" );
	}
	DBG_LEAVE( DbgInfo );
	return;
} // wl_enable_wds_ports
#endif  /* USE_WDS */
/*============================================================================*/


/*******************************************************************************
 *	wl_connect()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Used to connect a MAC port
 *
 *  PARAMETERS:
 *
 *      lp      - pointer to the device's private adapter structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
int wl_connect( struct wl_private *lp )
{
	int hcf_status;
	/*------------------------------------------------------------------------*/

	DBG_FUNC( "wl_connect" );
	DBG_ENTER( DbgInfo );

	if ( lp->portState != WVLAN_PORT_STATE_ENABLED ) {
		DBG_TRACE( DbgInfo, "No action: Not in enabled state\n" );
		DBG_LEAVE( DbgInfo );
		return HCF_SUCCESS;
	}
	hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_CONNECT );
	if ( hcf_status == HCF_SUCCESS ) {
		lp->portState = WVLAN_PORT_STATE_CONNECTED;
	}
	DBG_LEAVE( DbgInfo );
	return hcf_status;
} // wl_connect
/*============================================================================*/


/*******************************************************************************
 *	wl_disconnect()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *      Used to disconnect a MAC port
 *
 *  PARAMETERS:
 *
 *      lp      - pointer to the device's private adapter structure
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
int wl_disconnect( struct wl_private *lp )
{
	int hcf_status;
	/*------------------------------------------------------------------------*/

	DBG_FUNC( "wl_disconnect" );
	DBG_ENTER( DbgInfo );

	if ( lp->portState != WVLAN_PORT_STATE_CONNECTED ) {
		DBG_TRACE( DbgInfo, "No action: Not in connected state\n" );
		DBG_LEAVE( DbgInfo );
		return HCF_SUCCESS;
	}
	hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_DISCONNECT );
	if ( hcf_status == HCF_SUCCESS ) {
		lp->portState = WVLAN_PORT_STATE_ENABLED;
	}
	DBG_LEAVE( DbgInfo );
	return hcf_status;
} // wl_disconnect
/*============================================================================*/


/*******************************************************************************
 *	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 )
{
	int hcf_status = HCF_SUCCESS;
	/*------------------------------------------------------------------------*/
	DBG_FUNC( "wl_disable" );
	DBG_ENTER( DbgInfo );
	
	if ( lp->portState == WVLAN_PORT_STATE_DISABLED ) {
		DBG_TRACE( DbgInfo, "No action: Port state is disabled\n" );
	} else {
		hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_DISABLE );
		if ( hcf_status == HCF_SUCCESS ) {
			/* Set the status of the port to disabled */ //;?bad mnemonic use NIC iso PORT
			lp->portState = WVLAN_PORT_STATE_DISABLED;

#ifdef ENABLE_DMA
			if ( lp->use_dma ) {
				wl_pci_dma_hcf_reclaim( lp );
			}
#endif
		}
	}
	if ( hcf_status != HCF_SUCCESS ) {
		DBG_TRACE( DbgInfo, "failed: 0x%x\n", hcf_status );
	}
	DBG_LEAVE( DbgInfo );
	return hcf_status;
} // wl_disable
/*============================================================================*/


#ifdef USE_WDS
/*******************************************************************************
 *	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 ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ){
		DBG_ERROR( DbgInfo, "!!!!;? someone misunderstood something !!!!!\n" );
	}
// 	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_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 );
// 	}
	DBG_LEAVE( DbgInfo );
	return;
} // wl_disable_wds_ports
#endif // USE_WDS
/*============================================================================*/


#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 hcf_status = 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;
	hcf_status = hcf_get_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));

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

		DBG_LEAVE( DbgInfo );
		return hcf_status;
	}

	if ( lp->ltvRecord.typ == CFG_MB_INFO ) {
		DBG_LEAVE( DbgInfo );
		return hcf_status;
	}
	/* Endian translate the mailbox data, then process the message */
	wl_endian_translate_mailbox( &( lp->ltvRecord ));
	wl_process_mailbox( lp );
	DBG_LEAVE( DbgInfo );
	return hcf_status;
} // wl_mbx
/*============================================================================*/


/*******************************************************************************
 *	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:
		{
			PROBE_RESP *probe_resp = (PROBE_RESP *)ltv;

			probe_resp->frameControl   = CNV_LITTLE_TO_INT( probe_resp->frameControl );
			probe_resp->durID          = CNV_LITTLE_TO_INT( probe_resp->durID );
			probe_resp->sequence       = CNV_LITTLE_TO_INT( probe_resp->sequence );
			probe_resp->dataLength     = CNV_LITTLE_TO_INT( probe_resp->dataLength );
#ifndef WARP 
			probe_resp->lenType        = CNV_LITTLE_TO_INT( probe_resp->lenType );
#endif // WARP
			probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
			probe_resp->capability     = CNV_LITTLE_TO_INT( probe_resp->capability );
			probe_resp->flags          = CNV_LITTLE_TO_INT( probe_resp->flags );
		}
		break;

	  case CFG_LINK_STAT:
#define ls ((LINK_STATUS_STRCT *)ltv)
			ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
		break;
#undef ls

	  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_endian_translate_mailbox
/*============================================================================*/

/*******************************************************************************
 *	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;
	hcf_16  ltv_val = 0xFFFF;
	/*------------------------------------------------------------------------*/
	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:
#define ls ((LINK_STATUS_STRCT *)ltv)
		DBG_TRACE( DbgInfo, "CFG_LINK_STAT\n" );

		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;
#undef ls

	  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;

	  case CFG_UPDATED_INFO_RECORD:        // Updated Information Record
		DBG_TRACE( DbgInfo, "UPDATED INFORMATION RECORD\n" );

		ltv_val = CNV_INT_TO_LITTLE( ltv->u.u16[0] );

		/* Check and see which RID was updated */
		switch( ltv_val ) {
		  case CFG_CUR_COUNTRY_INFO:  // Indicate Passive Scan Completion
			DBG_TRACE( DbgInfo, "Updated country info\n" );

			/* Do I need to hold off on updating RIDs until the process is
			   complete? */
			wl_connect( lp );
			break;

		  case CFG_PORT_STAT:    // Wait for Connect Event
			//wl_connect( lp );

			break;

		default:
			DBG_WARNING( DbgInfo, "Unknown RID: 0x%04x\n", ltv_val );
		}

		break;

	default:
		DBG_TRACE( DbgInfo, "UNKNOWN MESSAGE: 0x%04x\n", ltv->typ );
		break;
	}
	DBG_LEAVE( DbgInfo );
	return;
} // wl_process_mailbox
/*============================================================================*/
#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 );
	//;?why is there no USE_WDS clause like in wl_enable_wds_ports
	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_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_register
/*============================================================================*/


/*******************************************************************************
 *	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 ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_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;
} // wl_wds_netdev_deregister
/*============================================================================*/
#endif  /* USE_WDS */


#if 1 //SCULL_USE_PROC /* don't waste space if unused */
/*
 * The proc filesystem: function to read and entry
 */
int printf_hcf_16( char *s, char *buf, hcf_16* p, int n );
int printf_hcf_16( char *s, char *buf, hcf_16* p, int n ) {
	
int i, len;
	
	len = sprintf(buf, "%s", s );
	while ( len < 20 ) len += sprintf(buf+len, " " );
	len += sprintf(buf+len,": " );
	for ( i = 0; i < n; i++ ) {
		if ( len % 80 > 75 ) {
			len += sprintf(buf+len,"\n" );
		}
		len += sprintf(buf+len,"%04X ", p[i] );
	}
	len += sprintf(buf+len,"\n" );
	return len;
} // printf_hcf_16

int printf_hcf_8( char *s, char *buf, hcf_8* p, int n );
int printf_hcf_8( char *s, char *buf, hcf_8* p, int n ) {
	
int i, len;
	
	len = sprintf(buf, "%s", s );
	while ( len < 20 ) len += sprintf(buf+len, " " );
	len += sprintf(buf+len,": " );
	for ( i = 0; i <= n; i++ ) {
		if ( len % 80 > 77 ) {
			len += sprintf(buf+len,"\n" );
		}
		len += sprintf(buf+len,"%02X ", p[i] );
	}
	len += sprintf(buf+len,"\n" );
	return len;
} // printf_hcf8

int printf_strct( char *s, char *buf, hcf_16* p );
int printf_strct( char *s, char *buf, hcf_16* p ) {
	
int i, len;
	
	len = sprintf(buf, "%s", s );
	while ( len < 20 ) len += sprintf(buf+len, " " );
	len += sprintf(buf+len,": " );
	for ( i = 0; i <= *p; i++ ) {
		if ( len % 80 > 75 ) {
			len += sprintf(buf+len,"\n" );
		}
		len += sprintf(buf+len,"%04X ", p[i] );
	}
	len += sprintf(buf+len,"\n" );
	return len;
} // printf_strct

int scull_read_procmem(char *buf, char **start, off_t offset, int len, int *eof, void *data )
{
	struct wl_private	*lp = NULL;
	IFBP				ifbp;

    #define LIMIT (PAGE_SIZE-80) /* don't print any more after this size */
	
    len=0;
	
	if ( ( lp = ((struct net_device *)data)->priv ) == NULL ) {
        len += sprintf(buf+len,"No wl_private in scull_read_procmem\n" );
	} else if ( lp->wlags49_type == 0 ){
   	    ifbp = &lp->hcfCtx;
   	    len += sprintf(buf+len,"Magic:               0x%04X\n", ifbp->IFB_Magic );
   	    len += sprintf(buf+len,"IOBase:              0x%04X\n", ifbp->IFB_IOBase );
   	    len += sprintf(buf+len,"LinkStat:            0x%04X\n", ifbp->IFB_LinkStat );
   	    len += sprintf(buf+len,"DSLinkStat:          0x%04X\n", ifbp->IFB_DSLinkStat );
   	    len += sprintf(buf+len,"TickIni:         0x%08lX\n", ifbp->IFB_TickIni );
   	    len += sprintf(buf+len,"TickCnt:             0x%04X\n", ifbp->IFB_TickCnt );
   	    len += sprintf(buf+len,"IntOffCnt:           0x%04X\n", ifbp->IFB_IntOffCnt );
		len += printf_hcf_16( "IFB_FWIdentity", &buf[len],
							  &ifbp->IFB_FWIdentity.len, ifbp->IFB_FWIdentity.len + 1 );
	} else if ( lp->wlags49_type == 1 ) {
   	    len += sprintf(buf+len,"Channel:              0x%04X\n", lp->Channel );
/****** len += sprintf(buf+len,"slock:                  %d\n", lp->slock );		*/
//x		struct tq_struct            "task:               0x%04X\n", lp->task );
//x		struct net_device_stats     "stats:              0x%04X\n", lp->stats );
#ifdef WIRELESS_EXT
//x		struct iw_statistics        "wstats:             0x%04X\n", lp->wstats );
   	    len += sprintf(buf+len,"spy_number:           0x%04X\n", lp->spy_number );
//x		u_char                      spy_address[IW_MAX_SPY][ETH_ALEN];
//x		struct iw_quality           spy_stat[IW_MAX_SPY];
#endif // WIRELESS_EXT
   	    len += sprintf(buf+len,"IFB:                  0x%p\n", &lp->hcfCtx );
   	    len += sprintf(buf+len,"flags:                %#.8lX\n", lp->flags );  //;?use this format from now on
   	    len += sprintf(buf+len,"DebugFlag(wl_private) 0x%04X\n", lp->DebugFlag );
   	    len += sprintf(buf+len,"DebugFlag (DbgInfo):   0x%08lX\n", DbgInfo->DebugFlag );
   	    len += sprintf(buf+len,"is_registered:        0x%04X\n", lp->is_registered );
//x		CFG_DRV_INFO_STRCT          "driverInfo:         0x%04X\n", lp->driverInfo );
		len += printf_strct( "driverInfo", &buf[len], (hcf_16*)&lp->driverInfo );
//x		CFG_IDENTITY_STRCT          "driverIdentity:     0x%04X\n", lp->driverIdentity );
		len += printf_strct( "driverIdentity", &buf[len], (hcf_16*)&lp->driverIdentity );
//x		CFG_FW_IDENTITY_STRCT       "StationIdentity:    0x%04X\n", lp->StationIdentity );
		len += printf_strct( "StationIdentity", &buf[len], (hcf_16*)&lp->StationIdentity );
//x		CFG_PRI_IDENTITY_STRCT      "PrimaryIdentity:    0x%04X\n", lp->PrimaryIdentity );
		len += printf_strct( "PrimaryIdentity", &buf[len], (hcf_16*)&lp->hcfCtx.IFB_PRIIdentity );
		len += printf_strct( "PrimarySupplier", &buf[len], (hcf_16*)&lp->hcfCtx.IFB_PRISup );
//x		CFG_PRI_IDENTITY_STRCT      "NICIdentity:        0x%04X\n", lp->NICIdentity );
		len += printf_strct( "NICIdentity", &buf[len], (hcf_16*)&lp->NICIdentity );
//x		ltv_t                       "ltvRecord:          0x%04X\n", lp->ltvRecord );
   	    len += sprintf(buf+len,"txBytes:              0x%08lX\n", lp->txBytes );
   	    len += sprintf(buf+len,"maxPort:              0x%04X\n", lp->maxPort );        /* 0 for STA, 6 for AP */
	/* Elements used for async notification from hardware */
//x		RID_LOG_STRCT				RidList[10];
//x		ltv_t                       "updatedRecord:      0x%04X\n", lp->updatedRecord );
//x		PROBE_RESP				    "ProbeResp:                    0x%04X\n", lp->ProbeResp );
//x		ASSOC_STATUS_STRCT          "assoc_stat:         0x%04X\n", lp->assoc_stat );
//x		SECURITY_STATUS_STRCT       "sec_stat:           0x%04X\n", lp->sec_stat );
//x		u_char                      lookAheadBuf[WVLAN_MAX_LOOKAHEAD];
   	    len += sprintf(buf+len,"PortType:             0x%04X\n", lp->PortType );           // 1 - 3 (1 [Normal] | 3 [AdHoc])
   	    len += sprintf(buf+len,"Channel:              0x%04X\n", lp->Channel );            // 0 - 14 (0)
//x		hcf_16                      TxRateControl[2];
   	    len += sprintf(buf+len,"TxRateControl[2]:     0x%04X 0x%04X\n", 
						lp->TxRateControl[0], lp->TxRateControl[1] );
   	    len += sprintf(buf+len,"DistanceBetweenAPs:   0x%04X\n", lp->DistanceBetweenAPs ); // 1 - 3 (1)
   	    len += sprintf(buf+len,"RTSThreshold:         0x%04X\n", lp->RTSThreshold );       // 0 - 2347 (2347)
   	    len += sprintf(buf+len,"PMEnabled:            0x%04X\n", lp->PMEnabled );          // 0 - 2, 8001 - 8002 (0)
   	    len += sprintf(buf+len,"MicrowaveRobustness:  0x%04X\n", lp->MicrowaveRobustness );// 0 - 1 (0)
   	    len += sprintf(buf+len,"CreateIBSS:           0x%04X\n", lp->CreateIBSS );         // 0 - 1 (0)
   	    len += sprintf(buf+len,"MulticastReceive:     0x%04X\n", lp->MulticastReceive );   // 0 - 1 (1)
   	    len += sprintf(buf+len,"MaxSleepDuration:     0x%04X\n", lp->MaxSleepDuration );   // 0 - 65535 (100)
//x		hcf_8                       MACAddress[ETH_ALEN];
		len += printf_hcf_8( "MACAddress", &buf[len], lp->MACAddress, ETH_ALEN );
//x		char                        NetworkName[HCF_MAX_NAME_LEN+1];
   	    len += sprintf(buf+len,"NetworkName:          %.32s\n", lp->NetworkName );
//x		char                        StationName[HCF_MAX_NAME_LEN+1];
   	    len += sprintf(buf+len,"EnableEncryption:     0x%04X\n", lp->EnableEncryption );   // 0 - 1 (0)
//x		char                        Key1[MAX_KEY_LEN+1];
		len += printf_hcf_8( "Key1", &buf[len], lp->Key1, MAX_KEY_LEN );
//x		char                        Key2[MAX_KEY_LEN+1];
//x		char                        Key3[MAX_KEY_LEN+1];
//x		char                        Key4[MAX_KEY_LEN+1];
   	    len += sprintf(buf+len,"TransmitKeyID:        0x%04X\n", lp->TransmitKeyID );      // 1 - 4 (1)
//x		CFG_DEFAULT_KEYS_STRCT	    "DefaultKeys:         0x%04X\n", lp->DefaultKeys );
//x		u_char                      mailbox[MB_SIZE];
//x		char                        szEncryption[MAX_ENC_LEN];
   	    len += sprintf(buf+len,"driverEnable:         0x%04X\n", lp->driverEnable );
   	    len += sprintf(buf+len,"wolasEnable:          0x%04X\n", lp->wolasEnable );
   	    len += sprintf(buf+len,"atimWindow:           0x%04X\n", lp->atimWindow );
   	    len += sprintf(buf+len,"holdoverDuration:     0x%04X\n", lp->holdoverDuration );
//x		hcf_16                      MulticastRate[2];
   	    len += sprintf(buf+len,"authentication:       0x%04X\n", lp->authentication ); // is this AP specific?
   	    len += sprintf(buf+len,"promiscuousMode:      0x%04X\n", lp->promiscuousMode );
   	    len += sprintf(buf+len,"DownloadFirmware:     0x%04X\n", lp->DownloadFirmware );   // 0 - 2 (0 [None] | 1 [STA] | 2 [AP])
   	    len += sprintf(buf+len,"AuthKeyMgmtSuite:     0x%04X\n", lp->AuthKeyMgmtSuite );
   	    len += sprintf(buf+len,"loadBalancing:        0x%04X\n", lp->loadBalancing );
   	    len += sprintf(buf+len,"mediumDistribution:   0x%04X\n", lp->mediumDistribution );
   	    len += sprintf(buf+len,"txPowLevel:           0x%04X\n", lp->txPowLevel );
//   	    len += sprintf(buf+len,"shortRetryLimit:    0x%04X\n", lp->shortRetryLimit );
//   	    len += sprintf(buf+len,"longRetryLimit:     0x%04X\n", lp->longRetryLimit );
//x		hcf_16                      srsc[2];
//x		hcf_16                      brsc[2];
   	    len += sprintf(buf+len,"connectionControl:    0x%04X\n", lp->connectionControl );
//x		//hcf_16                      probeDataRates[2];
   	    len += sprintf(buf+len,"ownBeaconInterval:    0x%04X\n", lp->ownBeaconInterval );
   	    len += sprintf(buf+len,"coexistence:          0x%04X\n", lp->coexistence );
//x		WVLAN_FRAME                 "txF:                0x%04X\n", lp->txF );
//x		WVLAN_LFRAME                txList[DEFAULT_NUM_TX_FRAMES];
//x		struct list_head            "txFree:             0x%04X\n", lp->txFree );
//x		struct list_head            txQ[WVLAN_MAX_TX_QUEUES]; 
   	    len += sprintf(buf+len,"netif_queue_on:       0x%04X\n", lp->netif_queue_on );
   	    len += sprintf(buf+len,"txQ_count:            0x%04X\n", lp->txQ_count );
//x		DESC_STRCT                  "desc_rx:            0x%04X\n", lp->desc_rx );
//x		DESC_STRCT                  "desc_tx:            0x%04X\n", lp->desc_tx );
//x		WVLAN_PORT_STATE            "portState:          0x%04X\n", lp->portState );
//x		ScanResult                  "scan_results:       0x%04X\n", lp->scan_results );
//x		ProbeResult                 "probe_results:      0x%04X\n", lp->probe_results );
   	    len += sprintf(buf+len,"probe_num_aps:        0x%04X\n", lp->probe_num_aps );
   	    len += sprintf(buf+len,"use_dma:              0x%04X\n", lp->use_dma );
//x		DMA_STRCT                   "dma:                0x%04X\n", lp->dma );
#ifdef USE_RTS
   	    len += sprintf(buf+len,"useRTS:               0x%04X\n", lp->useRTS );
#endif  // USE_RTS
#if 1 //;? (HCF_TYPE) & HCF_TYPE_AP
		//;?should we restore this to allow smaller memory footprint
		//;?I guess not. This should be brought under Debug mode only
   	    len += sprintf(buf+len,"DTIMPeriod:           0x%04X\n", lp->DTIMPeriod );         // 1 - 255 (1)
   	    len += sprintf(buf+len,"multicastPMBuffering: 0x%04X\n", lp->multicastPMBuffering );
   	    len += sprintf(buf+len,"RejectAny:            0x%04X\n", lp->RejectAny );          // 0 - 1 (0)
   	    len += sprintf(buf+len,"ExcludeUnencrypted:   0x%04X\n", lp->ExcludeUnencrypted ); // 0 - 1 (1)
   	    len += sprintf(buf+len,"intraBSSRelay:        0x%04X\n", lp->intraBSSRelay );
   	    len += sprintf(buf+len,"wlags49_type:             0x%08lX\n", lp->wlags49_type );
#ifdef USE_WDS
//x		WVLAN_WDS_IF                wds_port[NUM_WDS_PORTS];
#endif // USE_WDS
#endif // HCF_AP
	} else if ( lp->wlags49_type == 2 ){
        len += sprintf(buf+len,"tallies to be added\n" );
//Hermes Tallies (IFB substructure) {
   	    CFG_HERMES_TALLIES_STRCT *p = &lp->hcfCtx.IFB_NIC_Tallies;
        len += sprintf(buf+len,"TxUnicastFrames:          %08lX\n", p->TxUnicastFrames );
        len += sprintf(buf+len,"TxMulticastFrames:        %08lX\n", p->TxMulticastFrames );
        len += sprintf(buf+len,"TxFragments:              %08lX\n", p->TxFragments );
        len += sprintf(buf+len,"TxUnicastOctets:          %08lX\n", p->TxUnicastOctets );
        len += sprintf(buf+len,"TxMulticastOctets:        %08lX\n", p->TxMulticastOctets );
        len += sprintf(buf+len,"TxDeferredTransmissions:  %08lX\n", p->TxDeferredTransmissions );
        len += sprintf(buf+len,"TxSingleRetryFrames:      %08lX\n", p->TxSingleRetryFrames );
        len += sprintf(buf+len,"TxMultipleRetryFrames:    %08lX\n", p->TxMultipleRetryFrames );
        len += sprintf(buf+len,"TxRetryLimitExceeded:     %08lX\n", p->TxRetryLimitExceeded );
        len += sprintf(buf+len,"TxDiscards:               %08lX\n", p->TxDiscards );
        len += sprintf(buf+len,"RxUnicastFrames:          %08lX\n", p->RxUnicastFrames );
        len += sprintf(buf+len,"RxMulticastFrames:        %08lX\n", p->RxMulticastFrames );
        len += sprintf(buf+len,"RxFragments:              %08lX\n", p->RxFragments );
        len += sprintf(buf+len,"RxUnicastOctets:          %08lX\n", p->RxUnicastOctets );
        len += sprintf(buf+len,"RxMulticastOctets:        %08lX\n", p->RxMulticastOctets );
        len += sprintf(buf+len,"RxFCSErrors:              %08lX\n", p->RxFCSErrors );
        len += sprintf(buf+len,"RxDiscardsNoBuffer:       %08lX\n", p->RxDiscardsNoBuffer );
        len += sprintf(buf+len,"TxDiscardsWrongSA:        %08lX\n", p->TxDiscardsWrongSA );
        len += sprintf(buf+len,"RxWEPUndecryptable:       %08lX\n", p->RxWEPUndecryptable );
        len += sprintf(buf+len,"RxMsgInMsgFragments:      %08lX\n", p->RxMsgInMsgFragments );
        len += sprintf(buf+len,"RxMsgInBadMsgFragments:   %08lX\n", p->RxMsgInBadMsgFragments );
        len += sprintf(buf+len,"RxDiscardsWEPICVError:    %08lX\n", p->RxDiscardsWEPICVError );
        len += sprintf(buf+len,"RxDiscardsWEPExcluded:    %08lX\n", p->RxDiscardsWEPExcluded );
#if (HCF_EXT) & HCF_EXT_TALLIES_FW
        //to be added ;?
#endif // HCF_EXT_TALLIES_FW
	} else if ( lp->wlags49_type & 0x8000 ) {	//;?kludgy but it is unclear to me were else to place this
		DbgInfo->DebugFlag = lp->wlags49_type & 0x7FFF;
		lp->wlags49_type = 0;				//default to IFB again ;?
	} else {
        len += sprintf(buf+len,"unknown value for wlags49_type: 0x%08lX\n", lp->wlags49_type );
        len += sprintf(buf+len,"0x0000 - IFB\n" );
        len += sprintf(buf+len,"0x0001 - wl_private\n" );
        len += sprintf(buf+len,"0x0002 - Tallies\n" );
        len += sprintf(buf+len,"0x8xxx - Change debufflag\n" );
        len += sprintf(buf+len,"ERROR    0001\nWARNING  0002\nNOTICE   0004\nTRACE    0008\n" );
        len += sprintf(buf+len,"VERBOSE  0010\nPARAM    0020\nBREAK    0040\nRX       0100\n" );
        len += sprintf(buf+len,"TX       0200\nDS       0400\n" );
	}
    return len;
} // scull_read_procmem

static void proc_write(const char *name, write_proc_t *w, void *data)
{
	struct proc_dir_entry * entry = create_proc_entry(name, S_IFREG | S_IWUSR, NULL);
	if (entry) {
		entry->write_proc = w;
		entry->data = data;
	}
} // proc_write

static int write_int(struct file *file, const char *buffer, unsigned long count, void *data)
{
	static char		proc_number[11];
	unsigned int	nr = 0;
	
	DBG_FUNC( "write_int" );
	DBG_ENTER( DbgInfo );

	if (count > 9) {
		count = -EINVAL;
	} else if ( copy_from_user(proc_number, buffer, count) ) {
		count = -EFAULT;
	}
	if  (count > 0 ) {
		proc_number[count] = 0;
		nr = wvlan_atoi( proc_number );
 		*(unsigned int *)data = nr;
		if ( nr & 0x8000 ) {	//;?kludgy but it is unclear to me were else to place this
			DbgInfo->DebugFlag = nr & 0x7FFF;
		}
	}
	DBG_PRINT( "value: %08lX\n", nr );
	DBG_LEAVE( DbgInfo );
	return count;
} // write_int

#endif /* SCULL_USE_PROC */

#ifdef DN554
#define RUN_AT(x)		(jiffies+(x))		//"borrowed" from include/pcmcia/k_compat.h
#define DS_OOR	0x8000		//Deepsleep OutOfRange Status
		
		lp->timer_oor_cnt = DS_OOR;
		init_timer( &lp->timer_oor );
		lp->timer_oor.function = timer_oor;
		lp->timer_oor.data = (unsigned long)lp;
		lp->timer_oor.expires = RUN_AT( 3 * HZ );
		add_timer( &lp->timer_oor );
		printk( "<5>wl_enable: %ld\n", jiffies );		//;?remove me 1 day
#endif //DN554
#ifdef DN554		
/*******************************************************************************
 *	timer_oor()
 *******************************************************************************
 *
 *  DESCRIPTION:
 *
 *
 *  PARAMETERS:
 *
 *      arg - a u_long representing a pointer to a dev_link_t structure for the
 *            device to be released.
 *
 *  RETURNS:
 *
 *      N/A
 *
 ******************************************************************************/
void timer_oor( u_long arg )
{
	struct wl_private       *lp = (struct wl_private *)arg;

    /*------------------------------------------------------------------------*/

    DBG_FUNC( "timer_oor" );
    DBG_ENTER( DbgInfo );
    DBG_PARAM( DbgInfo, "arg", "0x%08lx", arg );

	printk( "<5>timer_oor: %ld 0x%04X\n", jiffies, lp->timer_oor_cnt );		//;?remove me 1 day
	lp->timer_oor_cnt += 10;
    if ( (lp->timer_oor_cnt & ~DS_OOR) > 300 ) {
		lp->timer_oor_cnt = 300;
	}
	lp->timer_oor_cnt |= DS_OOR;
	init_timer( &lp->timer_oor );
	lp->timer_oor.function = timer_oor;
	lp->timer_oor.data = (unsigned long)lp;
	lp->timer_oor.expires = RUN_AT( (lp->timer_oor_cnt & ~DS_OOR) * HZ );
	add_timer( &lp->timer_oor );

    DBG_LEAVE( DbgInfo );
} // timer_oor
#endif //DN554
