• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/wlags49_h2/
1/*******************************************************************************
2 * Agere Systems Inc.
3 * Wireless device driver for Linux (wlags49).
4 *
5 * Copyright (c) 1998-2003 Agere Systems Inc.
6 * All rights reserved.
7 *   http://www.agere.com
8 *
9 * Initially developed by TriplePoint, Inc.
10 *   http://www.triplepoint.com
11 *
12 *------------------------------------------------------------------------------
13 *
14 *   This file contains the main driver entry points and other adapter
15 *   specific routines.
16 *
17 *------------------------------------------------------------------------------
18 *
19 * SOFTWARE LICENSE
20 *
21 * This software is provided subject to the following terms and conditions,
22 * which you should read carefully before using the software.  Using this
23 * software indicates your acceptance of these terms and conditions.  If you do
24 * not agree with these terms and conditions, do not use the software.
25 *
26 * Copyright � 2003 Agere Systems Inc.
27 * All rights reserved.
28 *
29 * Redistribution and use in source or binary forms, with or without
30 * modifications, are permitted provided that the following conditions are met:
31 *
32 * . Redistributions of source code must retain the above copyright notice, this
33 *    list of conditions and the following Disclaimer as comments in the code as
34 *    well as in the documentation and/or other materials provided with the
35 *    distribution.
36 *
37 * . Redistributions in binary form must reproduce the above copyright notice,
38 *    this list of conditions and the following Disclaimer in the documentation
39 *    and/or other materials provided with the distribution.
40 *
41 * . Neither the name of Agere Systems Inc. nor the names of the contributors
42 *    may be used to endorse or promote products derived from this software
43 *    without specific prior written permission.
44 *
45 * Disclaimer
46 *
47 * THIS SOFTWARE IS PROVIDED �AS IS� AND ANY EXPRESS OR IMPLIED WARRANTIES,
48 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
49 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
50 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
51 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
52 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
55 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
57 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
58 * DAMAGE.
59 *
60 ******************************************************************************/
61
62/*******************************************************************************
63 *  constant definitions
64 ******************************************************************************/
65
66/* Allow support for calling system fcns to access F/W iamge file */
67#define __KERNEL_SYSCALLS__
68
69/*******************************************************************************
70 *  include files
71 ******************************************************************************/
72#include <wl_version.h>
73
74#include <linux/module.h>
75#include <linux/proc_fs.h>
76#include <linux/types.h>
77#include <linux/kernel.h>
78// #include <linux/sched.h>
79// #include <linux/ptrace.h>
80// #include <linux/slab.h>
81// #include <linux/ctype.h>
82// #include <linux/string.h>
83// #include <linux/timer.h>
84//#include <linux/interrupt.h>
85// #include <linux/tqueue.h>
86// #include <linux/in.h>
87// #include <linux/delay.h>
88// #include <asm/io.h>
89// #include <asm/system.h>
90// #include <asm/bitops.h>
91#include <linux/unistd.h>
92#include <asm/uaccess.h>
93
94#include <linux/netdevice.h>
95#include <linux/etherdevice.h>
96// #include <linux/skbuff.h>
97// #include <linux/if_arp.h>
98// #include <linux/ioport.h>
99
100#define BIN_DL 0
101#if BIN_DL
102#include <linux/vmalloc.h>
103#endif // BIN_DL
104
105
106#include <debug.h>
107
108#include <hcf.h>
109#include <dhf.h>
110//in order to get around:: wl_main.c:2229: `HREG_EV_RDMAD' undeclared (first use in this function)
111#include <hcfdef.h>
112
113#include <wl_if.h>
114#include <wl_internal.h>
115#include <wl_util.h>
116#include <wl_main.h>
117#include <wl_netdev.h>
118#include <wl_wext.h>
119
120#ifdef USE_PROFILE
121#include <wl_profile.h>
122#endif  /* USE_PROFILE */
123
124#ifdef BUS_PCMCIA
125#include <wl_cs.h>
126#endif  /* BUS_PCMCIA */
127
128#ifdef BUS_PCI
129#include <wl_pci.h>
130#endif  /* BUS_PCI */
131/*******************************************************************************
132 *	macro defintions
133 ******************************************************************************/
134#define VALID_PARAM(C) \
135	{ \
136		if (!(C)) \
137		{ \
138			printk(KERN_INFO "Wireless, parameter error: \"%s\"\n", #C); \
139			goto failed; \
140		} \
141	}
142/*******************************************************************************
143 *	local functions
144 ******************************************************************************/
145void wl_isr_handler( unsigned long p );
146
147#if 0 //SCULL_USE_PROC     /* don't waste space if unused */
148//int scull_read_procmem(char *buf, char **start, off_t offset, int len, int unused);
149int scull_read_procmem(char *buf, char **start, off_t offset, int len, int *eof, void *data );
150static int write_int(struct file *file, const char *buffer, unsigned long count, void *data);
151static void proc_write(const char *name, write_proc_t *w, void *data);
152
153#endif /* SCULL_USE_PROC */
154
155/*******************************************************************************
156 * module parameter definitions - set with 'insmod'
157 ******************************************************************************/
158static p_u16    irq_mask                = 0xdeb8; // IRQ3,4,5,7,9,10,11,12,14,15
159static p_s8     irq_list[4]             = { -1 };
160
161
162static p_u8     PARM_AUTHENTICATION        	= PARM_DEFAULT_AUTHENTICATION;
163static p_u16    PARM_AUTH_KEY_MGMT_SUITE   	= PARM_DEFAULT_AUTH_KEY_MGMT_SUITE;
164static p_u16    PARM_BRSC_2GHZ             	= PARM_DEFAULT_BRSC_2GHZ;
165static p_u16    PARM_BRSC_5GHZ             	= PARM_DEFAULT_BRSC_5GHZ;
166static p_u16    PARM_COEXISTENCE           	= PARM_DEFAULT_COEXISTENCE;
167static p_u16    PARM_CONNECTION_CONTROL    	= PARM_DEFAULT_CONNECTION_CONTROL;  //;?rename and move
168static p_char  *PARM_CREATE_IBSS           	= PARM_DEFAULT_CREATE_IBSS_STR;
169static p_char  *PARM_DESIRED_SSID          	= PARM_DEFAULT_SSID;
170static p_char  *PARM_DOWNLOAD_FIRMWARE      = "";
171static p_u16    PARM_ENABLE_ENCRYPTION     	= PARM_DEFAULT_ENABLE_ENCRYPTION;
172static p_char  *PARM_EXCLUDE_UNENCRYPTED   	= PARM_DEFAULT_EXCLUDE_UNENCRYPTED_STR;
173static p_char  *PARM_INTRA_BSS_RELAY       	= PARM_DEFAULT_INTRA_BSS_RELAY_STR;
174static p_char  *PARM_KEY1                  	= "";
175static p_char  *PARM_KEY2                  	= "";
176static p_char  *PARM_KEY3                  	= "";
177static p_char  *PARM_KEY4                  	= "";
178static p_char  *PARM_LOAD_BALANCING        	= PARM_DEFAULT_LOAD_BALANCING_STR;
179static p_u16    PARM_MAX_SLEEP             	= PARM_DEFAULT_MAX_PM_SLEEP;
180static p_char  *PARM_MEDIUM_DISTRIBUTION   	= PARM_DEFAULT_MEDIUM_DISTRIBUTION_STR;
181static p_char  *PARM_MICROWAVE_ROBUSTNESS  	= PARM_DEFAULT_MICROWAVE_ROBUSTNESS_STR;
182static p_char  *PARM_MULTICAST_PM_BUFFERING	= PARM_DEFAULT_MULTICAST_PM_BUFFERING_STR;
183static p_u16    PARM_MULTICAST_RATE        	= PARM_DEFAULT_MULTICAST_RATE_2GHZ;
184static p_char  *PARM_MULTICAST_RX          	= PARM_DEFAULT_MULTICAST_RX_STR;
185static p_u8     PARM_NETWORK_ADDR[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
186static p_u16    PARM_OWN_ATIM_WINDOW       	= PARM_DEFAULT_OWN_ATIM_WINDOW;
187static p_u16    PARM_OWN_BEACON_INTERVAL   	= PARM_DEFAULT_OWN_BEACON_INTERVAL;
188static p_u8     PARM_OWN_CHANNEL           	= PARM_DEFAULT_OWN_CHANNEL;
189static p_u8     PARM_OWN_DTIM_PERIOD       	= PARM_DEFAULT_OWN_DTIM_PERIOD;
190static p_char  *PARM_OWN_NAME              	= PARM_DEFAULT_OWN_NAME;
191static p_char  *PARM_OWN_SSID              	= PARM_DEFAULT_SSID;
192static p_u16	PARM_PM_ENABLED            	= WVLAN_PM_STATE_DISABLED;
193static p_u16    PARM_PM_HOLDOVER_DURATION  	= PARM_DEFAULT_PM_HOLDOVER_DURATION;
194static p_u8     PARM_PORT_TYPE             	= PARM_DEFAULT_PORT_TYPE;
195static p_char  *PARM_PROMISCUOUS_MODE      	= PARM_DEFAULT_PROMISCUOUS_MODE_STR;
196static p_char  *PARM_REJECT_ANY            	= PARM_DEFAULT_REJECT_ANY_STR;
197#ifdef USE_WDS
198static p_u16    PARM_RTS_THRESHOLD1        	= PARM_DEFAULT_RTS_THRESHOLD;
199static p_u16    PARM_RTS_THRESHOLD2        	= PARM_DEFAULT_RTS_THRESHOLD;
200static p_u16    PARM_RTS_THRESHOLD3        	= PARM_DEFAULT_RTS_THRESHOLD;
201static p_u16    PARM_RTS_THRESHOLD4        	= PARM_DEFAULT_RTS_THRESHOLD;
202static p_u16    PARM_RTS_THRESHOLD5        	= PARM_DEFAULT_RTS_THRESHOLD;
203static p_u16    PARM_RTS_THRESHOLD6        	= PARM_DEFAULT_RTS_THRESHOLD;
204#endif // USE_WDS
205static p_u16    PARM_RTS_THRESHOLD         	= PARM_DEFAULT_RTS_THRESHOLD;
206static p_u16    PARM_SRSC_2GHZ             	= PARM_DEFAULT_SRSC_2GHZ;
207static p_u16    PARM_SRSC_5GHZ             	= PARM_DEFAULT_SRSC_5GHZ;
208static p_u8     PARM_SYSTEM_SCALE          	= PARM_DEFAULT_SYSTEM_SCALE;
209static p_u8     PARM_TX_KEY                	= PARM_DEFAULT_TX_KEY;
210static p_u16    PARM_TX_POW_LEVEL          	= PARM_DEFAULT_TX_POW_LEVEL;
211#ifdef USE_WDS
212static p_u16    PARM_TX_RATE1              	= PARM_DEFAULT_TX_RATE_2GHZ;
213static p_u16    PARM_TX_RATE2              	= PARM_DEFAULT_TX_RATE_2GHZ;
214static p_u16    PARM_TX_RATE3              	= PARM_DEFAULT_TX_RATE_2GHZ;
215static p_u16    PARM_TX_RATE4              	= PARM_DEFAULT_TX_RATE_2GHZ;
216static p_u16    PARM_TX_RATE5              	= PARM_DEFAULT_TX_RATE_2GHZ;
217static p_u16    PARM_TX_RATE6              	= PARM_DEFAULT_TX_RATE_2GHZ;
218#endif // USE_WDS
219static p_u16    PARM_TX_RATE               	= PARM_DEFAULT_TX_RATE_2GHZ;
220#ifdef USE_WDS
221static p_u8     PARM_WDS_ADDRESS1[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
222static p_u8     PARM_WDS_ADDRESS2[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
223static p_u8     PARM_WDS_ADDRESS3[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
224static p_u8     PARM_WDS_ADDRESS4[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
225static p_u8     PARM_WDS_ADDRESS5[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
226static p_u8     PARM_WDS_ADDRESS6[ETH_ALEN]	= PARM_DEFAULT_NETWORK_ADDR;
227#endif // USE_WDS
228
229
230
231/* END NEW PARAMETERS */
232/*******************************************************************************
233 * debugging specifics
234 ******************************************************************************/
235#if DBG
236
237static p_u32    pc_debug = DBG_LVL;
238//MODULE_PARM(pc_debug, "i");
239/*static ;?conflicts with my understanding of CL parameters and breaks now I moved
240 * the correspondig logic to wl_profile
241 */ p_u32    DebugFlag = ~0; //recognizable "undefined value" rather then DBG_DEFAULTS;
242//MODULE_PARM(DebugFlag, "l");
243
244dbg_info_t   wl_info = { DBG_MOD_NAME, 0, 0 };
245dbg_info_t  *DbgInfo = &wl_info;
246
247#endif /* DBG */
248#ifdef USE_RTS
249
250static p_char  *useRTS = "N";
251MODULE_PARM( useRTS, "s" );
252MODULE_PARM_DESC( useRTS, "Use RTS test interface (<string> N or Y) [N]" );
253
254#endif  /* USE_RTS */
255/*******************************************************************************
256 * firmware download specifics
257 ******************************************************************************/
258extern struct CFG_RANGE2_STRCT BASED
259	cfg_drv_act_ranges_pri; 	    // describes primary-actor range of HCF
260
261
262//extern memimage station;            // STA firmware image to be downloaded
263extern memimage fw_image;            // firmware image to be downloaded
264
265
266/*******************************************************************************
267 *	wl_insert()
268 *******************************************************************************
269 *
270 *  DESCRIPTION:
271 *
272 *      wl_insert() is scheduled to run after a CARD_INSERTION event is
273 *  received, to configure the PCMCIA socket, and to make the ethernet device
274 *  available to the system.
275 *
276 *  PARAMETERS:
277 *
278 *      dev - a pointer to the net_device struct of the wireless device
279 *
280 *  RETURNS:
281 *
282 *      TRUE or FALSE
283 *
284 ******************************************************************************/
285int wl_insert( struct net_device *dev )
286{
287	int                     result = 0;
288	int                     hcf_status = HCF_SUCCESS;
289	int                     i;
290	unsigned long           flags = 0;
291	struct wl_private       *lp = wl_priv(dev);
292	/*------------------------------------------------------------------------*/
293	DBG_FUNC( "wl_insert" );
294	DBG_ENTER( DbgInfo );
295
296	/* Initialize the adapter hardware. */
297	memset( &( lp->hcfCtx ), 0, sizeof( IFB_STRCT ));
298
299	/* Initialize the adapter parameters. */
300	spin_lock_init( &( lp->slock ));
301
302	/* Intialize states */
303	//lp->lockcount = 0; //PE1DNN
304        lp->is_handling_int = WL_NOT_HANDLING_INT;
305	lp->firmware_present = WL_FRIMWARE_NOT_PRESENT;
306
307	lp->dev = dev;
308
309	DBG_PARAM( DbgInfo, "irq_mask", "0x%04x", irq_mask & 0x0FFFF );
310	DBG_PARAM( DbgInfo, "irq_list", "0x%02x 0x%02x 0x%02x 0x%02x",
311			   irq_list[0] & 0x0FF, irq_list[1] & 0x0FF,
312			   irq_list[2] & 0x0FF, irq_list[3] & 0x0FF );
313	DBG_PARAM( DbgInfo, PARM_NAME_DESIRED_SSID, "\"%s\"", PARM_DESIRED_SSID );
314	DBG_PARAM( DbgInfo, PARM_NAME_OWN_SSID, "\"%s\"", PARM_OWN_SSID );
315	DBG_PARAM( DbgInfo, PARM_NAME_OWN_CHANNEL, "%d", PARM_OWN_CHANNEL);
316	DBG_PARAM( DbgInfo, PARM_NAME_SYSTEM_SCALE, "%d", PARM_SYSTEM_SCALE );
317	DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE, "%d", PARM_TX_RATE );
318	DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD, "%d", PARM_RTS_THRESHOLD );
319	DBG_PARAM( DbgInfo, PARM_NAME_MICROWAVE_ROBUSTNESS, "\"%s\"", PARM_MICROWAVE_ROBUSTNESS );
320	DBG_PARAM( DbgInfo, PARM_NAME_OWN_NAME, "\"%s\"", PARM_OWN_NAME );
321//;?		DBG_PARAM( DbgInfo, PARM_NAME_ENABLE_ENCRYPTION, "\"%s\"", PARM_ENABLE_ENCRYPTION );
322	DBG_PARAM( DbgInfo, PARM_NAME_KEY1, "\"%s\"", PARM_KEY1 );
323	DBG_PARAM( DbgInfo, PARM_NAME_KEY2, "\"%s\"", PARM_KEY2 );
324	DBG_PARAM( DbgInfo, PARM_NAME_KEY3, "\"%s\"", PARM_KEY3 );
325	DBG_PARAM( DbgInfo, PARM_NAME_KEY4, "\"%s\"", PARM_KEY4 );
326	DBG_PARAM( DbgInfo, PARM_NAME_TX_KEY, "%d", PARM_TX_KEY );
327	DBG_PARAM( DbgInfo, PARM_NAME_MULTICAST_RATE, "%d", PARM_MULTICAST_RATE );
328	DBG_PARAM( DbgInfo, PARM_NAME_DOWNLOAD_FIRMWARE, "\"%s\"", PARM_DOWNLOAD_FIRMWARE );
329	DBG_PARAM( DbgInfo, PARM_NAME_AUTH_KEY_MGMT_SUITE, "%d", PARM_AUTH_KEY_MGMT_SUITE );
330//;?#if (HCF_TYPE) & HCF_TYPE_STA
331					//;?should we make this code conditional depending on in STA mode
332//;?        DBG_PARAM( DbgInfo, PARM_NAME_PORT_TYPE, "%d", PARM_PORT_TYPE );
333		DBG_PARAM( DbgInfo, PARM_NAME_PM_ENABLED, "%04x", PARM_PM_ENABLED );
334//;?        DBG_PARAM( DbgInfo, PARM_NAME_CREATE_IBSS, "\"%s\"", PARM_CREATE_IBSS );
335//;?        DBG_PARAM( DbgInfo, PARM_NAME_MULTICAST_RX, "\"%s\"", PARM_MULTICAST_RX );
336//;?        DBG_PARAM( DbgInfo, PARM_NAME_MAX_SLEEP, "%d", PARM_MAX_SLEEP );
337//;?        DBG_PARAM( DbgInfo, PARM_NAME_NETWORK_ADDR, "\"%s\"", DbgHwAddr( PARM_NETWORK_ADDR ));
338//;?        DBG_PARAM( DbgInfo, PARM_NAME_AUTHENTICATION, "%d", PARM_AUTHENTICATION );
339//;?        DBG_PARAM( DbgInfo, PARM_NAME_OWN_ATIM_WINDOW, "%d", PARM_OWN_ATIM_WINDOW );
340//;?        DBG_PARAM( DbgInfo, PARM_NAME_PM_HOLDOVER_DURATION, "%d", PARM_PM_HOLDOVER_DURATION );
341//;?        DBG_PARAM( DbgInfo, PARM_NAME_PROMISCUOUS_MODE, "\"%s\"", PARM_PROMISCUOUS_MODE );
342//;?#endif /* HCF_STA */
343		//;?should we restore this to allow smaller memory footprint
344		//;?I guess: no, since this is Debug mode only
345	DBG_PARAM( DbgInfo, PARM_NAME_OWN_DTIM_PERIOD, "%d", PARM_OWN_DTIM_PERIOD );
346	DBG_PARAM( DbgInfo, PARM_NAME_REJECT_ANY, "\"%s\"", PARM_REJECT_ANY );
347	DBG_PARAM( DbgInfo, PARM_NAME_EXCLUDE_UNENCRYPTED, "\"%s\"", PARM_EXCLUDE_UNENCRYPTED );
348	DBG_PARAM( DbgInfo, PARM_NAME_MULTICAST_PM_BUFFERING, "\"%s\"", PARM_MULTICAST_PM_BUFFERING );
349	DBG_PARAM( DbgInfo, PARM_NAME_INTRA_BSS_RELAY, "\"%s\"", PARM_INTRA_BSS_RELAY );
350#ifdef USE_WDS
351	DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD1, "%d", PARM_RTS_THRESHOLD1 );
352	DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD2, "%d", PARM_RTS_THRESHOLD2 );
353	DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD3, "%d", PARM_RTS_THRESHOLD3 );
354	DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD4, "%d", PARM_RTS_THRESHOLD4 );
355	DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD5, "%d", PARM_RTS_THRESHOLD5 );
356	DBG_PARAM( DbgInfo, PARM_NAME_RTS_THRESHOLD6, "%d", PARM_RTS_THRESHOLD6 );
357	DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE1, "%d", PARM_TX_RATE1 );
358	DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE2, "%d", PARM_TX_RATE2 );
359	DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE3, "%d", PARM_TX_RATE3 );
360	DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE4, "%d", PARM_TX_RATE4 );
361	DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE5, "%d", PARM_TX_RATE5 );
362	DBG_PARAM( DbgInfo, PARM_NAME_TX_RATE6, "%d", PARM_TX_RATE6 );
363	DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS1, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS1 ));
364	DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS2, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS2 ));
365	DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS3, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS3 ));
366	DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS4, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS4 ));
367	DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS5, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS5 ));
368	DBG_PARAM( DbgInfo, PARM_NAME_WDS_ADDRESS6, "\"%s\"", DbgHwAddr( PARM_WDS_ADDRESS6 ));
369#endif /* USE_WDS */
370
371	VALID_PARAM( !PARM_DESIRED_SSID || ( strlen( PARM_DESIRED_SSID ) <= PARM_MAX_NAME_LEN ));
372	VALID_PARAM( !PARM_OWN_SSID || ( strlen( PARM_OWN_SSID ) <= PARM_MAX_NAME_LEN ));
373	VALID_PARAM(( PARM_OWN_CHANNEL <= PARM_MAX_OWN_CHANNEL ));
374	VALID_PARAM(( PARM_SYSTEM_SCALE >= PARM_MIN_SYSTEM_SCALE ) && ( PARM_SYSTEM_SCALE <= PARM_MAX_SYSTEM_SCALE ));
375	VALID_PARAM(( PARM_TX_RATE >= PARM_MIN_TX_RATE ) && ( PARM_TX_RATE <= PARM_MAX_TX_RATE ));
376	VALID_PARAM(( PARM_RTS_THRESHOLD <= PARM_MAX_RTS_THRESHOLD ));
377	VALID_PARAM( !PARM_MICROWAVE_ROBUSTNESS || strchr( "NnYy", PARM_MICROWAVE_ROBUSTNESS[0] ) != NULL );
378	VALID_PARAM( !PARM_OWN_NAME || ( strlen( PARM_NAME_OWN_NAME ) <= PARM_MAX_NAME_LEN ));
379	VALID_PARAM(( PARM_ENABLE_ENCRYPTION <= PARM_MAX_ENABLE_ENCRYPTION ));
380	VALID_PARAM( is_valid_key_string( PARM_KEY1 ));
381	VALID_PARAM( is_valid_key_string( PARM_KEY2 ));
382	VALID_PARAM( is_valid_key_string( PARM_KEY3 ));
383	VALID_PARAM( is_valid_key_string( PARM_KEY4 ));
384	VALID_PARAM(( PARM_TX_KEY >= PARM_MIN_TX_KEY ) && ( PARM_TX_KEY <= PARM_MAX_TX_KEY ));
385
386	VALID_PARAM(( PARM_MULTICAST_RATE >= PARM_MIN_MULTICAST_RATE ) &&
387					( PARM_MULTICAST_RATE <= PARM_MAX_MULTICAST_RATE ));
388
389	VALID_PARAM( !PARM_DOWNLOAD_FIRMWARE || ( strlen( PARM_DOWNLOAD_FIRMWARE ) <= 255 /*;?*/ ));
390	VALID_PARAM(( PARM_AUTH_KEY_MGMT_SUITE < PARM_MAX_AUTH_KEY_MGMT_SUITE ));
391
392	VALID_PARAM( !PARM_LOAD_BALANCING || strchr( "NnYy", PARM_LOAD_BALANCING[0] ) != NULL );
393	VALID_PARAM( !PARM_MEDIUM_DISTRIBUTION || strchr( "NnYy", PARM_MEDIUM_DISTRIBUTION[0] ) != NULL );
394	VALID_PARAM(( PARM_TX_POW_LEVEL <= PARM_MAX_TX_POW_LEVEL ));
395
396 	VALID_PARAM(( PARM_PORT_TYPE >= PARM_MIN_PORT_TYPE ) && ( PARM_PORT_TYPE <= PARM_MAX_PORT_TYPE ));
397	VALID_PARAM( PARM_PM_ENABLED <= WVLAN_PM_STATE_STANDARD ||
398				 ( PARM_PM_ENABLED & 0x7FFF ) <= WVLAN_PM_STATE_STANDARD );
399 	VALID_PARAM( !PARM_CREATE_IBSS || strchr( "NnYy", PARM_CREATE_IBSS[0] ) != NULL );
400 	VALID_PARAM( !PARM_MULTICAST_RX || strchr( "NnYy", PARM_MULTICAST_RX[0] ) != NULL );
401 	VALID_PARAM(( PARM_MAX_SLEEP <= PARM_MAX_MAX_PM_SLEEP ));
402 	VALID_PARAM(( PARM_AUTHENTICATION <= PARM_MAX_AUTHENTICATION ));
403 	VALID_PARAM(( PARM_OWN_ATIM_WINDOW <= PARM_MAX_OWN_ATIM_WINDOW ));
404 	VALID_PARAM(( PARM_PM_HOLDOVER_DURATION <= PARM_MAX_PM_HOLDOVER_DURATION ));
405 	VALID_PARAM( !PARM_PROMISCUOUS_MODE || strchr( "NnYy", PARM_PROMISCUOUS_MODE[0] ) != NULL );
406	VALID_PARAM(( PARM_CONNECTION_CONTROL <= PARM_MAX_CONNECTION_CONTROL ));
407
408	VALID_PARAM(( PARM_OWN_DTIM_PERIOD >= PARM_MIN_OWN_DTIM_PERIOD ));
409	VALID_PARAM( !PARM_REJECT_ANY || strchr( "NnYy", PARM_REJECT_ANY[0] ) != NULL );
410	VALID_PARAM( !PARM_EXCLUDE_UNENCRYPTED || strchr( "NnYy", PARM_EXCLUDE_UNENCRYPTED[0] ) != NULL );
411	VALID_PARAM( !PARM_MULTICAST_PM_BUFFERING || strchr( "NnYy", PARM_MULTICAST_PM_BUFFERING[0] ) != NULL );
412	VALID_PARAM( !PARM_INTRA_BSS_RELAY || strchr( "NnYy", PARM_INTRA_BSS_RELAY[0] ) != NULL );
413#ifdef USE_WDS
414	VALID_PARAM(( PARM_RTS_THRESHOLD1 <= PARM_MAX_RTS_THRESHOLD ));
415	VALID_PARAM(( PARM_RTS_THRESHOLD2 <= PARM_MAX_RTS_THRESHOLD ));
416	VALID_PARAM(( PARM_RTS_THRESHOLD3 <= PARM_MAX_RTS_THRESHOLD ));
417	VALID_PARAM(( PARM_RTS_THRESHOLD4 <= PARM_MAX_RTS_THRESHOLD ));
418	VALID_PARAM(( PARM_RTS_THRESHOLD5 <= PARM_MAX_RTS_THRESHOLD ));
419	VALID_PARAM(( PARM_RTS_THRESHOLD6 <= PARM_MAX_RTS_THRESHOLD ));
420	VALID_PARAM(( PARM_TX_RATE1 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE1 <= PARM_MAX_TX_RATE ));
421	VALID_PARAM(( PARM_TX_RATE2 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE2 <= PARM_MAX_TX_RATE ));
422	VALID_PARAM(( PARM_TX_RATE3 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE3 <= PARM_MAX_TX_RATE ));
423	VALID_PARAM(( PARM_TX_RATE4 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE4 <= PARM_MAX_TX_RATE ));
424	VALID_PARAM(( PARM_TX_RATE5 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE5 <= PARM_MAX_TX_RATE ));
425	VALID_PARAM(( PARM_TX_RATE6 >= PARM_MIN_TX_RATE ) && (PARM_TX_RATE6 <= PARM_MAX_TX_RATE ));
426#endif /* USE_WDS */
427
428	VALID_PARAM(( PARM_OWN_BEACON_INTERVAL >= PARM_MIN_OWN_BEACON_INTERVAL ) && ( PARM_OWN_BEACON_INTERVAL <= PARM_MAX_OWN_BEACON_INTERVAL ));
429	VALID_PARAM(( PARM_COEXISTENCE <= PARM_COEXISTENCE ));
430
431	/* Set the driver parameters from the passed in parameters. */
432
433	/* THESE MODULE PARAMETERS ARE TO BE DEPRECATED IN FAVOR OF A NAMING CONVENTION
434	   WHICH IS INLINE WITH THE FORTHCOMING WAVELAN API */
435
436	/* START NEW PARAMETERS */
437
438	lp->Channel             = PARM_OWN_CHANNEL;
439	lp->DistanceBetweenAPs  = PARM_SYSTEM_SCALE;
440
441	/* Need to determine how to handle the new bands for 5GHz */
442	lp->TxRateControl[0]    = PARM_DEFAULT_TX_RATE_2GHZ;
443	lp->TxRateControl[1]    = PARM_DEFAULT_TX_RATE_5GHZ;
444
445	lp->RTSThreshold        = PARM_RTS_THRESHOLD;
446
447	/* Need to determine how to handle the new bands for 5GHz */
448	lp->MulticastRate[0]    = PARM_DEFAULT_MULTICAST_RATE_2GHZ;
449	lp->MulticastRate[1]    = PARM_DEFAULT_MULTICAST_RATE_5GHZ;
450
451	if ( strchr( "Yy", PARM_MICROWAVE_ROBUSTNESS[0] ) != NULL ) {
452		lp->MicrowaveRobustness = 1;
453	} else {
454		lp->MicrowaveRobustness = 0;
455	}
456	if ( PARM_DESIRED_SSID && ( strlen( PARM_DESIRED_SSID ) <= HCF_MAX_NAME_LEN )) {
457		strcpy( lp->NetworkName, PARM_DESIRED_SSID );
458	}
459	if ( PARM_OWN_SSID && ( strlen( PARM_OWN_SSID ) <= HCF_MAX_NAME_LEN )) {
460		strcpy( lp->NetworkName, PARM_OWN_SSID );
461	}
462	if ( PARM_OWN_NAME && ( strlen( PARM_OWN_NAME ) <= HCF_MAX_NAME_LEN )) {
463		strcpy( lp->StationName, PARM_OWN_NAME );
464	}
465	lp->EnableEncryption = PARM_ENABLE_ENCRYPTION;
466	if ( PARM_KEY1 && ( strlen( PARM_KEY1 ) <= MAX_KEY_LEN )) {
467		strcpy( lp->Key1, PARM_KEY1 );
468	}
469	if ( PARM_KEY2 && ( strlen( PARM_KEY2 ) <= MAX_KEY_LEN )) {
470		strcpy( lp->Key2, PARM_KEY2 );
471	}
472	if ( PARM_KEY3 && ( strlen( PARM_KEY3 ) <= MAX_KEY_LEN )) {
473		strcpy( lp->Key3, PARM_KEY3 );
474	}
475	if ( PARM_KEY4 && ( strlen( PARM_KEY4 ) <= MAX_KEY_LEN )) {
476		strcpy( lp->Key4, PARM_KEY4 );
477	}
478
479	lp->TransmitKeyID = PARM_TX_KEY;
480
481	key_string2key( lp->Key1, &(lp->DefaultKeys.key[0] ));
482	key_string2key( lp->Key2, &(lp->DefaultKeys.key[1] ));
483	key_string2key( lp->Key3, &(lp->DefaultKeys.key[2] ));
484	key_string2key( lp->Key4, &(lp->DefaultKeys.key[3] ));
485
486	lp->DownloadFirmware = 1 ; //;?to be upgraded PARM_DOWNLOAD_FIRMWARE;
487	lp->AuthKeyMgmtSuite = PARM_AUTH_KEY_MGMT_SUITE;
488
489	if ( strchr( "Yy", PARM_LOAD_BALANCING[0] ) != NULL ) {
490		lp->loadBalancing = 1;
491	} else {
492		lp->loadBalancing = 0;
493	}
494
495	if ( strchr( "Yy", PARM_MEDIUM_DISTRIBUTION[0] ) != NULL ) {
496		lp->mediumDistribution = 1;
497	} else {
498		lp->mediumDistribution = 0;
499	}
500
501	lp->txPowLevel = PARM_TX_POW_LEVEL;
502
503	lp->srsc[0] = PARM_SRSC_2GHZ;
504	lp->srsc[1] = PARM_SRSC_5GHZ;
505	lp->brsc[0] = PARM_BRSC_2GHZ;
506	lp->brsc[1] = PARM_BRSC_5GHZ;
507//;?seems reasonable that even an AP-only driver could afford this small additional footprint
508	lp->PortType            = PARM_PORT_TYPE;
509	lp->MaxSleepDuration    = PARM_MAX_SLEEP;
510	lp->authentication      = PARM_AUTHENTICATION;
511	lp->atimWindow          = PARM_OWN_ATIM_WINDOW;
512	lp->holdoverDuration    = PARM_PM_HOLDOVER_DURATION;
513	lp->PMEnabled           = PARM_PM_ENABLED;  //;?
514	if ( strchr( "Yy", PARM_CREATE_IBSS[0] ) != NULL ) {
515		lp->CreateIBSS = 1;
516	} else {
517		lp->CreateIBSS = 0;
518	}
519	if ( strchr( "Nn", PARM_MULTICAST_RX[0] ) != NULL ) {
520		lp->MulticastReceive = 0;
521	} else {
522		lp->MulticastReceive = 1;
523	}
524	if ( strchr( "Yy", PARM_PROMISCUOUS_MODE[0] ) != NULL ) {
525		lp->promiscuousMode = 1;
526	} else {
527		lp->promiscuousMode = 0;
528	}
529	for( i = 0; i < ETH_ALEN; i++ ) {
530	   lp->MACAddress[i] = PARM_NETWORK_ADDR[i];
531	}
532
533	lp->connectionControl = PARM_CONNECTION_CONTROL;
534	//;?should we restore this to allow smaller memory footprint
535	lp->DTIMPeriod = PARM_OWN_DTIM_PERIOD;
536
537	if ( strchr( "Yy", PARM_REJECT_ANY[0] ) != NULL ) {
538		lp->RejectAny = 1;
539	} else {
540		lp->RejectAny = 0;
541	}
542	if ( strchr( "Nn", PARM_EXCLUDE_UNENCRYPTED[0] ) != NULL ) {
543		lp->ExcludeUnencrypted = 0;
544	} else {
545		lp->ExcludeUnencrypted = 1;
546	}
547	if ( strchr( "Yy", PARM_MULTICAST_PM_BUFFERING[0] ) != NULL ) {
548		lp->multicastPMBuffering = 1;
549	} else {
550		lp->multicastPMBuffering = 0;
551	}
552	if ( strchr( "Yy", PARM_INTRA_BSS_RELAY[0] ) != NULL ) {
553		lp->intraBSSRelay = 1;
554	} else {
555		lp->intraBSSRelay = 0;
556	}
557
558	lp->ownBeaconInterval = PARM_OWN_BEACON_INTERVAL;
559	lp->coexistence       = PARM_COEXISTENCE;
560
561#ifdef USE_WDS
562	lp->wds_port[0].rtsThreshold    = PARM_RTS_THRESHOLD1;
563	lp->wds_port[1].rtsThreshold    = PARM_RTS_THRESHOLD2;
564	lp->wds_port[2].rtsThreshold    = PARM_RTS_THRESHOLD3;
565	lp->wds_port[3].rtsThreshold    = PARM_RTS_THRESHOLD4;
566	lp->wds_port[4].rtsThreshold    = PARM_RTS_THRESHOLD5;
567	lp->wds_port[5].rtsThreshold    = PARM_RTS_THRESHOLD6;
568	lp->wds_port[0].txRateCntl      = PARM_TX_RATE1;
569	lp->wds_port[1].txRateCntl      = PARM_TX_RATE2;
570	lp->wds_port[2].txRateCntl      = PARM_TX_RATE3;
571	lp->wds_port[3].txRateCntl      = PARM_TX_RATE4;
572	lp->wds_port[4].txRateCntl      = PARM_TX_RATE5;
573	lp->wds_port[5].txRateCntl      = PARM_TX_RATE6;
574
575	for( i = 0; i < ETH_ALEN; i++ ) {
576		lp->wds_port[0].wdsAddress[i] = PARM_WDS_ADDRESS1[i];
577	}
578	for( i = 0; i < ETH_ALEN; i++ ) {
579		lp->wds_port[1].wdsAddress[i] = PARM_WDS_ADDRESS2[i];
580	}
581	for( i = 0; i < ETH_ALEN; i++ ) {
582		lp->wds_port[2].wdsAddress[i] = PARM_WDS_ADDRESS3[i];
583	}
584	for( i = 0; i < ETH_ALEN; i++ ) {
585		lp->wds_port[3].wdsAddress[i] = PARM_WDS_ADDRESS4[i];
586	}
587	for( i = 0; i < ETH_ALEN; i++ ) {
588		lp->wds_port[4].wdsAddress[i] = PARM_WDS_ADDRESS5[i];
589	}
590	for( i = 0; i < ETH_ALEN; i++ ) {
591		lp->wds_port[5].wdsAddress[i] = PARM_WDS_ADDRESS6[i];
592	}
593#endif  /* USE_WDS */
594#ifdef USE_RTS
595	if ( strchr( "Yy", useRTS[0] ) != NULL ) {
596		lp->useRTS = 1;
597	} else {
598		lp->useRTS = 0;
599	}
600#endif  /* USE_RTS */
601
602
603	/* END NEW PARAMETERS */
604
605
606	wl_lock( lp, &flags );
607
608	/* Initialize the portState variable */
609	lp->portState = WVLAN_PORT_STATE_DISABLED;
610
611	/* Initialize the ScanResult struct */
612	memset( &( lp->scan_results ), 0, sizeof( lp->scan_results ));
613	lp->scan_results.scan_complete = FALSE;
614
615	/* Initialize the ProbeResult struct */
616	memset( &( lp->probe_results ), 0, sizeof( lp->probe_results ));
617	lp->probe_results.scan_complete = FALSE;
618	lp->probe_num_aps = 0;
619
620
621	/* Initialize Tx queue stuff */
622	memset( lp->txList, 0, sizeof( lp->txList ));
623
624	INIT_LIST_HEAD( &( lp->txFree ));
625
626	lp->txF.skb  = NULL;
627	lp->txF.port = 0;
628
629
630	for( i = 0; i < DEFAULT_NUM_TX_FRAMES; i++ ) {
631		list_add_tail( &( lp->txList[i].node ), &( lp->txFree ));
632	}
633
634
635	for( i = 0; i < WVLAN_MAX_TX_QUEUES; i++ ) {
636		INIT_LIST_HEAD( &( lp->txQ[i] ));
637	}
638
639	lp->netif_queue_on = TRUE;
640	lp->txQ_count = 0;
641	/* Initialize the use_dma element in the adapter structure. Not sure if
642	   this should be a compile-time or run-time configurable. So for now,
643	   implement as run-time and just define here */
644#ifdef WARP
645#ifdef ENABLE_DMA
646	DBG_TRACE( DbgInfo, "HERMES 2.5 BUSMASTER DMA MODE\n" );
647	lp->use_dma = 1;
648#else
649	DBG_TRACE( DbgInfo, "HERMES 2.5 PORT I/O MODE\n" );
650	lp->use_dma = 0;
651#endif // ENABLE_DMA
652#endif // WARP
653
654	/* Register the ISR handler information here, so that it's not done
655	   repeatedly in the ISR */
656        tasklet_init(&lp->task, wl_isr_handler, (unsigned long)lp);
657
658        /* Connect to the adapter */
659        DBG_TRACE( DbgInfo, "Calling hcf_connect()...\n" );
660        hcf_status = hcf_connect( &lp->hcfCtx, dev->base_addr );
661	//HCF_ERR_INCOMP_FW is acceptable, because download must still take place
662	//HCF_ERR_INCOMP_PRI is not acceptable
663	if ( hcf_status != HCF_SUCCESS && hcf_status != HCF_ERR_INCOMP_FW ) {
664		DBG_ERROR( DbgInfo, "hcf_connect() failed, status: 0x%x\n", hcf_status );
665		wl_unlock( lp, &flags );
666		goto hcf_failed;
667	}
668
669	//;?should set HCF_version and how about driver_stat
670	lp->driverInfo.IO_address       = dev->base_addr;
671	lp->driverInfo.IO_range         = HCF_NUM_IO_PORTS;	//;?conditionally 0x40 or 0x80 seems better
672	lp->driverInfo.IRQ_number       = dev->irq;
673	lp->driverInfo.card_stat        = lp->hcfCtx.IFB_CardStat;
674	//;? what happened to frame_type
675
676	/* Fill in the driver identity structure */
677	lp->driverIdentity.len              = ( sizeof( lp->driverIdentity ) / sizeof( hcf_16 )) - 1;
678	lp->driverIdentity.typ              = CFG_DRV_IDENTITY;
679	lp->driverIdentity.comp_id          = DRV_IDENTITY;
680	lp->driverIdentity.variant          = DRV_VARIANT;
681	lp->driverIdentity.version_major    = DRV_MAJOR_VERSION;
682	lp->driverIdentity.version_minor    = DRV_MINOR_VERSION;
683
684
685	/* Start the card here - This needs to be done in order to get the
686	   MAC address for the network layer */
687	DBG_TRACE( DbgInfo, "Calling wvlan_go() to perform a card reset...\n" );
688	hcf_status = wl_go( lp );
689
690	if ( hcf_status != HCF_SUCCESS ) {
691		DBG_ERROR( DbgInfo, "wl_go() failed\n" );
692		wl_unlock( lp, &flags );
693		goto hcf_failed;
694	}
695
696	/* Certain RIDs must be set before enabling the ports */
697	wl_put_ltv_init( lp );
698
699
700	/* Fill out the MAC address information in the net_device struct */
701	memcpy( lp->dev->dev_addr, lp->MACAddress, ETH_ALEN );
702	dev->addr_len = ETH_ALEN;
703
704	lp->is_registered = TRUE;
705
706#ifdef USE_PROFILE
707	/* Parse the config file for the sake of creating WDS ports if WDS is
708	   configured there but not in the module options */
709	parse_config( dev );
710#endif  /* USE_PROFILE */
711
712	/* If we're going into AP Mode, register the "virtual" ethernet devices
713	   needed for WDS */
714	WL_WDS_NETDEV_REGISTER( lp );
715
716	/* Reset the DownloadFirmware variable in the private struct. If the
717	   config file is not used, this will not matter; if it is used, it
718	   will be reparsed in wl_open(). This is done because logic in wl_open
719	   used to check if a firmware download is needed is broken by parsing
720	   the file here; however, this parsing is needed to register WDS ports
721	   in AP mode, if they are configured */
722	lp->DownloadFirmware = WVLAN_DRV_MODE_STA; //;?download_firmware;
723
724#ifdef USE_RTS
725	if ( lp->useRTS == 1 ) {
726		DBG_TRACE( DbgInfo, "ENTERING RTS MODE...\n" );
727                wl_act_int_off( lp );
728                lp->is_handling_int = WL_NOT_HANDLING_INT; // Not handling interrupts anymore
729
730		wl_disable( lp );
731
732        	hcf_connect( &lp->hcfCtx, HCF_DISCONNECT);
733	}
734#endif  /* USE_RTS */
735
736	wl_unlock( lp, &flags );
737
738	DBG_TRACE( DbgInfo, "%s: Wireless, io_addr %#03lx, irq %d, ""mac_address ",
739			   dev->name, dev->base_addr, dev->irq );
740
741	for( i = 0; i < ETH_ALEN; i++ ) {
742		printk( "%02X%c", dev->dev_addr[i], (( i < ( ETH_ALEN-1 )) ? ':' : '\n' ));
743	}
744
745#if 0 //SCULL_USE_PROC     /* don't waste space if unused */
746	create_proc_read_entry( "wlags", 0, NULL, scull_read_procmem, dev );
747	proc_mkdir("driver/wlags49", 0);
748	proc_write("driver/wlags49/wlags49_type", write_int, &lp->wlags49_type);
749#endif /* SCULL_USE_PROC */
750
751	DBG_LEAVE( DbgInfo );
752	return result;
753
754hcf_failed:
755	wl_hcf_error( dev, hcf_status );
756
757failed:
758
759	DBG_ERROR( DbgInfo, "wl_insert() FAILED\n" );
760
761	if ( lp->is_registered == TRUE ) {
762		lp->is_registered = FALSE;
763	}
764
765	WL_WDS_NETDEV_DEREGISTER( lp );
766
767	result = -EFAULT;
768
769
770	DBG_LEAVE( DbgInfo );
771	return result;
772} // wl_insert
773/*============================================================================*/
774
775
776/*******************************************************************************
777 *	wl_reset()
778 *******************************************************************************
779 *
780 *  DESCRIPTION:
781 *
782 *      Reset the adapter.
783 *
784 *  PARAMETERS:
785 *
786 *      dev - a pointer to the net_device struct of the wireless device
787 *
788 *  RETURNS:
789 *
790 *      an HCF status code
791 *
792 ******************************************************************************/
793int wl_reset(struct net_device *dev)
794{
795	struct wl_private  *lp = wl_priv(dev);
796	int                 hcf_status = HCF_SUCCESS;
797	/*------------------------------------------------------------------------*/
798	DBG_FUNC( "wl_reset" );
799	DBG_ENTER( DbgInfo );
800	DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
801	DBG_PARAM( DbgInfo, "dev->base_addr", "(%#03lx)", dev->base_addr );
802
803	/*
804         * The caller should already have a lock and
805         * disable the interrupts, we do not lock here,
806         * nor do we enable/disable interrupts!
807         */
808
809	DBG_TRACE( DbgInfo, "Device Base Address: %#03lx\n", dev->base_addr );
810	if ( dev->base_addr ) {
811		/* Shutdown the adapter. */
812		hcf_connect( &lp->hcfCtx, HCF_DISCONNECT );
813
814		/* Reset the driver information. */
815		lp->txBytes = 0;
816
817		/* Connect to the adapter. */
818        	hcf_status = hcf_connect( &lp->hcfCtx, dev->base_addr );
819		if ( hcf_status != HCF_SUCCESS && hcf_status != HCF_ERR_INCOMP_FW ) {
820			DBG_ERROR( DbgInfo, "hcf_connect() failed, status: 0x%x\n", hcf_status );
821			goto out;
822		}
823
824		/* Check if firmware is present, if not change state */
825		if ( hcf_status == HCF_ERR_INCOMP_FW ) {
826			lp->firmware_present = WL_FRIMWARE_NOT_PRESENT;
827		}
828
829		/* Initialize the portState variable */
830		lp->portState = WVLAN_PORT_STATE_DISABLED;
831
832		/* Restart the adapter. */
833		hcf_status = wl_go( lp );
834		if ( hcf_status != HCF_SUCCESS ) {
835			DBG_ERROR( DbgInfo, "wl_go() failed, status: 0x%x\n", hcf_status );
836			goto out;
837		}
838
839		/* Certain RIDs must be set before enabling the ports */
840		wl_put_ltv_init( lp );
841	} else {
842		DBG_ERROR( DbgInfo, "Device Base Address INVALID!!!\n" );
843	}
844
845out:
846	DBG_LEAVE( DbgInfo );
847	return hcf_status;
848} // wl_reset
849/*============================================================================*/
850
851
852/*******************************************************************************
853 *	wl_go()
854 *******************************************************************************
855 *
856 *  DESCRIPTION:
857 *
858 *      Reset the adapter.
859 *
860 *  PARAMETERS:
861 *
862 *      dev - a pointer to the net_device struct of the wireless device
863 *
864 *  RETURNS:
865 *
866 *      an HCF status code
867 *
868 ******************************************************************************/
869int wl_go( struct wl_private *lp )
870{
871	int  	hcf_status = HCF_SUCCESS;
872	char	*cp = NULL;			//fw_image
873	int	retries = 0;
874	/*------------------------------------------------------------------------*/
875	DBG_FUNC( "wl_go" );
876	DBG_ENTER( DbgInfo );
877
878	hcf_status = wl_disable( lp );
879	if ( hcf_status != HCF_SUCCESS ) {
880		DBG_TRACE( DbgInfo, "Disable port 0 failed: 0x%x\n", hcf_status );
881
882		while (( hcf_status != HCF_SUCCESS ) && (retries < 10)) {
883			retries++;
884			hcf_status = wl_disable( lp );
885		}
886		if ( hcf_status == HCF_SUCCESS ) {
887			DBG_TRACE( DbgInfo, "Disable port 0 succes : %d retries\n", retries );
888		} else {
889			DBG_TRACE( DbgInfo, "Disable port 0 failed after: %d retries\n", retries );
890		}
891	}
892
893	//DBG_TRACE( DbgInfo, "Disabling WDS Ports\n" );
894	//wl_disable_wds_ports( lp );
895
896//;?what was the purpose of this
897// 	/* load the appropriate firmware image, depending on driver mode */
898// 	lp->ltvRecord.len   = ( sizeof( CFG_RANGE20_STRCT ) / sizeof( hcf_16 )) - 1;
899// 	lp->ltvRecord.typ   = CFG_DRV_ACT_RANGES_PRI;
900// 	hcf_get_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
901
902#if BIN_DL
903	if ( strlen( lp->fw_image_filename ) ) {
904mm_segment_t	fs;
905int		    	file_desc;
906int 			rc;
907
908		DBG_TRACE( DbgInfo, "F/W image:%s:\n", lp->fw_image_filename );
909		/* Obtain a user-space process context, storing the original context */
910		fs = get_fs( );
911		set_fs( get_ds( ));
912		file_desc = open( lp->fw_image_filename, O_RDONLY, 0 );
913		if ( file_desc == -1 ) {
914			DBG_ERROR( DbgInfo, "No image file found\n" );
915		} else {
916			DBG_TRACE( DbgInfo, "F/W image file found\n" );
917#define DHF_ALLOC_SIZE 96000			//just below 96K, let's hope it suffices for now and for the future
918			cp = (char*)vmalloc( DHF_ALLOC_SIZE );
919			if ( cp == NULL ) {
920				DBG_ERROR( DbgInfo, "error in vmalloc\n" );
921			} else {
922				rc = read( file_desc, cp, DHF_ALLOC_SIZE );
923				if ( rc == DHF_ALLOC_SIZE ) {
924					DBG_ERROR( DbgInfo, "buffer too small, %d\n", DHF_ALLOC_SIZE );
925				} else if ( rc > 0 ) {
926					DBG_TRACE( DbgInfo, "read O.K.: %d bytes  %.12s\n", rc, cp );
927					rc = read( file_desc, &cp[rc], 1 );
928					if ( rc == 0 ) { //;/change to an until-loop at rc<=0
929						DBG_TRACE( DbgInfo, "no more to read\n" );
930					}
931				}
932				if ( rc != 0 ) {
933					DBG_ERROR( DbgInfo, "file not read in one swoop or other error"\
934										", give up, too complicated, rc = %0X\n", rc );
935					DBG_ERROR( DbgInfo, "still have to change code to get a real download now !!!!!!!!\n" );
936				} else {
937					DBG_TRACE( DbgInfo, "before dhf_download_binary\n" );
938					hcf_status = dhf_download_binary( (memimage *)cp );
939					DBG_TRACE( DbgInfo, "after dhf_download_binary, before dhf_download_fw\n" );
940					//;?improve error flow/handling
941					hcf_status = dhf_download_fw( &lp->hcfCtx, (memimage *)cp );
942					DBG_TRACE( DbgInfo, "after dhf_download_fw\n" );
943				}
944				vfree( cp );
945			}
946			close( file_desc );
947		}
948		set_fs( fs );			/* Return to the original context */
949	}
950#endif // BIN_DL
951
952	/* If firmware is present but the type is unknown then download anyway */
953	if ( (lp->firmware_present == WL_FRIMWARE_PRESENT)
954	     &&
955	     ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) != COMP_ID_FW_STA )
956	     &&
957	     ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) != COMP_ID_FW_AP ) ) {
958		/* Unknown type, download needed.  */
959		lp->firmware_present = WL_FRIMWARE_NOT_PRESENT;
960	}
961
962	if(lp->firmware_present == WL_FRIMWARE_NOT_PRESENT)
963	{
964		if ( cp == NULL ) {
965			DBG_TRACE( DbgInfo, "Downloading STA firmware...\n" );
966//			hcf_status = dhf_download_fw( &lp->hcfCtx, &station );
967			hcf_status = dhf_download_fw( &lp->hcfCtx, &fw_image );
968		}
969		if ( hcf_status != HCF_SUCCESS ) {
970			DBG_ERROR( DbgInfo, "Firmware Download failed\n" );
971			DBG_LEAVE( DbgInfo );
972			return hcf_status;
973		}
974	}
975	/* Report the FW versions */
976	//;?obsolete, use the available IFB info:: wl_get_pri_records( lp );
977	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA  ) {
978		DBG_TRACE( DbgInfo, "downloaded station F/W\n" );
979	} else if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
980		DBG_TRACE( DbgInfo, "downloaded AP F/W\n" );
981	} else {
982		DBG_ERROR( DbgInfo, "unknown F/W type\n" );
983	}
984
985	/*
986         * Downloaded, no need to repeat this next time, assume the
987         * contents stays in the card until it is powered off. Note we
988         * do not switch firmware on the fly, the firmware is fixed in
989         * the driver for now.
990         */
991	lp->firmware_present = WL_FRIMWARE_PRESENT;
992
993	DBG_TRACE( DbgInfo, "ComponentID:%04x variant:%04x major:%04x minor:%04x\n",
994				CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ),
995				CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.variant ),
996				CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.version_major ),
997				CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.version_minor ));
998
999	/* now we wil get the MAC address of the card */
1000	lp->ltvRecord.len = 4;
1001	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
1002		lp->ltvRecord.typ = CFG_NIC_MAC_ADDR;
1003	} else
1004	{
1005		lp->ltvRecord.typ = CFG_CNF_OWN_MAC_ADDR;
1006	}
1007	hcf_status = hcf_get_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1008	if ( hcf_status != HCF_SUCCESS ) {
1009		DBG_ERROR( DbgInfo, "Could not retrieve MAC address\n" );
1010		DBG_LEAVE( DbgInfo );
1011		return hcf_status;
1012	}
1013	memcpy( lp->MACAddress, &lp->ltvRecord.u.u8[0], ETH_ALEN );
1014	DBG_TRACE( DbgInfo, "Card MAC Address: %s\n", DbgHwAddr( lp->MACAddress ));
1015
1016	/* Write out configuration to the device, enable, and reconnect. However,
1017	   only reconnect if in AP mode. For STA mode, need to wait for passive scan
1018	   completion before a connect can be issued */
1019	wl_put_ltv( lp );
1020	/* Enable the ports */
1021	hcf_status = wl_enable( lp );
1022
1023	if ( lp->DownloadFirmware == WVLAN_DRV_MODE_AP ) {
1024#ifdef USE_WDS
1025		wl_enable_wds_ports( lp );
1026#endif // USE_WDS
1027		hcf_status = wl_connect( lp );
1028	}
1029	DBG_LEAVE( DbgInfo );
1030	return hcf_status;
1031} // wl_go
1032/*============================================================================*/
1033
1034
1035/*******************************************************************************
1036 *	wl_set_wep_keys()
1037 *******************************************************************************
1038 *
1039 *  DESCRIPTION:
1040 *
1041 *      Write TxKeyID and WEP keys to the adapter. This is separated from
1042 *  wl_apply() to allow dynamic WEP key updates through the wireless
1043 *  extensions.
1044 *
1045 *  PARAMETERS:
1046 *
1047 *      lp  - a pointer to the wireless adapter's private structure
1048 *
1049 *  RETURNS:
1050 *
1051 *      N/A
1052 *
1053 ******************************************************************************/
1054void wl_set_wep_keys( struct wl_private *lp )
1055{
1056	int count = 0;
1057	/*------------------------------------------------------------------------*/
1058	DBG_FUNC( "wl_set_wep_keys" );
1059	DBG_ENTER( DbgInfo );
1060	DBG_PARAM( DbgInfo, "lp", "%s (0x%p)", lp->dev->name, lp );
1061	if ( lp->EnableEncryption ) {
1062		/* NOTE: CFG_CNF_ENCRYPTION is set in wl_put_ltv() as it's a static
1063				 RID */
1064
1065		/* set TxKeyID */
1066		lp->ltvRecord.len = 2;
1067		lp->ltvRecord.typ       = CFG_TX_KEY_ID;
1068		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE(lp->TransmitKeyID - 1);
1069
1070		hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1071
1072		DBG_TRACE( DbgInfo, "Key 1 len: %d\n", lp->DefaultKeys.key[0].len );
1073		DBG_TRACE( DbgInfo, "Key 2 len: %d\n", lp->DefaultKeys.key[1].len );
1074		DBG_TRACE( DbgInfo, "Key 3 len: %d\n", lp->DefaultKeys.key[2].len );
1075		DBG_TRACE( DbgInfo, "Key 4 len: %d\n", lp->DefaultKeys.key[3].len );
1076
1077		/* write keys */
1078		lp->DefaultKeys.len = sizeof( lp->DefaultKeys ) / sizeof( hcf_16 ) - 1;
1079		lp->DefaultKeys.typ = CFG_DEFAULT_KEYS;
1080
1081		/* endian translate the appropriate key information */
1082		for( count = 0; count < MAX_KEYS; count++ ) {
1083			lp->DefaultKeys.key[count].len = CNV_INT_TO_LITTLE( lp->DefaultKeys.key[count].len );
1084		}
1085
1086		hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->DefaultKeys ));
1087
1088		/* Reverse the above endian translation, since these keys are accessed
1089		   elsewhere */
1090		for( count = 0; count < MAX_KEYS; count++ ) {
1091			lp->DefaultKeys.key[count].len = CNV_INT_TO_LITTLE( lp->DefaultKeys.key[count].len );
1092		}
1093
1094		DBG_NOTICE( DbgInfo, "encrypt: %d, ID: %d\n", lp->EnableEncryption, lp->TransmitKeyID );
1095		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 );
1096	}
1097
1098	DBG_LEAVE( DbgInfo );
1099} // wl_set_wep_keys
1100/*============================================================================*/
1101
1102
1103/*******************************************************************************
1104 *	wl_apply()
1105 *******************************************************************************
1106 *
1107 *  DESCRIPTION:
1108 *
1109 *      Write the parameters to the adapter. (re-)enables the card if device is
1110 *  open. Returns hcf_status of hcf_enable().
1111 *
1112 *  PARAMETERS:
1113 *
1114 *      lp  - a pointer to the wireless adapter's private structure
1115 *
1116 *  RETURNS:
1117 *
1118 *      an HCF status code
1119 *
1120 ******************************************************************************/
1121int wl_apply(struct wl_private *lp)
1122{
1123	int hcf_status = HCF_SUCCESS;
1124	/*------------------------------------------------------------------------*/
1125	DBG_FUNC( "wl_apply" );
1126	DBG_ENTER( DbgInfo );
1127	DBG_ASSERT( lp != NULL);
1128	DBG_PARAM( DbgInfo, "lp", "%s (0x%p)", lp->dev->name, lp );
1129
1130	if ( !( lp->flags & WVLAN2_UIL_BUSY )) {
1131		/* The adapter parameters have changed:
1132				disable card
1133				reload parameters
1134				enable card
1135		*/
1136
1137		if ( wl_adapter_is_open( lp->dev )) {
1138			/* Disconnect and disable if necessary */
1139			hcf_status = wl_disconnect( lp );
1140			if ( hcf_status != HCF_SUCCESS ) {
1141				DBG_ERROR( DbgInfo, "Disconnect failed\n" );
1142				DBG_LEAVE( DbgInfo );
1143				return -1;
1144			}
1145			hcf_status = wl_disable( lp );
1146			if ( hcf_status != HCF_SUCCESS ) {
1147				DBG_ERROR( DbgInfo, "Disable failed\n" );
1148				DBG_LEAVE( DbgInfo );
1149				return -1;
1150			} else {
1151				/* Write out configuration to the device, enable, and reconnect.
1152				   However, only reconnect if in AP mode. For STA mode, need to
1153				   wait for passive scan completion before a connect can be
1154				   issued */
1155				hcf_status = wl_put_ltv( lp );
1156
1157				if ( hcf_status == HCF_SUCCESS ) {
1158					hcf_status = wl_enable( lp );
1159
1160					if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
1161						hcf_status = wl_connect( lp );
1162					}
1163				} else {
1164					DBG_WARNING( DbgInfo, "wl_put_ltv() failed\n" );
1165				}
1166			}
1167		}
1168	}
1169
1170	DBG_LEAVE( DbgInfo );
1171	return hcf_status;
1172} // wl_apply
1173/*============================================================================*/
1174
1175
1176/*******************************************************************************
1177 *	wl_put_ltv_init()
1178 *******************************************************************************
1179 *
1180 *  DESCRIPTION:
1181 *
1182 *      Used to set basic parameters for card initialization.
1183 *
1184 *  PARAMETERS:
1185 *
1186 *      lp  - a pointer to the wireless adapter's private structure
1187 *
1188 *  RETURNS:
1189 *
1190 *      an HCF status code
1191 *
1192 ******************************************************************************/
1193int wl_put_ltv_init( struct wl_private *lp )
1194{
1195	int i;
1196	int hcf_status;
1197	CFG_RID_LOG_STRCT *RidLog;
1198	/*------------------------------------------------------------------------*/
1199	DBG_FUNC( "wl_put_ltv_init" );
1200	DBG_ENTER( DbgInfo );
1201	if ( lp == NULL ) {
1202		DBG_ERROR( DbgInfo, "lp pointer is NULL\n" );
1203		DBG_LEAVE( DbgInfo );
1204		return -1;
1205	}
1206	/* DMA/IO */
1207	lp->ltvRecord.len = 2;
1208	lp->ltvRecord.typ = CFG_CNTL_OPT;
1209
1210	/* The Card Services build must ALWAYS configure for 16-bit I/O. PCI or
1211	   CardBus can be set to either 16/32 bit I/O, or Bus Master DMA, but only
1212	   for Hermes-2.5 */
1213#ifdef BUS_PCMCIA
1214	lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( USE_16BIT );
1215#else
1216	if ( lp->use_dma ) {
1217		lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( USE_DMA );
1218	} else {
1219		lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE( 0 );
1220	}
1221
1222#endif
1223	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1224	DBG_TRACE( DbgInfo, "CFG_CNTL_OPT                      : 0x%04x\n",
1225			   lp->ltvRecord.u.u16[0] );
1226	DBG_TRACE( DbgInfo, "CFG_CNTL_OPT result               : 0x%04x\n",
1227			   hcf_status );
1228
1229	/* Register the list of RIDs on which asynchronous notification is
1230	   required. Note that this mechanism replaces the mailbox, so the mailbox
1231	   can be queried by the host (if desired) without contention from us */
1232	i=0;
1233
1234	lp->RidList[i].len     = sizeof( lp->ProbeResp );
1235	lp->RidList[i].typ     = CFG_ACS_SCAN;
1236	lp->RidList[i].bufp    = (wci_recordp)&lp->ProbeResp;
1237	//lp->ProbeResp.infoType = 0xFFFF;
1238	i++;
1239
1240	lp->RidList[i].len     = sizeof( lp->assoc_stat );
1241	lp->RidList[i].typ     = CFG_ASSOC_STAT;
1242	lp->RidList[i].bufp    = (wci_recordp)&lp->assoc_stat;
1243	lp->assoc_stat.len     = 0xFFFF;
1244	i++;
1245
1246	lp->RidList[i].len     = 4;
1247	lp->RidList[i].typ     = CFG_UPDATED_INFO_RECORD;
1248	lp->RidList[i].bufp    = (wci_recordp)&lp->updatedRecord;
1249	lp->updatedRecord.len  = 0xFFFF;
1250	i++;
1251
1252	lp->RidList[i].len     = sizeof( lp->sec_stat );
1253	lp->RidList[i].typ     = CFG_SECURITY_STAT;
1254	lp->RidList[i].bufp    = (wci_recordp)&lp->sec_stat;
1255	lp->sec_stat.len       = 0xFFFF;
1256	i++;
1257
1258	lp->RidList[i].typ     = 0;    // Terminate List
1259
1260	RidLog = (CFG_RID_LOG_STRCT *)&lp->ltvRecord;
1261	RidLog->len     = 3;
1262	RidLog->typ     = CFG_REG_INFO_LOG;
1263	RidLog->recordp = (RID_LOGP)&lp->RidList[0];
1264
1265	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1266	DBG_TRACE( DbgInfo, "CFG_REG_INFO_LOG\n" );
1267	DBG_TRACE( DbgInfo, "CFG_REG_INFO_LOG result           : 0x%04x\n",
1268			   hcf_status );
1269	DBG_LEAVE( DbgInfo );
1270	return hcf_status;
1271} // wl_put_ltv_init
1272/*============================================================================*/
1273
1274
1275/*******************************************************************************
1276 *	wl_put_ltv()
1277 *******************************************************************************
1278 *
1279 *  DESCRIPTION:
1280 *
1281 *      Used by wvlan_apply() and wvlan_go to set the card's configuration.
1282 *
1283 *  PARAMETERS:
1284 *
1285 *      lp  - a pointer to the wireless adapter's private structure
1286 *
1287 *  RETURNS:
1288 *
1289 *      an HCF status code
1290 *
1291 ******************************************************************************/
1292int wl_put_ltv( struct wl_private *lp )
1293{
1294	int len;
1295	int hcf_status;
1296	/*------------------------------------------------------------------------*/
1297	DBG_FUNC( "wl_put_ltv" );
1298	DBG_ENTER( DbgInfo );
1299
1300	if ( lp == NULL ) {
1301		DBG_ERROR( DbgInfo, "lp pointer is NULL\n" );
1302		return -1;
1303	}
1304	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
1305		lp->maxPort = 6;			//;?why set this here and not as part of download process
1306	} else {
1307		lp->maxPort = 0;
1308	}
1309
1310	/* Send our configuration to the card. Perform any endian translation
1311	   necessary */
1312	/* Register the Mailbox; VxWorks does this elsewhere; why;? */
1313	lp->ltvRecord.len       = 4;
1314	lp->ltvRecord.typ       = CFG_REG_MB;
1315	lp->ltvRecord.u.u32[0]  = (u_long)&( lp->mailbox );
1316	lp->ltvRecord.u.u16[2]  = ( MB_SIZE / sizeof( hcf_16 ));
1317	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1318
1319	/* Max Data Length */
1320	lp->ltvRecord.len       = 2;
1321	lp->ltvRecord.typ       = CFG_CNF_MAX_DATA_LEN;
1322	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( HCF_MAX_PACKET_SIZE );
1323	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1324
1325	/* System Scale / Distance between APs */
1326	lp->ltvRecord.len       = 2;
1327	lp->ltvRecord.typ       = CFG_CNF_SYSTEM_SCALE;
1328	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->DistanceBetweenAPs );
1329	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1330
1331	/* Channel */
1332	if ( lp->CreateIBSS && ( lp->Channel == 0 )) {
1333		DBG_TRACE( DbgInfo, "Create IBSS" );
1334		lp->Channel = 10;
1335	}
1336	lp->ltvRecord.len       = 2;
1337	lp->ltvRecord.typ       = CFG_CNF_OWN_CHANNEL;
1338	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->Channel );
1339	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1340
1341	/* Microwave Robustness */
1342	lp->ltvRecord.len       = 2;
1343	lp->ltvRecord.typ       = CFG_CNF_MICRO_WAVE;
1344	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->MicrowaveRobustness );
1345	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1346
1347	/* Load Balancing */
1348	lp->ltvRecord.len       = 2;
1349	lp->ltvRecord.typ       = CFG_CNF_LOAD_BALANCING;
1350	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->loadBalancing );
1351	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1352
1353	/* Medium Distribution */
1354	lp->ltvRecord.len       = 2;
1355	lp->ltvRecord.typ       = CFG_CNF_MEDIUM_DISTRIBUTION;
1356	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->mediumDistribution );
1357	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1358	/* Country Code */
1359
1360#ifdef WARP
1361	/* Tx Power Level (for supported cards) */
1362	lp->ltvRecord.len       = 2;
1363	lp->ltvRecord.typ       = CFG_CNF_TX_POW_LVL;
1364	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->txPowLevel );
1365	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1366
1367	/* Short Retry Limit */
1368	/*lp->ltvRecord.len       = 2;
1369	lp->ltvRecord.typ       = 0xFC32;
1370	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->shortRetryLimit );
1371	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1372	*/
1373
1374	/* Long Retry Limit */
1375	/*lp->ltvRecord.len       = 2;
1376	lp->ltvRecord.typ       = 0xFC33;
1377	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->longRetryLimit );
1378	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1379	*/
1380
1381	/* Supported Rate Set Control */
1382	lp->ltvRecord.len       = 3;
1383	lp->ltvRecord.typ       = CFG_SUPPORTED_RATE_SET_CNTL; //0xFC88;
1384	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->srsc[0] );
1385	lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( lp->srsc[1] );
1386	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1387
1388	/* Basic Rate Set Control */
1389	lp->ltvRecord.len       = 3;
1390	lp->ltvRecord.typ       = CFG_BASIC_RATE_SET_CNTL; //0xFC89;
1391	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->brsc[0] );
1392	lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( lp->brsc[1] );
1393	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1394
1395	/* Frame Burst Limit */
1396	/* Defined, but not currently available in Firmware */
1397
1398#endif // WARP
1399
1400#ifdef WARP
1401	/* Multicast Rate */
1402	lp->ltvRecord.len       = 3;
1403	lp->ltvRecord.typ       = CFG_CNF_MCAST_RATE;
1404	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->MulticastRate[0] );
1405	lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( lp->MulticastRate[1] );
1406#else
1407	lp->ltvRecord.len       = 2;
1408	lp->ltvRecord.typ       = CFG_CNF_MCAST_RATE;
1409	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->MulticastRate[0] );
1410#endif // WARP
1411	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1412
1413	/* Own Name (Station Nickname) */
1414	if (( len = ( strlen( lp->StationName ) + 1 ) & ~0x01 ) != 0 ) {
1415		//DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME                  : %s\n",
1416		//           lp->StationName );
1417
1418		lp->ltvRecord.len       = 2 + ( len / sizeof( hcf_16 ));
1419		lp->ltvRecord.typ       = CFG_CNF_OWN_NAME;
1420		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( strlen( lp->StationName ));
1421
1422		memcpy( &( lp->ltvRecord.u.u8[2] ), lp->StationName, len );
1423	} else {
1424		//DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME                  : EMPTY\n" );
1425
1426		lp->ltvRecord.len       = 2;
1427		lp->ltvRecord.typ       = CFG_CNF_OWN_NAME;
1428		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0 );
1429	}
1430
1431	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1432
1433	//DBG_TRACE( DbgInfo, "CFG_CNF_OWN_NAME result           : 0x%04x\n",
1434	//           hcf_status );
1435
1436	/* The following are set in STA mode only */
1437	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA  ) {
1438
1439		/* RTS Threshold */
1440		lp->ltvRecord.len       = 2;
1441		lp->ltvRecord.typ       = CFG_RTS_THRH;
1442		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->RTSThreshold );
1443		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1444
1445		/* Port Type */
1446		lp->ltvRecord.len       = 2;
1447		lp->ltvRecord.typ       = CFG_CNF_PORT_TYPE;
1448		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->PortType );
1449		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1450
1451		/* Tx Rate Control */
1452#ifdef WARP
1453		lp->ltvRecord.len       = 3;
1454		lp->ltvRecord.typ       = CFG_TX_RATE_CNTL;
1455		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->TxRateControl[0] );
1456		lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( lp->TxRateControl[1] );
1457#else
1458		lp->ltvRecord.len       = 2;
1459		lp->ltvRecord.typ       = CFG_TX_RATE_CNTL;
1460		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->TxRateControl[0] );
1461#endif  // WARP
1462
1463//;?skip temporarily to see whether the RID or something else is the probelm hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1464
1465		DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL 2.4GHz           : 0x%04x\n",
1466				   lp->TxRateControl[0] );
1467		DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL 5.0GHz           : 0x%04x\n",
1468				   lp->TxRateControl[1] );
1469		DBG_TRACE( DbgInfo, "CFG_TX_RATE_CNTL result           : 0x%04x\n",
1470				   hcf_status );
1471		/* Power Management */
1472		lp->ltvRecord.len       = 2;
1473		lp->ltvRecord.typ       = CFG_CNF_PM_ENABLED;
1474		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->PMEnabled );
1475//		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0x8001 );
1476		DBG_TRACE( DbgInfo, "CFG_CNF_PM_ENABLED                : 0x%04x\n", lp->PMEnabled );
1477		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1478		/* Multicast Receive */
1479		lp->ltvRecord.len       = 2;
1480		lp->ltvRecord.typ       = CFG_CNF_MCAST_RX;
1481		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->MulticastReceive );
1482		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1483
1484		/* Max Sleep Duration */
1485		lp->ltvRecord.len       = 2;
1486		lp->ltvRecord.typ       = CFG_CNF_MAX_SLEEP_DURATION;
1487		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->MaxSleepDuration );
1488		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1489
1490		/* Create IBSS */
1491		lp->ltvRecord.len       = 2;
1492		lp->ltvRecord.typ       = CFG_CREATE_IBSS;
1493		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->CreateIBSS );
1494		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1495
1496		/* Desired SSID */
1497		if ((( len = ( strlen( lp->NetworkName ) + 1 ) & ~0x01 ) != 0 ) &&
1498			 ( strcmp( lp->NetworkName, "ANY" ) != 0 ) &&
1499			 ( strcmp( lp->NetworkName, "any" ) != 0 )) {
1500			//DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID                  : %s\n",
1501			//           lp->NetworkName );
1502
1503			lp->ltvRecord.len       = 2 + (len / sizeof(hcf_16));
1504			lp->ltvRecord.typ       = CFG_DESIRED_SSID;
1505			lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( strlen( lp->NetworkName ));
1506
1507			memcpy( &( lp->ltvRecord.u.u8[2] ), lp->NetworkName, len );
1508		} else {
1509			//DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID                  : ANY\n" );
1510
1511			lp->ltvRecord.len       = 2;
1512			lp->ltvRecord.typ       = CFG_DESIRED_SSID;
1513			lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0 );
1514		}
1515
1516		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1517
1518		//DBG_TRACE( DbgInfo, "CFG_DESIRED_SSID result           : 0x%04x\n",
1519		//           hcf_status );
1520		/* Own ATIM window */
1521		lp->ltvRecord.len       = 2;
1522		lp->ltvRecord.typ       = CFG_CNF_OWN_ATIM_WINDOW;
1523		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->atimWindow );
1524		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1525
1526
1527		/* Holdover Duration */
1528		lp->ltvRecord.len       = 2;
1529		lp->ltvRecord.typ       = CFG_CNF_HOLDOVER_DURATION;
1530		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->holdoverDuration );
1531		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1532
1533		/* Promiscuous Mode */
1534		lp->ltvRecord.len       = 2;
1535		lp->ltvRecord.typ       = CFG_PROMISCUOUS_MODE;
1536		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->promiscuousMode );
1537		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1538
1539		/* Authentication */
1540		lp->ltvRecord.len       = 2;
1541		lp->ltvRecord.typ       = CFG_CNF_AUTHENTICATION;
1542		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->authentication );
1543		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1544#ifdef WARP
1545		/* Connection Control */
1546		lp->ltvRecord.len       = 2;
1547		lp->ltvRecord.typ       = CFG_CNF_CONNECTION_CNTL;
1548		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->connectionControl );
1549		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1550
1551
1552
1553		/* Probe data rate */
1554		/*lp->ltvRecord.len       = 3;
1555		lp->ltvRecord.typ       = CFG_PROBE_DATA_RATE;
1556		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->probeDataRates[0] );
1557		lp->ltvRecord.u.u16[1]  = CNV_INT_TO_LITTLE( lp->probeDataRates[1] );
1558		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1559
1560		DBG_TRACE( DbgInfo, "CFG_PROBE_DATA_RATE 2.4GHz        : 0x%04x\n",
1561				   lp->probeDataRates[0] );
1562		DBG_TRACE( DbgInfo, "CFG_PROBE_DATA_RATE 5.0GHz        : 0x%04x\n",
1563				   lp->probeDataRates[1] );
1564		DBG_TRACE( DbgInfo, "CFG_PROBE_DATA_RATE result        : 0x%04x\n",
1565				   hcf_status );*/
1566#endif // WARP
1567	} else {
1568		/* The following are set in AP mode only */
1569	}
1570
1571	/* Own MAC Address */
1572	//DBG_TRACE( DbgInfo, "MAC Address                       : %s\n",
1573	//           DbgHwAddr( lp->MACAddress ));
1574
1575	if ( WVLAN_VALID_MAC_ADDRESS( lp->MACAddress )) {
1576		/* Make the MAC address valid by:
1577				Clearing the multicast bit
1578				Setting the local MAC address bit
1579		*/
1580		//lp->MACAddress[0] &= ~0x03;  //;?why is this commented out already in 720
1581		//lp->MACAddress[0] |= 0x02;
1582
1583		lp->ltvRecord.len = 1 + ( ETH_ALEN / sizeof( hcf_16 ));
1584		if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
1585			//DBG_TRACE( DbgInfo, "CFG_NIC_MAC_ADDR\n" );
1586			lp->ltvRecord.typ = CFG_NIC_MAC_ADDR;
1587		} else {
1588			//DBG_TRACE( DbgInfo, "CFG_CNF_OWN_MAC_ADDR\n" );
1589			lp->ltvRecord.typ = CFG_CNF_OWN_MAC_ADDR;
1590		}
1591		/* MAC address is byte aligned, no endian conversion needed */
1592		memcpy( &( lp->ltvRecord.u.u8[0] ), lp->MACAddress, ETH_ALEN );
1593		hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1594		//DBG_TRACE( DbgInfo, "CFG_XXX_MAC_ADDR result           : 0x%04x\n",
1595		//           hcf_status );
1596
1597		/* Update the MAC address in the netdevice struct */
1598		memcpy( lp->dev->dev_addr, lp->MACAddress, ETH_ALEN ); //;?what is the purpose of this seemingly complex logic
1599	}
1600	/* Own SSID */
1601	if ((( len = ( strlen( lp->NetworkName ) + 1 ) & ~0x01 ) != 0 ) &&
1602				 ( strcmp( lp->NetworkName, "ANY" ) != 0 ) &&
1603				 ( strcmp( lp->NetworkName, "any" ) != 0 )) {
1604		//DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID                  : %s\n",
1605		//           lp->NetworkName );
1606		lp->ltvRecord.len       = 2 + (len / sizeof(hcf_16));
1607		lp->ltvRecord.typ       = CFG_CNF_OWN_SSID;
1608		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( strlen( lp->NetworkName ));
1609
1610		memcpy( &( lp->ltvRecord.u.u8[2] ), lp->NetworkName, len );
1611	} else {
1612		//DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID                  : ANY\n" );
1613		lp->ltvRecord.len       = 2;
1614		lp->ltvRecord.typ       = CFG_CNF_OWN_SSID;
1615		lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0 );
1616	}
1617
1618	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1619
1620	//DBG_TRACE( DbgInfo, "CFG_CNF_OWN_SSID result           : 0x%04x\n",
1621	//           hcf_status );
1622	/* enable/disable encryption */
1623	lp->ltvRecord.len       = 2;
1624	lp->ltvRecord.typ       = CFG_CNF_ENCRYPTION;
1625	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->EnableEncryption );
1626	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1627
1628	/* Set the Authentication Key Management Suite */
1629	lp->ltvRecord.len       = 2;
1630	lp->ltvRecord.typ       = CFG_SET_WPA_AUTH_KEY_MGMT_SUITE;
1631	lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( lp->AuthKeyMgmtSuite );
1632	hcf_status = hcf_put_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
1633	/* WEP Keys */
1634	wl_set_wep_keys( lp );
1635
1636	/* Country Code */
1637	/* countryInfo, ltvCountryInfo, CFG_CNF_COUNTRY_INFO */
1638
1639	DBG_LEAVE( DbgInfo );
1640	return hcf_status;
1641} // wl_put_ltv
1642/*============================================================================*/
1643
1644
1645/*******************************************************************************
1646 *	init_module()
1647 *******************************************************************************
1648 *
1649 *  DESCRIPTION:
1650 *
1651 *      Load the kernel module.
1652 *
1653 *  PARAMETERS:
1654 *
1655 *      N/A
1656 *
1657 *  RETURNS:
1658 *
1659 *      0 on success
1660 *      an errno value otherwise
1661 *
1662 ******************************************************************************/
1663static int __init wl_module_init( void )
1664{
1665	int result;
1666	/*------------------------------------------------------------------------*/
1667
1668	DBG_FUNC( "wl_module_init" );
1669
1670#if DBG
1671	/* Convert "standard" PCMCIA parameter pc_debug to a reasonable DebugFlag value.
1672	 * NOTE: The values all fall through to the lower values. */
1673	DbgInfo->DebugFlag = 0;
1674	DbgInfo->DebugFlag = DBG_TRACE_ON;		//;?get this mess resolved one day
1675	if ( pc_debug ) switch( pc_debug ) {
1676	  case 8:
1677		DbgInfo->DebugFlag |= DBG_DS_ON;
1678	  case 7:
1679		DbgInfo->DebugFlag |= DBG_RX_ON | DBG_TX_ON;
1680	  case 6:
1681		DbgInfo->DebugFlag |= DBG_PARAM_ON;
1682	  case 5:
1683		DbgInfo->DebugFlag |= DBG_TRACE_ON;
1684	  case 4:
1685		DbgInfo->DebugFlag |= DBG_VERBOSE_ON;
1686	  case 1:
1687		DbgInfo->DebugFlag |= DBG_DEFAULTS;
1688	  default:
1689		break;
1690	}
1691#endif /* DBG */
1692
1693	DBG_ENTER( DbgInfo );
1694	printk(KERN_INFO "%s\n", VERSION_INFO);
1695    	printk(KERN_INFO "*** Modified for kernel 2.6 by Henk de Groot <pe1dnn@amsat.org>\n");
1696        printk(KERN_INFO "*** Based on 7.18 version by Andrey Borzenkov <arvidjaar@mail.ru> $Revision: 39 $\n");
1697
1698
1699// ;?#if (HCF_TYPE) & HCF_TYPE_AP
1700// 	DBG_PRINT( "Access Point Mode (AP) Support: YES\n" );
1701// #else
1702// 	DBG_PRINT( "Access Point Mode (AP) Support: NO\n" );
1703// #endif /* (HCF_TYPE) & HCF_TYPE_AP */
1704
1705	result = wl_adapter_init_module( );
1706	DBG_LEAVE( DbgInfo );
1707	return result;
1708} // init_module
1709/*============================================================================*/
1710
1711
1712/*******************************************************************************
1713 *	cleanup_module()
1714 *******************************************************************************
1715 *
1716 *  DESCRIPTION:
1717 *
1718 *      Unload the kernel module.
1719 *
1720 *  PARAMETERS:
1721 *
1722 *      N/A
1723 *
1724 *  RETURNS:
1725 *
1726 *      N/A
1727 *
1728 ******************************************************************************/
1729static void __exit wl_module_exit( void )
1730{
1731	DBG_FUNC( "wl_module_exit" );
1732	DBG_ENTER(DbgInfo);
1733
1734	wl_adapter_cleanup_module( );
1735#if 0 //SCULL_USE_PROC     /* don't waste space if unused */
1736	remove_proc_entry( "wlags", NULL );		//;?why so a-symmetric compared to location of create_proc_read_entry
1737#endif
1738
1739	DBG_LEAVE( DbgInfo );
1740	return;
1741} // cleanup_module
1742/*============================================================================*/
1743
1744module_init(wl_module_init);
1745module_exit(wl_module_exit);
1746
1747/*******************************************************************************
1748 *	wl_isr()
1749 *******************************************************************************
1750 *
1751 *  DESCRIPTION:
1752 *
1753 *      The Interrupt Service Routine for the driver.
1754 *
1755 *  PARAMETERS:
1756 *
1757 *      irq     -   the irq the interrupt came in on
1758 *      dev_id  -   a buffer containing information about the request
1759 *      regs    -
1760 *
1761 *  RETURNS:
1762 *
1763 *      N/A
1764 *
1765 ******************************************************************************/
1766irqreturn_t wl_isr( int irq, void *dev_id, struct pt_regs *regs )
1767{
1768	int                 events;
1769	struct net_device   *dev = (struct net_device *) dev_id;
1770	struct wl_private   *lp = NULL;
1771	/*------------------------------------------------------------------------*/
1772	if (( dev == NULL ) || ( !netif_device_present( dev ))) {
1773		return IRQ_NONE;
1774	}
1775
1776	/* Set the wl_private pointer (lp), now that we know that dev is non-null */
1777	lp = wl_priv(dev);
1778
1779#ifdef USE_RTS
1780	if ( lp->useRTS == 1 ) {
1781		DBG_PRINT( "EXITING ISR, IN RTS MODE...\n" );
1782		return;
1783		}
1784#endif  /* USE_RTS */
1785
1786	/* If we have interrupts pending, then put them on a system task
1787	   queue. Otherwise turn interrupts back on */
1788	events = hcf_action( &lp->hcfCtx, HCF_ACT_INT_OFF );
1789
1790	if ( events == HCF_INT_PENDING ) {
1791		/* Schedule the ISR handler as a bottom-half task in the
1792		   tq_immediate queue */
1793		tasklet_schedule(&lp->task);
1794	} else {
1795		//DBG_PRINT( "NOT OUR INTERRUPT\n" );
1796		hcf_action( &lp->hcfCtx, HCF_ACT_INT_ON );
1797	}
1798
1799	return IRQ_RETVAL(events == HCF_INT_PENDING);
1800} // wl_isr
1801/*============================================================================*/
1802
1803
1804/*******************************************************************************
1805 *	wl_isr_handler()
1806 *******************************************************************************
1807 *
1808 *  DESCRIPTION:
1809 *
1810 *      The ISR handler, scheduled to run in a deferred context by the ISR. This
1811 *      is where the ISR's work actually gets done.
1812 *
1813 *  PARAMETERS:
1814 *
1815 *      lp  - a pointer to the device's private adapter structure
1816 *
1817 *  RETURNS:
1818 *
1819 *      N/A
1820 *
1821 ******************************************************************************/
1822#define WVLAN_MAX_INT_SERVICES  50
1823
1824void wl_isr_handler( unsigned long p )
1825{
1826	struct net_device       *dev;
1827	unsigned long           flags;
1828	bool_t                  stop = TRUE;
1829	int                     count;
1830	int                     result;
1831        struct wl_private       *lp = (struct wl_private *)p;
1832	/*------------------------------------------------------------------------*/
1833
1834	if ( lp == NULL ) {
1835		DBG_PRINT( "wl_isr_handler  lp adapter pointer is NULL!!!\n" );
1836	} else {
1837		wl_lock( lp, &flags );
1838
1839		dev = (struct net_device *)lp->dev;
1840		if ( dev != NULL && netif_device_present( dev ) ) stop = FALSE;
1841		for( count = 0; stop == FALSE && count < WVLAN_MAX_INT_SERVICES; count++ ) {
1842			stop = TRUE;
1843			result = hcf_service_nic( &lp->hcfCtx,
1844									  (wci_bufp)lp->lookAheadBuf,
1845									  sizeof( lp->lookAheadBuf ));
1846			if ( result == HCF_ERR_MIC ) {
1847				wl_wext_event_mic_failed( dev ); 	/* Send an event that MIC failed */
1848				//;?this seems wrong if HCF_ERR_MIC coincides with another event, stop gets FALSE
1849				//so why not do it always ;?
1850			}
1851
1852#ifndef USE_MBOX_SYNC
1853			if ( lp->hcfCtx.IFB_MBInfoLen != 0 ) {	/* anything in the mailbox */
1854				wl_mbx( lp );
1855				stop = FALSE;
1856			}
1857#endif
1858			/* Check for a Link status event */
1859			if ( ( lp->hcfCtx.IFB_LinkStat & CFG_LINK_STAT_FW ) != 0 ) {
1860				wl_process_link_status( lp );
1861				stop = FALSE;
1862			}
1863			/* Check for probe response events */
1864			if ( lp->ProbeResp.infoType != 0 &&
1865				lp->ProbeResp.infoType != 0xFFFF ) {
1866				wl_process_probe_response( lp );
1867				memset( &lp->ProbeResp, 0, sizeof( lp->ProbeResp ));
1868				lp->ProbeResp.infoType = 0xFFFF;
1869				stop = FALSE;
1870			}
1871			/* Check for updated record events */
1872			if ( lp->updatedRecord.len != 0xFFFF ) {
1873				wl_process_updated_record( lp );
1874				lp->updatedRecord.len = 0xFFFF;
1875				stop = FALSE;
1876			}
1877			/* Check for association status events */
1878			if ( lp->assoc_stat.len != 0xFFFF ) {
1879				wl_process_assoc_status( lp );
1880				lp->assoc_stat.len = 0xFFFF;
1881				stop = FALSE;
1882			}
1883			/* Check for security status events */
1884			if ( lp->sec_stat.len != 0xFFFF ) {
1885				wl_process_security_status( lp );
1886				lp->sec_stat.len = 0xFFFF;
1887				stop = FALSE;
1888			}
1889
1890#ifdef ENABLE_DMA
1891			if ( lp->use_dma ) {
1892				/* Check for DMA Rx packets */
1893				if ( lp->hcfCtx.IFB_DmaPackets & HREG_EV_RDMAD ) {
1894					wl_rx_dma( dev );
1895					stop = FALSE;
1896				}
1897				/* Return Tx DMA descriptors to host */
1898				if ( lp->hcfCtx.IFB_DmaPackets & HREG_EV_TDMAD ) {
1899					wl_pci_dma_hcf_reclaim_tx( lp );
1900					stop = FALSE;
1901				}
1902			}
1903			else
1904#endif // ENABLE_DMA
1905			{
1906				/* Check for Rx packets */
1907				if ( lp->hcfCtx.IFB_RxLen != 0 ) {
1908					wl_rx( dev );
1909					stop = FALSE;
1910				}
1911				/* Make sure that queued frames get sent */
1912				if ( wl_send( lp )) {
1913					stop = FALSE;
1914				}
1915			}
1916		}
1917		/* We're done, so turn interrupts which were turned off in wl_isr, back on */
1918		hcf_action( &lp->hcfCtx, HCF_ACT_INT_ON );
1919		wl_unlock( lp, &flags );
1920	}
1921	return;
1922} // wl_isr_handler
1923/*============================================================================*/
1924
1925
1926/*******************************************************************************
1927 *	wl_remove()
1928 *******************************************************************************
1929 *
1930 *  DESCRIPTION:
1931 *
1932 *      Notify the adapter that it has been removed. Since the adapter is gone,
1933 *  we should no longer try to talk to it.
1934 *
1935 *  PARAMETERS:
1936 *
1937 *      dev - a pointer to the device's net_device structure
1938 *
1939 *  RETURNS:
1940 *
1941 *      N/A
1942 *
1943 ******************************************************************************/
1944void wl_remove( struct net_device *dev )
1945{
1946	struct wl_private   *lp = wl_priv(dev);
1947	unsigned long   flags;
1948	/*------------------------------------------------------------------------*/
1949	DBG_FUNC( "wl_remove" );
1950	DBG_ENTER( DbgInfo );
1951
1952	DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
1953
1954	wl_lock( lp, &flags );
1955
1956	/* stop handling interrupts */
1957	wl_act_int_off( lp );
1958        lp->is_handling_int = WL_NOT_HANDLING_INT;
1959
1960	/*
1961         * Disable the ports: just change state: since the
1962         * card is gone it is useless to talk to it and at
1963         * disconnect all state information is lost anyway.
1964         */
1965	/* Reset portState */
1966	lp->portState = WVLAN_PORT_STATE_DISABLED;
1967
1968
1969	/* Mark the device as unregistered */
1970	lp->is_registered = FALSE;
1971
1972	/* Deregister the WDS ports as well */
1973	WL_WDS_NETDEV_DEREGISTER( lp );
1974#ifdef USE_RTS
1975	if ( lp->useRTS == 1 ) {
1976		wl_unlock( lp, &flags );
1977
1978		DBG_LEAVE( DbgInfo );
1979		return;
1980	}
1981#endif  /* USE_RTS */
1982
1983	/* Inform the HCF that the card has been removed */
1984	hcf_connect( &lp->hcfCtx, HCF_DISCONNECT );
1985
1986	wl_unlock( lp, &flags );
1987
1988	DBG_LEAVE( DbgInfo );
1989	return;
1990} // wl_remove
1991/*============================================================================*/
1992
1993
1994/*******************************************************************************
1995 *	wl_suspend()
1996 *******************************************************************************
1997 *
1998 *  DESCRIPTION:
1999 *
2000 *      Power-down and halt the adapter.
2001 *
2002 *  PARAMETERS:
2003 *
2004 *      dev - a pointer to the device's net_device structure
2005 *
2006 *  RETURNS:
2007 *
2008 *      N/A
2009 *
2010 ******************************************************************************/
2011void wl_suspend( struct net_device *dev )
2012{
2013	struct wl_private  *lp = wl_priv(dev);
2014	unsigned long   flags;
2015	/*------------------------------------------------------------------------*/
2016	DBG_FUNC( "wl_suspend" );
2017	DBG_ENTER( DbgInfo );
2018
2019	DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
2020
2021	/* The adapter is suspended:
2022			Stop the adapter
2023			Power down
2024	*/
2025	wl_lock( lp, &flags );
2026
2027	/* Disable interrupt handling */
2028	wl_act_int_off( lp );
2029
2030	/* Disconnect */
2031	wl_disconnect( lp );
2032
2033	/* Disable */
2034	wl_disable( lp );
2035
2036        /* Disconnect from the adapter */
2037	hcf_connect( &lp->hcfCtx, HCF_DISCONNECT );
2038
2039	/* Reset portState to be sure (should have been done by wl_disable */
2040	lp->portState = WVLAN_PORT_STATE_DISABLED;
2041
2042	wl_unlock( lp, &flags );
2043
2044	DBG_LEAVE( DbgInfo );
2045	return;
2046} // wl_suspend
2047/*============================================================================*/
2048
2049
2050/*******************************************************************************
2051 *	wl_resume()
2052 *******************************************************************************
2053 *
2054 *  DESCRIPTION:
2055 *
2056 *      Resume a previously suspended adapter.
2057 *
2058 *  PARAMETERS:
2059 *
2060 *      dev - a pointer to the device's net_device structure
2061 *
2062 *  RETURNS:
2063 *
2064 *      N/A
2065 *
2066 ******************************************************************************/
2067void wl_resume(struct net_device *dev)
2068{
2069	struct wl_private  *lp = wl_priv(dev);
2070	unsigned long   flags;
2071	/*------------------------------------------------------------------------*/
2072	DBG_FUNC( "wl_resume" );
2073	DBG_ENTER( DbgInfo );
2074
2075	DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
2076
2077	wl_lock( lp, &flags );
2078
2079        /* Connect to the adapter */
2080	hcf_connect( &lp->hcfCtx, dev->base_addr );
2081
2082	/* Reset portState */
2083	lp->portState = WVLAN_PORT_STATE_DISABLED;
2084
2085	/* Power might have been off, assume the card lost the firmware*/
2086	lp->firmware_present = WL_FRIMWARE_NOT_PRESENT;
2087
2088	/* Reload the firmware and restart */
2089	wl_reset( dev );
2090
2091	/* Resume interrupt handling */
2092	wl_act_int_on( lp );
2093
2094	wl_unlock( lp, &flags );
2095
2096	DBG_LEAVE( DbgInfo );
2097	return;
2098} // wl_resume
2099/*============================================================================*/
2100
2101
2102/*******************************************************************************
2103 *	wl_release()
2104 *******************************************************************************
2105 *
2106 *  DESCRIPTION:
2107 *
2108 *      This function perfroms a check on the device and calls wl_remove() if
2109 *  necessary. This function can be used for all bus types, but exists mostly
2110 *  for the benefit of the Card Services driver, as there are times when
2111 *  wl_remove() does not get called.
2112 *
2113 *  PARAMETERS:
2114 *
2115 *      dev - a pointer to the device's net_device structure
2116 *
2117 *  RETURNS:
2118 *
2119 *      N/A
2120 *
2121 ******************************************************************************/
2122void wl_release( struct net_device *dev )
2123{
2124	struct wl_private  *lp = wl_priv(dev);
2125	/*------------------------------------------------------------------------*/
2126	DBG_FUNC( "wl_release" );
2127	DBG_ENTER( DbgInfo );
2128
2129	DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
2130	/* If wl_remove() hasn't been called (i.e. when Card Services is shut
2131	   down with the card in the slot), then call it */
2132	if ( lp->is_registered == TRUE ) {
2133		DBG_TRACE( DbgInfo, "Calling unregister_netdev(), as it wasn't called yet\n" );
2134		wl_remove( dev );
2135
2136		lp->is_registered = FALSE;
2137	}
2138
2139	DBG_LEAVE( DbgInfo );
2140	return;
2141} // wl_release
2142/*============================================================================*/
2143
2144
2145/*******************************************************************************
2146 *	wl_get_irq_mask()
2147 *******************************************************************************
2148 *
2149 *  DESCRIPTION:
2150 *
2151 *      Accessor function to retrieve the irq_mask module parameter
2152 *
2153 *  PARAMETERS:
2154 *
2155 *      N/A
2156 *
2157 *  RETURNS:
2158 *
2159 *      The irq_mask module parameter
2160 *
2161 ******************************************************************************/
2162p_u16 wl_get_irq_mask( void )
2163{
2164	return irq_mask;
2165} // wl_get_irq_mask
2166/*============================================================================*/
2167
2168
2169/*******************************************************************************
2170 *	wl_get_irq_list()
2171 *******************************************************************************
2172 *
2173 *  DESCRIPTION:
2174 *
2175 *      Accessor function to retrieve the irq_list module parameter
2176 *
2177 *  PARAMETERS:
2178 *
2179 *      N/A
2180 *
2181 *  RETURNS:
2182 *
2183 *      The irq_list module parameter
2184 *
2185 ******************************************************************************/
2186p_s8 * wl_get_irq_list( void )
2187{
2188	return irq_list;
2189} // wl_get_irq_list
2190/*============================================================================*/
2191
2192
2193
2194/*******************************************************************************
2195 *	wl_enable()
2196 *******************************************************************************
2197 *
2198 *  DESCRIPTION:
2199 *
2200 *      Used to enable MAC ports
2201 *
2202 *  PARAMETERS:
2203 *
2204 *      lp      - pointer to the device's private adapter structure
2205 *
2206 *  RETURNS:
2207 *
2208 *      N/A
2209 *
2210 ******************************************************************************/
2211int wl_enable( struct wl_private *lp )
2212{
2213	int hcf_status = HCF_SUCCESS;
2214	/*------------------------------------------------------------------------*/
2215	DBG_FUNC( "wl_enable" );
2216	DBG_ENTER( DbgInfo );
2217
2218	if ( lp->portState == WVLAN_PORT_STATE_ENABLED ) {
2219		DBG_TRACE( DbgInfo, "No action: Card already enabled\n" );
2220	} else if ( lp->portState == WVLAN_PORT_STATE_CONNECTED ) {
2221		//;?suspicuous logic, how can you be connected without being enabled so this is probably dead code
2222		DBG_TRACE( DbgInfo, "No action: Card already connected\n" );
2223	} else {
2224		hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_ENABLE );
2225		if ( hcf_status == HCF_SUCCESS ) {
2226			/* Set the status of the NIC to enabled */
2227			lp->portState = WVLAN_PORT_STATE_ENABLED;   //;?bad mnemonic, NIC iso PORT
2228#ifdef ENABLE_DMA
2229			if ( lp->use_dma ) {
2230				wl_pci_dma_hcf_supply( lp );  //;?always succes?
2231			}
2232#endif
2233		}
2234	}
2235	if ( hcf_status != HCF_SUCCESS ) {  //;?make this an assert
2236		DBG_TRACE( DbgInfo, "failed: 0x%x\n", hcf_status );
2237	}
2238	DBG_LEAVE( DbgInfo );
2239	return hcf_status;
2240} // wl_enable
2241/*============================================================================*/
2242
2243
2244#ifdef USE_WDS
2245/*******************************************************************************
2246 *	wl_enable_wds_ports()
2247 *******************************************************************************
2248 *
2249 *  DESCRIPTION:
2250 *
2251 *      Used to enable the WDS MAC ports 1-6
2252 *
2253 *  PARAMETERS:
2254 *
2255 *      lp      - pointer to the device's private adapter structure
2256 *
2257 *  RETURNS:
2258 *
2259 *      N/A
2260 *
2261 ******************************************************************************/
2262void wl_enable_wds_ports( struct wl_private * lp )
2263{
2264
2265	DBG_FUNC( "wl_enable_wds_ports" );
2266	DBG_ENTER( DbgInfo );
2267	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ){
2268		DBG_ERROR( DbgInfo, "!!!!;? someone misunderstood something !!!!!\n" );
2269	}
2270	DBG_LEAVE( DbgInfo );
2271	return;
2272} // wl_enable_wds_ports
2273#endif  /* USE_WDS */
2274/*============================================================================*/
2275
2276
2277/*******************************************************************************
2278 *	wl_connect()
2279 *******************************************************************************
2280 *
2281 *  DESCRIPTION:
2282 *
2283 *      Used to connect a MAC port
2284 *
2285 *  PARAMETERS:
2286 *
2287 *      lp      - pointer to the device's private adapter structure
2288 *
2289 *  RETURNS:
2290 *
2291 *      N/A
2292 *
2293 ******************************************************************************/
2294int wl_connect( struct wl_private *lp )
2295{
2296	int hcf_status;
2297	/*------------------------------------------------------------------------*/
2298
2299	DBG_FUNC( "wl_connect" );
2300	DBG_ENTER( DbgInfo );
2301
2302	if ( lp->portState != WVLAN_PORT_STATE_ENABLED ) {
2303		DBG_TRACE( DbgInfo, "No action: Not in enabled state\n" );
2304		DBG_LEAVE( DbgInfo );
2305		return HCF_SUCCESS;
2306	}
2307	hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_CONNECT );
2308	if ( hcf_status == HCF_SUCCESS ) {
2309		lp->portState = WVLAN_PORT_STATE_CONNECTED;
2310	}
2311	DBG_LEAVE( DbgInfo );
2312	return hcf_status;
2313} // wl_connect
2314/*============================================================================*/
2315
2316
2317/*******************************************************************************
2318 *	wl_disconnect()
2319 *******************************************************************************
2320 *
2321 *  DESCRIPTION:
2322 *
2323 *      Used to disconnect a MAC port
2324 *
2325 *  PARAMETERS:
2326 *
2327 *      lp      - pointer to the device's private adapter structure
2328 *
2329 *  RETURNS:
2330 *
2331 *      N/A
2332 *
2333 ******************************************************************************/
2334int wl_disconnect( struct wl_private *lp )
2335{
2336	int hcf_status;
2337	/*------------------------------------------------------------------------*/
2338
2339	DBG_FUNC( "wl_disconnect" );
2340	DBG_ENTER( DbgInfo );
2341
2342	if ( lp->portState != WVLAN_PORT_STATE_CONNECTED ) {
2343		DBG_TRACE( DbgInfo, "No action: Not in connected state\n" );
2344		DBG_LEAVE( DbgInfo );
2345		return HCF_SUCCESS;
2346	}
2347	hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_DISCONNECT );
2348	if ( hcf_status == HCF_SUCCESS ) {
2349		lp->portState = WVLAN_PORT_STATE_ENABLED;
2350	}
2351	DBG_LEAVE( DbgInfo );
2352	return hcf_status;
2353} // wl_disconnect
2354/*============================================================================*/
2355
2356
2357/*******************************************************************************
2358 *	wl_disable()
2359 *******************************************************************************
2360 *
2361 *  DESCRIPTION:
2362 *
2363 *      Used to disable MAC ports
2364 *
2365 *  PARAMETERS:
2366 *
2367 *      lp      - pointer to the device's private adapter structure
2368 *      port    - the MAC port to disable
2369 *
2370 *  RETURNS:
2371 *
2372 *      N/A
2373 *
2374 ******************************************************************************/
2375int wl_disable( struct wl_private *lp )
2376{
2377	int hcf_status = HCF_SUCCESS;
2378	/*------------------------------------------------------------------------*/
2379	DBG_FUNC( "wl_disable" );
2380	DBG_ENTER( DbgInfo );
2381
2382	if ( lp->portState == WVLAN_PORT_STATE_DISABLED ) {
2383		DBG_TRACE( DbgInfo, "No action: Port state is disabled\n" );
2384	} else {
2385		hcf_status = hcf_cntl( &lp->hcfCtx, HCF_CNTL_DISABLE );
2386		if ( hcf_status == HCF_SUCCESS ) {
2387			/* Set the status of the port to disabled */ //;?bad mnemonic use NIC iso PORT
2388			lp->portState = WVLAN_PORT_STATE_DISABLED;
2389
2390#ifdef ENABLE_DMA
2391			if ( lp->use_dma ) {
2392				wl_pci_dma_hcf_reclaim( lp );
2393			}
2394#endif
2395		}
2396	}
2397	if ( hcf_status != HCF_SUCCESS ) {
2398		DBG_TRACE( DbgInfo, "failed: 0x%x\n", hcf_status );
2399	}
2400	DBG_LEAVE( DbgInfo );
2401	return hcf_status;
2402} // wl_disable
2403/*============================================================================*/
2404
2405
2406#ifdef USE_WDS
2407/*******************************************************************************
2408 *	wl_disable_wds_ports()
2409 *******************************************************************************
2410 *
2411 *  DESCRIPTION:
2412 *
2413 *      Used to disable the WDS MAC ports 1-6
2414 *
2415 *  PARAMETERS:
2416 *
2417 *      lp      - pointer to the device's private adapter structure
2418 *
2419 *  RETURNS:
2420 *
2421 *      N/A
2422 *
2423 ******************************************************************************/
2424void wl_disable_wds_ports( struct wl_private * lp )
2425{
2426
2427	DBG_FUNC( "wl_disable_wds_ports" );
2428	DBG_ENTER( DbgInfo );
2429
2430	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ){
2431		DBG_ERROR( DbgInfo, "!!!!;? someone misunderstood something !!!!!\n" );
2432	}
2433// 	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
2434// 		wl_disable( lp, HCF_PORT_1 );
2435// 		wl_disable( lp, HCF_PORT_2 );
2436// 		wl_disable( lp, HCF_PORT_3 );
2437// 		wl_disable( lp, HCF_PORT_4 );
2438// 		wl_disable( lp, HCF_PORT_5 );
2439// 		wl_disable( lp, HCF_PORT_6 );
2440// 	}
2441	DBG_LEAVE( DbgInfo );
2442	return;
2443} // wl_disable_wds_ports
2444#endif // USE_WDS
2445/*============================================================================*/
2446
2447
2448#ifndef USE_MBOX_SYNC
2449/*******************************************************************************
2450 *	wl_mbx()
2451 *******************************************************************************
2452 *
2453 *  DESCRIPTION:
2454 *      This function is used to read and process a mailbox message.
2455 *
2456 *
2457 *  PARAMETERS:
2458 *
2459 *      lp      - pointer to the device's private adapter structure
2460 *
2461 *  RETURNS:
2462 *
2463 *      an HCF status code
2464 *
2465 ******************************************************************************/
2466int wl_mbx( struct wl_private *lp )
2467{
2468	int hcf_status = HCF_SUCCESS;
2469	/*------------------------------------------------------------------------*/
2470	DBG_FUNC( "wl_mbx" );
2471	DBG_ENTER( DbgInfo );
2472	DBG_TRACE( DbgInfo, "Mailbox Info: IFB_MBInfoLen: %d\n",
2473			   lp->hcfCtx.IFB_MBInfoLen );
2474
2475	memset( &( lp->ltvRecord ), 0, sizeof( ltv_t ));
2476
2477	lp->ltvRecord.len = MB_SIZE;
2478	lp->ltvRecord.typ = CFG_MB_INFO;
2479	hcf_status = hcf_get_info( &lp->hcfCtx, (LTVP)&( lp->ltvRecord ));
2480
2481	if ( hcf_status != HCF_SUCCESS ) {
2482		DBG_ERROR( DbgInfo, "hcf_get_info returned 0x%x\n", hcf_status );
2483
2484		DBG_LEAVE( DbgInfo );
2485		return hcf_status;
2486	}
2487
2488	if ( lp->ltvRecord.typ == CFG_MB_INFO ) {
2489		DBG_LEAVE( DbgInfo );
2490		return hcf_status;
2491	}
2492	/* Endian translate the mailbox data, then process the message */
2493	wl_endian_translate_mailbox( &( lp->ltvRecord ));
2494	wl_process_mailbox( lp );
2495	DBG_LEAVE( DbgInfo );
2496	return hcf_status;
2497} // wl_mbx
2498/*============================================================================*/
2499
2500
2501/*******************************************************************************
2502 *	wl_endian_translate_mailbox()
2503 *******************************************************************************
2504 *
2505 *  DESCRIPTION:
2506 *
2507 *      This function will perform the tedious task of endian translating all
2508 *  fields withtin a mailbox message which need translating.
2509 *
2510 *  PARAMETERS:
2511 *
2512 *      ltv - pointer to the LTV to endian translate
2513 *
2514 *  RETURNS:
2515 *
2516 *      none
2517 *
2518 ******************************************************************************/
2519void wl_endian_translate_mailbox( ltv_t *ltv )
2520{
2521
2522	DBG_FUNC( "wl_endian_translate_mailbox" );
2523	DBG_ENTER( DbgInfo );
2524	switch( ltv->typ ) {
2525	  case CFG_TALLIES:
2526		break;
2527
2528	  case CFG_SCAN:
2529		{
2530			int num_aps;
2531			SCAN_RS_STRCT *aps = (SCAN_RS_STRCT *)&ltv->u.u8[0];
2532
2533			num_aps = (hcf_16)(( (size_t)(ltv->len - 1 ) * 2 ) /
2534								 ( sizeof( SCAN_RS_STRCT )));
2535
2536			while( num_aps >= 1 ) {
2537				num_aps--;
2538
2539				aps[num_aps].channel_id =
2540					CNV_LITTLE_TO_INT( aps[num_aps].channel_id );
2541
2542				aps[num_aps].noise_level =
2543					CNV_LITTLE_TO_INT( aps[num_aps].noise_level );
2544
2545				aps[num_aps].signal_level =
2546					CNV_LITTLE_TO_INT( aps[num_aps].signal_level );
2547
2548				aps[num_aps].beacon_interval_time =
2549					CNV_LITTLE_TO_INT( aps[num_aps].beacon_interval_time );
2550
2551				aps[num_aps].capability =
2552					CNV_LITTLE_TO_INT( aps[num_aps].capability );
2553
2554				aps[num_aps].ssid_len =
2555					CNV_LITTLE_TO_INT( aps[num_aps].ssid_len );
2556
2557				aps[num_aps].ssid_val[aps[num_aps].ssid_len] = 0;
2558			}
2559		}
2560		break;
2561
2562	  case CFG_ACS_SCAN:
2563		{
2564			PROBE_RESP *probe_resp = (PROBE_RESP *)ltv;
2565
2566			probe_resp->frameControl   = CNV_LITTLE_TO_INT( probe_resp->frameControl );
2567			probe_resp->durID          = CNV_LITTLE_TO_INT( probe_resp->durID );
2568			probe_resp->sequence       = CNV_LITTLE_TO_INT( probe_resp->sequence );
2569			probe_resp->dataLength     = CNV_LITTLE_TO_INT( probe_resp->dataLength );
2570#ifndef WARP
2571			probe_resp->lenType        = CNV_LITTLE_TO_INT( probe_resp->lenType );
2572#endif // WARP
2573			probe_resp->beaconInterval = CNV_LITTLE_TO_INT( probe_resp->beaconInterval );
2574			probe_resp->capability     = CNV_LITTLE_TO_INT( probe_resp->capability );
2575			probe_resp->flags          = CNV_LITTLE_TO_INT( probe_resp->flags );
2576		}
2577		break;
2578
2579	  case CFG_LINK_STAT:
2580#define ls ((LINK_STATUS_STRCT *)ltv)
2581			ls->linkStatus = CNV_LITTLE_TO_INT( ls->linkStatus );
2582		break;
2583#undef ls
2584
2585	  case CFG_ASSOC_STAT:
2586		{
2587			ASSOC_STATUS_STRCT *as = (ASSOC_STATUS_STRCT *)ltv;
2588
2589			as->assocStatus = CNV_LITTLE_TO_INT( as->assocStatus );
2590		}
2591		break;
2592
2593	  case CFG_SECURITY_STAT:
2594		{
2595			SECURITY_STATUS_STRCT *ss = (SECURITY_STATUS_STRCT *)ltv;
2596
2597			ss->securityStatus  = CNV_LITTLE_TO_INT( ss->securityStatus );
2598			ss->reason          = CNV_LITTLE_TO_INT( ss->reason );
2599		}
2600		break;
2601
2602	  case CFG_WMP:
2603		break;
2604
2605	  case CFG_NULL:
2606		break;
2607
2608	default:
2609		break;
2610	}
2611
2612	DBG_LEAVE( DbgInfo );
2613	return;
2614} // wl_endian_translate_mailbox
2615/*============================================================================*/
2616
2617/*******************************************************************************
2618 *	wl_process_mailbox()
2619 *******************************************************************************
2620 *
2621 *  DESCRIPTION:
2622 *
2623 *      This function will process the mailbox data.
2624 *
2625 *  PARAMETERS:
2626 *
2627 *      ltv - pointer to the LTV to be processed.
2628 *
2629 *  RETURNS:
2630 *
2631 *      none
2632 *
2633 ******************************************************************************/
2634void wl_process_mailbox( struct wl_private *lp )
2635{
2636	ltv_t   *ltv;
2637	hcf_16  ltv_val = 0xFFFF;
2638	/*------------------------------------------------------------------------*/
2639	DBG_FUNC( "wl_process_mailbox" );
2640	DBG_ENTER( DbgInfo );
2641	ltv = &( lp->ltvRecord );
2642
2643	switch( ltv->typ ) {
2644
2645	  case CFG_TALLIES:
2646		DBG_TRACE( DbgInfo, "CFG_TALLIES\n" );
2647		break;
2648	  case CFG_SCAN:
2649		DBG_TRACE( DbgInfo, "CFG_SCAN\n" );
2650
2651		{
2652			int num_aps;
2653			SCAN_RS_STRCT *aps = (SCAN_RS_STRCT *)&ltv->u.u8[0];
2654
2655			num_aps = (hcf_16)(( (size_t)(ltv->len - 1 ) * 2 ) /
2656								 ( sizeof( SCAN_RS_STRCT )));
2657
2658			lp->scan_results.num_aps = num_aps;
2659
2660			DBG_TRACE( DbgInfo, "Number of APs: %d\n", num_aps );
2661
2662			while( num_aps >= 1 ) {
2663				num_aps--;
2664
2665				DBG_TRACE( DbgInfo, "AP              : %d\n", num_aps );
2666				DBG_TRACE( DbgInfo, "=========================\n" );
2667				DBG_TRACE( DbgInfo, "Channel ID      : 0x%04x\n",
2668						   aps[num_aps].channel_id );
2669				DBG_TRACE( DbgInfo, "Noise Level     : 0x%04x\n",
2670						   aps[num_aps].noise_level );
2671				DBG_TRACE( DbgInfo, "Signal Level    : 0x%04x\n",
2672						   aps[num_aps].signal_level );
2673				DBG_TRACE( DbgInfo, "Beacon Interval : 0x%04x\n",
2674						   aps[num_aps].beacon_interval_time );
2675				DBG_TRACE( DbgInfo, "Capability      : 0x%04x\n",
2676						   aps[num_aps].capability );
2677				DBG_TRACE( DbgInfo, "SSID Length     : 0x%04x\n",
2678						   aps[num_aps].ssid_len );
2679				DBG_TRACE( DbgInfo, "BSSID           : %s\n",
2680						   DbgHwAddr( aps[num_aps].bssid ));
2681
2682				if ( aps[num_aps].ssid_len != 0 ) {
2683					DBG_TRACE( DbgInfo, "SSID            : %s.\n",
2684							   aps[num_aps].ssid_val );
2685				} else {
2686					DBG_TRACE( DbgInfo, "SSID            : %s.\n", "ANY" );
2687				}
2688
2689				DBG_TRACE( DbgInfo, "\n" );
2690
2691				/* Copy the info to the ScanResult structure in the private
2692				   adapter struct */
2693				memcpy( &( lp->scan_results.APTable[num_aps]), &( aps[num_aps] ),
2694						sizeof( SCAN_RS_STRCT ));
2695			}
2696
2697			/* Set scan result to true so that any scan requests will
2698			   complete */
2699			lp->scan_results.scan_complete = TRUE;
2700		}
2701
2702		break;
2703	  case CFG_ACS_SCAN:
2704		DBG_TRACE( DbgInfo, "CFG_ACS_SCAN\n" );
2705
2706		{
2707			PROBE_RESP  *probe_rsp = (PROBE_RESP *)ltv;
2708			hcf_8       *wpa_ie = NULL;
2709			hcf_16      wpa_ie_len = 0;
2710
2711			DBG_TRACE( DbgInfo, "(%s) =========================\n",
2712					   lp->dev->name );
2713
2714			DBG_TRACE( DbgInfo, "(%s) length      : 0x%04x.\n",
2715					   lp->dev->name, probe_rsp->length );
2716
2717			if ( probe_rsp->length > 1 ) {
2718				DBG_TRACE( DbgInfo, "(%s) infoType    : 0x%04x.\n",
2719						   lp->dev->name, probe_rsp->infoType );
2720
2721				DBG_TRACE( DbgInfo, "(%s) signal      : 0x%02x.\n",
2722						   lp->dev->name, probe_rsp->signal );
2723
2724				DBG_TRACE( DbgInfo, "(%s) silence     : 0x%02x.\n",
2725						   lp->dev->name, probe_rsp->silence );
2726
2727				DBG_TRACE( DbgInfo, "(%s) rxFlow      : 0x%02x.\n",
2728						   lp->dev->name, probe_rsp->rxFlow );
2729
2730				DBG_TRACE( DbgInfo, "(%s) rate        : 0x%02x.\n",
2731						   lp->dev->name, probe_rsp->rate );
2732
2733				DBG_TRACE( DbgInfo, "(%s) frame cntl  : 0x%04x.\n",
2734						   lp->dev->name, probe_rsp->frameControl );
2735
2736				DBG_TRACE( DbgInfo, "(%s) durID       : 0x%04x.\n",
2737						   lp->dev->name, probe_rsp->durID );
2738
2739				DBG_TRACE( DbgInfo, "(%s) address1    : %s\n",
2740						   lp->dev->name, DbgHwAddr( probe_rsp->address1 ));
2741
2742				DBG_TRACE( DbgInfo, "(%s) address2    : %s\n",
2743						   lp->dev->name, DbgHwAddr( probe_rsp->address2 ));
2744
2745				DBG_TRACE( DbgInfo, "(%s) BSSID       : %s\n",
2746						   lp->dev->name, DbgHwAddr( probe_rsp->BSSID ));
2747
2748				DBG_TRACE( DbgInfo, "(%s) sequence    : 0x%04x.\n",
2749						   lp->dev->name, probe_rsp->sequence );
2750
2751				DBG_TRACE( DbgInfo, "(%s) address4    : %s\n",
2752						   lp->dev->name, DbgHwAddr( probe_rsp->address4 ));
2753
2754				DBG_TRACE( DbgInfo, "(%s) datalength  : 0x%04x.\n",
2755						   lp->dev->name, probe_rsp->dataLength );
2756
2757				DBG_TRACE( DbgInfo, "(%s) DA          : %s\n",
2758						   lp->dev->name, DbgHwAddr( probe_rsp->DA ));
2759
2760				DBG_TRACE( DbgInfo, "(%s) SA          : %s\n",
2761						   lp->dev->name, DbgHwAddr( probe_rsp->SA ));
2762
2763				//DBG_TRACE( DbgInfo, "(%s) lenType     : 0x%04x.\n",
2764				//           lp->dev->name, probe_rsp->lenType );
2765
2766				DBG_TRACE( DbgInfo, "(%s) timeStamp   : %s\n",
2767						   lp->dev->name, DbgHwAddr( probe_rsp->timeStamp ));
2768
2769				DBG_TRACE( DbgInfo, "(%s) beaconInt   : 0x%04x.\n",
2770						   lp->dev->name, probe_rsp->beaconInterval );
2771
2772				DBG_TRACE( DbgInfo, "(%s) capability  : 0x%04x.\n",
2773						   lp->dev->name, probe_rsp->capability );
2774
2775				DBG_TRACE( DbgInfo, "(%s) SSID len    : 0x%04x.\n",
2776						   lp->dev->name, probe_rsp->rawData[1] );
2777
2778				if ( probe_rsp->rawData[1] > 0 ) {
2779					char ssid[HCF_MAX_NAME_LEN];
2780
2781					memset( ssid, 0, sizeof( ssid ));
2782					strncpy( ssid, &probe_rsp->rawData[2],
2783							 probe_rsp->rawData[1] );
2784
2785					DBG_TRACE( DbgInfo, "(%s) SSID        : %s\n",
2786							   lp->dev->name, ssid );
2787				}
2788
2789				/* Parse out the WPA-IE, if one exists */
2790				wpa_ie = wl_parse_wpa_ie( probe_rsp, &wpa_ie_len );
2791				if ( wpa_ie != NULL ) {
2792					DBG_TRACE( DbgInfo, "(%s) WPA-IE      : %s\n",
2793					lp->dev->name, wl_print_wpa_ie( wpa_ie, wpa_ie_len ));
2794				}
2795
2796				DBG_TRACE( DbgInfo, "(%s) flags       : 0x%04x.\n",
2797						   lp->dev->name, probe_rsp->flags );
2798			}
2799
2800			DBG_TRACE( DbgInfo, "\n\n" );
2801			/* If probe response length is 1, then the scan is complete */
2802			if ( probe_rsp->length == 1 ) {
2803				DBG_TRACE( DbgInfo, "SCAN COMPLETE\n" );
2804				lp->probe_results.num_aps = lp->probe_num_aps;
2805				lp->probe_results.scan_complete = TRUE;
2806
2807				/* Reset the counter for the next scan request */
2808				lp->probe_num_aps = 0;
2809
2810				/* Send a wireless extensions event that the scan completed */
2811				wl_wext_event_scan_complete( lp->dev );
2812			} else {
2813				/* Only copy to the table if the entry is unique; APs sometimes
2814				   respond more than once to a probe */
2815				if ( lp->probe_num_aps == 0 ) {
2816					/* Copy the info to the ScanResult structure in the private
2817					adapter struct */
2818					memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
2819							probe_rsp, sizeof( PROBE_RESP ));
2820
2821					/* Increment the number of APs detected */
2822					lp->probe_num_aps++;
2823				} else {
2824					int count;
2825					int unique = 1;
2826
2827					for( count = 0; count < lp->probe_num_aps; count++ ) {
2828						if ( memcmp( &( probe_rsp->BSSID ),
2829							lp->probe_results.ProbeTable[count].BSSID,
2830							ETH_ALEN ) == 0 ) {
2831							unique = 0;
2832						}
2833					}
2834
2835					if ( unique ) {
2836						/* Copy the info to the ScanResult structure in the
2837						private adapter struct. Only copy if there's room in the
2838						table */
2839						if ( lp->probe_num_aps < MAX_NAPS )
2840						{
2841							memcpy( &( lp->probe_results.ProbeTable[lp->probe_num_aps] ),
2842									probe_rsp, sizeof( PROBE_RESP ));
2843						}
2844						else
2845						{
2846							DBG_WARNING( DbgInfo, "Num of scan results exceeds storage, truncating\n" );
2847						}
2848
2849						/* Increment the number of APs detected. Note I do this
2850						   here even when I don't copy the probe response to the
2851						   buffer in order to detect the overflow condition */
2852						lp->probe_num_aps++;
2853					}
2854				}
2855			}
2856		}
2857
2858		break;
2859
2860	  case CFG_LINK_STAT:
2861#define ls ((LINK_STATUS_STRCT *)ltv)
2862		DBG_TRACE( DbgInfo, "CFG_LINK_STAT\n" );
2863
2864		switch( ls->linkStatus ) {
2865		  case 1:
2866			DBG_TRACE( DbgInfo, "Link Status : Connected\n" );
2867			wl_wext_event_ap( lp->dev );
2868			break;
2869
2870		  case 2:
2871			DBG_TRACE( DbgInfo, "Link Status : Disconnected\n"  );
2872			break;
2873
2874		  case 3:
2875			DBG_TRACE( DbgInfo, "Link Status : Access Point Change\n" );
2876			break;
2877
2878		  case 4:
2879			DBG_TRACE( DbgInfo, "Link Status : Access Point Out of Range\n" );
2880			break;
2881
2882		  case 5:
2883			DBG_TRACE( DbgInfo, "Link Status : Access Point In Range\n" );
2884			break;
2885
2886		default:
2887			DBG_TRACE( DbgInfo, "Link Status : UNKNOWN (0x%04x)\n",
2888					   ls->linkStatus );
2889			break;
2890		}
2891
2892		break;
2893#undef ls
2894
2895	  case CFG_ASSOC_STAT:
2896		DBG_TRACE( DbgInfo, "CFG_ASSOC_STAT\n" );
2897
2898		{
2899			ASSOC_STATUS_STRCT *as = (ASSOC_STATUS_STRCT *)ltv;
2900
2901			switch( as->assocStatus ) {
2902			  case 1:
2903				DBG_TRACE( DbgInfo, "Association Status : STA Associated\n" );
2904				break;
2905
2906			  case 2:
2907				DBG_TRACE( DbgInfo, "Association Status : STA Reassociated\n" );
2908				break;
2909
2910			  case 3:
2911				DBG_TRACE( DbgInfo, "Association Status : STA Disassociated\n" );
2912				break;
2913
2914			default:
2915				DBG_TRACE( DbgInfo, "Association Status : UNKNOWN (0x%04x)\n",
2916						   as->assocStatus );
2917				break;
2918			}
2919
2920			DBG_TRACE( DbgInfo, "STA Address        : %s\n",
2921					   DbgHwAddr( as->staAddr ));
2922
2923			if (( as->assocStatus == 2 )  && ( as->len == 8 )) {
2924				DBG_TRACE( DbgInfo, "Old AP Address     : %s\n",
2925						   DbgHwAddr( as->oldApAddr ));
2926			}
2927		}
2928
2929		break;
2930
2931	  case CFG_SECURITY_STAT:
2932		DBG_TRACE( DbgInfo, "CFG_SECURITY_STAT\n" );
2933
2934		{
2935			SECURITY_STATUS_STRCT *ss = (SECURITY_STATUS_STRCT *)ltv;
2936
2937			switch( ss->securityStatus ) {
2938			  case 1:
2939				DBG_TRACE( DbgInfo, "Security Status : Dissassociate [AP]\n" );
2940				break;
2941
2942			  case 2:
2943				DBG_TRACE( DbgInfo, "Security Status : Deauthenticate [AP]\n" );
2944				break;
2945
2946			  case 3:
2947				DBG_TRACE( DbgInfo, "Security Status : Authenticate Fail [STA] or [AP]\n" );
2948				break;
2949
2950			  case 4:
2951				DBG_TRACE( DbgInfo, "Security Status : MIC Fail\n" );
2952				break;
2953
2954			  case 5:
2955				DBG_TRACE( DbgInfo, "Security Status : Associate Fail\n" );
2956				break;
2957
2958			default:
2959				DBG_TRACE( DbgInfo, "Security Status : UNKNOWN %d\n",
2960						   ss->securityStatus );
2961				break;
2962			}
2963
2964			DBG_TRACE( DbgInfo, "STA Address     : %s\n", DbgHwAddr( ss->staAddr ));
2965
2966			DBG_TRACE( DbgInfo, "Reason          : 0x%04x \n", ss->reason );
2967		}
2968
2969		break;
2970
2971	  case CFG_WMP:
2972		DBG_TRACE( DbgInfo, "CFG_WMP, size is %d bytes\n", ltv->len );
2973		{
2974			WMP_RSP_STRCT *wmp_rsp = (WMP_RSP_STRCT *)ltv;
2975
2976			DBG_TRACE( DbgInfo, "CFG_WMP, pdu type is 0x%x\n",
2977					   wmp_rsp->wmpRsp.wmpHdr.type );
2978
2979			switch( wmp_rsp->wmpRsp.wmpHdr.type ) {
2980			  case WVLAN_WMP_PDU_TYPE_LT_RSP:
2981				{
2982#if DBG
2983					LINKTEST_RSP_STRCT  *lt_rsp = (LINKTEST_RSP_STRCT *)ltv;
2984#endif // DBG
2985					DBG_TRACE( DbgInfo, "LINK TEST RESULT\n" );
2986					DBG_TRACE( DbgInfo, "================\n" );
2987					DBG_TRACE( DbgInfo, "Length        : %d.\n",     lt_rsp->len );
2988
2989					DBG_TRACE( DbgInfo, "Name          : %s.\n",     lt_rsp->ltRsp.ltRsp.name );
2990					DBG_TRACE( DbgInfo, "Signal Level  : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.signal );
2991					DBG_TRACE( DbgInfo, "Noise  Level  : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.noise );
2992					DBG_TRACE( DbgInfo, "Receive Flow  : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.rxFlow );
2993					DBG_TRACE( DbgInfo, "Data Rate     : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.dataRate );
2994					DBG_TRACE( DbgInfo, "Protocol      : 0x%04x.\n", lt_rsp->ltRsp.ltRsp.protocol );
2995					DBG_TRACE( DbgInfo, "Station       : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.station );
2996					DBG_TRACE( DbgInfo, "Data Rate Cap : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.dataRateCap );
2997
2998					DBG_TRACE( DbgInfo, "Power Mgmt    : 0x%02x 0x%02x 0x%02x 0x%02x.\n",
2999								lt_rsp->ltRsp.ltRsp.powerMgmt[0],
3000								lt_rsp->ltRsp.ltRsp.powerMgmt[1],
3001								lt_rsp->ltRsp.ltRsp.powerMgmt[2],
3002								lt_rsp->ltRsp.ltRsp.powerMgmt[3] );
3003
3004					DBG_TRACE( DbgInfo, "Robustness    : 0x%02x 0x%02x 0x%02x 0x%02x.\n",
3005								lt_rsp->ltRsp.ltRsp.robustness[0],
3006								lt_rsp->ltRsp.ltRsp.robustness[1],
3007								lt_rsp->ltRsp.ltRsp.robustness[2],
3008								lt_rsp->ltRsp.ltRsp.robustness[3] );
3009
3010					DBG_TRACE( DbgInfo, "Scaling       : 0x%02x.\n", lt_rsp->ltRsp.ltRsp.scaling );
3011				}
3012
3013				break;
3014
3015			default:
3016				break;
3017			}
3018		}
3019
3020		break;
3021
3022	  case CFG_NULL:
3023		DBG_TRACE( DbgInfo, "CFG_NULL\n" );
3024		break;
3025
3026	  case CFG_UPDATED_INFO_RECORD:        // Updated Information Record
3027		DBG_TRACE( DbgInfo, "UPDATED INFORMATION RECORD\n" );
3028
3029		ltv_val = CNV_INT_TO_LITTLE( ltv->u.u16[0] );
3030
3031		/* Check and see which RID was updated */
3032		switch( ltv_val ) {
3033		  case CFG_CUR_COUNTRY_INFO:  // Indicate Passive Scan Completion
3034			DBG_TRACE( DbgInfo, "Updated country info\n" );
3035
3036			/* Do I need to hold off on updating RIDs until the process is
3037			   complete? */
3038			wl_connect( lp );
3039			break;
3040
3041		  case CFG_PORT_STAT:    // Wait for Connect Event
3042			//wl_connect( lp );
3043
3044			break;
3045
3046		default:
3047			DBG_WARNING( DbgInfo, "Unknown RID: 0x%04x\n", ltv_val );
3048		}
3049
3050		break;
3051
3052	default:
3053		DBG_TRACE( DbgInfo, "UNKNOWN MESSAGE: 0x%04x\n", ltv->typ );
3054		break;
3055	}
3056	DBG_LEAVE( DbgInfo );
3057	return;
3058} // wl_process_mailbox
3059/*============================================================================*/
3060#endif  /* ifndef USE_MBOX_SYNC */
3061
3062#ifdef USE_WDS
3063/*******************************************************************************
3064 *	wl_wds_netdev_register()
3065 *******************************************************************************
3066 *
3067 *  DESCRIPTION:
3068 *
3069 *      This function registers net_device structures with the system's network
3070 *      layer for use with the WDS ports.
3071 *
3072 *
3073 *  PARAMETERS:
3074 *
3075 *      lp      - pointer to the device's private adapter structure
3076 *
3077 *  RETURNS:
3078 *
3079 *      N/A
3080 *
3081 ******************************************************************************/
3082void wl_wds_netdev_register( struct wl_private *lp )
3083{
3084	int count;
3085	/*------------------------------------------------------------------------*/
3086	DBG_FUNC( "wl_wds_netdev_register" );
3087	DBG_ENTER( DbgInfo );
3088	//;?why is there no USE_WDS clause like in wl_enable_wds_ports
3089	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
3090		for( count = 0; count < NUM_WDS_PORTS; count++ ) {
3091			if ( WVLAN_VALID_MAC_ADDRESS( lp->wds_port[count].wdsAddress )) {
3092				if ( register_netdev( lp->wds_port[count].dev ) != 0 ) {
3093					DBG_WARNING( DbgInfo, "net device for WDS port %d could not be registered\n",
3094								( count + 1 ));
3095				}
3096				lp->wds_port[count].is_registered = TRUE;
3097
3098				/* Fill out the net_device structs with the MAC addr */
3099				memcpy( lp->wds_port[count].dev->dev_addr, lp->MACAddress, ETH_ALEN );
3100				lp->wds_port[count].dev->addr_len = ETH_ALEN;
3101			}
3102		}
3103	}
3104	DBG_LEAVE( DbgInfo );
3105	return;
3106} // wl_wds_netdev_register
3107/*============================================================================*/
3108
3109
3110/*******************************************************************************
3111 *	wl_wds_netdev_deregister()
3112 *******************************************************************************
3113 *
3114 *  DESCRIPTION:
3115 *
3116 *      This function deregisters the WDS net_device structures used by the
3117 *      system's network layer.
3118 *
3119 *
3120 *  PARAMETERS:
3121 *
3122 *      lp      - pointer to the device's private adapter structure
3123 *
3124 *  RETURNS:
3125 *
3126 *      N/A
3127 *
3128 ******************************************************************************/
3129void wl_wds_netdev_deregister( struct wl_private *lp )
3130{
3131	int count;
3132	/*------------------------------------------------------------------------*/
3133	DBG_FUNC( "wl_wds_netdev_deregister" );
3134	DBG_ENTER( DbgInfo );
3135	if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_AP  ) {
3136		for( count = 0; count < NUM_WDS_PORTS; count++ ) {
3137			if ( WVLAN_VALID_MAC_ADDRESS( lp->wds_port[count].wdsAddress )) {
3138				unregister_netdev( lp->wds_port[count].dev );
3139			}
3140			lp->wds_port[count].is_registered = FALSE;
3141		}
3142	}
3143	DBG_LEAVE( DbgInfo );
3144	return;
3145} // wl_wds_netdev_deregister
3146/*============================================================================*/
3147#endif  /* USE_WDS */
3148
3149
3150#if 0 //SCULL_USE_PROC     /* don't waste space if unused */
3151/*
3152 * The proc filesystem: function to read and entry
3153 */
3154int printf_hcf_16( char *s, char *buf, hcf_16* p, int n );
3155int printf_hcf_16( char *s, char *buf, hcf_16* p, int n ) {
3156
3157int i, len;
3158
3159	len = sprintf(buf, "%s", s );
3160	while ( len < 20 ) len += sprintf(buf+len, " " );
3161	len += sprintf(buf+len,": " );
3162	for ( i = 0; i < n; i++ ) {
3163		if ( len % 80 > 75 ) {
3164			len += sprintf(buf+len,"\n" );
3165		}
3166		len += sprintf(buf+len,"%04X ", p[i] );
3167	}
3168	len += sprintf(buf+len,"\n" );
3169	return len;
3170} // printf_hcf_16
3171
3172int printf_hcf_8( char *s, char *buf, hcf_8* p, int n );
3173int printf_hcf_8( char *s, char *buf, hcf_8* p, int n ) {
3174
3175int i, len;
3176
3177	len = sprintf(buf, "%s", s );
3178	while ( len < 20 ) len += sprintf(buf+len, " " );
3179	len += sprintf(buf+len,": " );
3180	for ( i = 0; i <= n; i++ ) {
3181		if ( len % 80 > 77 ) {
3182			len += sprintf(buf+len,"\n" );
3183		}
3184		len += sprintf(buf+len,"%02X ", p[i] );
3185	}
3186	len += sprintf(buf+len,"\n" );
3187	return len;
3188} // printf_hcf8
3189
3190int printf_strct( char *s, char *buf, hcf_16* p );
3191int printf_strct( char *s, char *buf, hcf_16* p ) {
3192
3193int i, len;
3194
3195	len = sprintf(buf, "%s", s );
3196	while ( len < 20 ) len += sprintf(buf+len, " " );
3197	len += sprintf(buf+len,": " );
3198	for ( i = 0; i <= *p; i++ ) {
3199		if ( len % 80 > 75 ) {
3200			len += sprintf(buf+len,"\n" );
3201		}
3202		len += sprintf(buf+len,"%04X ", p[i] );
3203	}
3204	len += sprintf(buf+len,"\n" );
3205	return len;
3206} // printf_strct
3207
3208int scull_read_procmem(char *buf, char **start, off_t offset, int len, int *eof, void *data )
3209{
3210	struct wl_private	*lp = NULL;
3211	IFBP				ifbp;
3212   	CFG_HERMES_TALLIES_STRCT *p;
3213
3214    #define LIMIT (PAGE_SIZE-80) /* don't print any more after this size */
3215
3216    len=0;
3217
3218	lp = ((struct net_device *)data)->priv;
3219	if (lp == NULL) {
3220        len += sprintf(buf+len,"No wl_private in scull_read_procmem\n" );
3221	} else if ( lp->wlags49_type == 0 ){
3222   	    ifbp = &lp->hcfCtx;
3223   	    len += sprintf(buf+len,"Magic:               0x%04X\n", ifbp->IFB_Magic );
3224   	    len += sprintf(buf+len,"IOBase:              0x%04X\n", ifbp->IFB_IOBase );
3225   	    len += sprintf(buf+len,"LinkStat:            0x%04X\n", ifbp->IFB_LinkStat );
3226   	    len += sprintf(buf+len,"DSLinkStat:          0x%04X\n", ifbp->IFB_DSLinkStat );
3227   	    len += sprintf(buf+len,"TickIni:         0x%08lX\n", ifbp->IFB_TickIni );
3228   	    len += sprintf(buf+len,"TickCnt:             0x%04X\n", ifbp->IFB_TickCnt );
3229   	    len += sprintf(buf+len,"IntOffCnt:           0x%04X\n", ifbp->IFB_IntOffCnt );
3230		len += printf_hcf_16( "IFB_FWIdentity", &buf[len],
3231							  &ifbp->IFB_FWIdentity.len, ifbp->IFB_FWIdentity.len + 1 );
3232	} else if ( lp->wlags49_type == 1 ) {
3233   	    len += sprintf(buf+len,"Channel:              0x%04X\n", lp->Channel );
3234/****** len += sprintf(buf+len,"slock:                  %d\n", lp->slock );		*/
3235//x		struct tq_struct            "task:               0x%04X\n", lp->task );
3236//x		struct net_device_stats     "stats:              0x%04X\n", lp->stats );
3237#ifdef WIRELESS_EXT
3238//x		struct iw_statistics        "wstats:             0x%04X\n", lp->wstats );
3239//x   	    len += sprintf(buf+len,"spy_number:           0x%04X\n", lp->spy_number );
3240//x		u_char                      spy_address[IW_MAX_SPY][ETH_ALEN];
3241//x		struct iw_quality           spy_stat[IW_MAX_SPY];
3242#endif // WIRELESS_EXT
3243   	    len += sprintf(buf+len,"IFB:                  0x%p\n", &lp->hcfCtx );
3244   	    len += sprintf(buf+len,"flags:                %#.8lX\n", lp->flags );  //;?use this format from now on
3245   	    len += sprintf(buf+len,"DebugFlag(wl_private) 0x%04X\n", lp->DebugFlag );
3246#if DBG
3247   	    len += sprintf(buf+len,"DebugFlag (DbgInfo):   0x%08lX\n", DbgInfo->DebugFlag );
3248#endif // DBG
3249   	    len += sprintf(buf+len,"is_registered:        0x%04X\n", lp->is_registered );
3250//x		CFG_DRV_INFO_STRCT          "driverInfo:         0x%04X\n", lp->driverInfo );
3251		len += printf_strct( "driverInfo", &buf[len], (hcf_16*)&lp->driverInfo );
3252//x		CFG_IDENTITY_STRCT          "driverIdentity:     0x%04X\n", lp->driverIdentity );
3253		len += printf_strct( "driverIdentity", &buf[len], (hcf_16*)&lp->driverIdentity );
3254//x		CFG_FW_IDENTITY_STRCT       "StationIdentity:    0x%04X\n", lp->StationIdentity );
3255		len += printf_strct( "StationIdentity", &buf[len], (hcf_16*)&lp->StationIdentity );
3256//x		CFG_PRI_IDENTITY_STRCT      "PrimaryIdentity:    0x%04X\n", lp->PrimaryIdentity );
3257		len += printf_strct( "PrimaryIdentity", &buf[len], (hcf_16*)&lp->hcfCtx.IFB_PRIIdentity );
3258		len += printf_strct( "PrimarySupplier", &buf[len], (hcf_16*)&lp->hcfCtx.IFB_PRISup );
3259//x		CFG_PRI_IDENTITY_STRCT      "NICIdentity:        0x%04X\n", lp->NICIdentity );
3260		len += printf_strct( "NICIdentity", &buf[len], (hcf_16*)&lp->NICIdentity );
3261//x		ltv_t                       "ltvRecord:          0x%04X\n", lp->ltvRecord );
3262   	    len += sprintf(buf+len,"txBytes:              0x%08lX\n", lp->txBytes );
3263   	    len += sprintf(buf+len,"maxPort:              0x%04X\n", lp->maxPort );        /* 0 for STA, 6 for AP */
3264	/* Elements used for async notification from hardware */
3265//x		RID_LOG_STRCT				RidList[10];
3266//x		ltv_t                       "updatedRecord:      0x%04X\n", lp->updatedRecord );
3267//x		PROBE_RESP				    "ProbeResp:                    0x%04X\n", lp->ProbeResp );
3268//x		ASSOC_STATUS_STRCT          "assoc_stat:         0x%04X\n", lp->assoc_stat );
3269//x		SECURITY_STATUS_STRCT       "sec_stat:           0x%04X\n", lp->sec_stat );
3270//x		u_char                      lookAheadBuf[WVLAN_MAX_LOOKAHEAD];
3271   	    len += sprintf(buf+len,"PortType:             0x%04X\n", lp->PortType );           // 1 - 3 (1 [Normal] | 3 [AdHoc])
3272   	    len += sprintf(buf+len,"Channel:              0x%04X\n", lp->Channel );            // 0 - 14 (0)
3273//x		hcf_16                      TxRateControl[2];
3274   	    len += sprintf(buf+len,"TxRateControl[2]:     0x%04X 0x%04X\n",
3275						lp->TxRateControl[0], lp->TxRateControl[1] );
3276   	    len += sprintf(buf+len,"DistanceBetweenAPs:   0x%04X\n", lp->DistanceBetweenAPs ); // 1 - 3 (1)
3277   	    len += sprintf(buf+len,"RTSThreshold:         0x%04X\n", lp->RTSThreshold );       // 0 - 2347 (2347)
3278   	    len += sprintf(buf+len,"PMEnabled:            0x%04X\n", lp->PMEnabled );          // 0 - 2, 8001 - 8002 (0)
3279   	    len += sprintf(buf+len,"MicrowaveRobustness:  0x%04X\n", lp->MicrowaveRobustness );// 0 - 1 (0)
3280   	    len += sprintf(buf+len,"CreateIBSS:           0x%04X\n", lp->CreateIBSS );         // 0 - 1 (0)
3281   	    len += sprintf(buf+len,"MulticastReceive:     0x%04X\n", lp->MulticastReceive );   // 0 - 1 (1)
3282   	    len += sprintf(buf+len,"MaxSleepDuration:     0x%04X\n", lp->MaxSleepDuration );   // 0 - 65535 (100)
3283//x		hcf_8                       MACAddress[ETH_ALEN];
3284		len += printf_hcf_8( "MACAddress", &buf[len], lp->MACAddress, ETH_ALEN );
3285//x		char                        NetworkName[HCF_MAX_NAME_LEN+1];
3286   	    len += sprintf(buf+len,"NetworkName:          %.32s\n", lp->NetworkName );
3287//x		char                        StationName[HCF_MAX_NAME_LEN+1];
3288   	    len += sprintf(buf+len,"EnableEncryption:     0x%04X\n", lp->EnableEncryption );   // 0 - 1 (0)
3289//x		char                        Key1[MAX_KEY_LEN+1];
3290		len += printf_hcf_8( "Key1", &buf[len], lp->Key1, MAX_KEY_LEN );
3291//x		char                        Key2[MAX_KEY_LEN+1];
3292//x		char                        Key3[MAX_KEY_LEN+1];
3293//x		char                        Key4[MAX_KEY_LEN+1];
3294   	    len += sprintf(buf+len,"TransmitKeyID:        0x%04X\n", lp->TransmitKeyID );      // 1 - 4 (1)
3295//x		CFG_DEFAULT_KEYS_STRCT	    "DefaultKeys:         0x%04X\n", lp->DefaultKeys );
3296//x		u_char                      mailbox[MB_SIZE];
3297//x		char                        szEncryption[MAX_ENC_LEN];
3298   	    len += sprintf(buf+len,"driverEnable:         0x%04X\n", lp->driverEnable );
3299   	    len += sprintf(buf+len,"wolasEnable:          0x%04X\n", lp->wolasEnable );
3300   	    len += sprintf(buf+len,"atimWindow:           0x%04X\n", lp->atimWindow );
3301   	    len += sprintf(buf+len,"holdoverDuration:     0x%04X\n", lp->holdoverDuration );
3302//x		hcf_16                      MulticastRate[2];
3303   	    len += sprintf(buf+len,"authentication:       0x%04X\n", lp->authentication ); // is this AP specific?
3304   	    len += sprintf(buf+len,"promiscuousMode:      0x%04X\n", lp->promiscuousMode );
3305   	    len += sprintf(buf+len,"DownloadFirmware:     0x%04X\n", lp->DownloadFirmware );   // 0 - 2 (0 [None] | 1 [STA] | 2 [AP])
3306   	    len += sprintf(buf+len,"AuthKeyMgmtSuite:     0x%04X\n", lp->AuthKeyMgmtSuite );
3307   	    len += sprintf(buf+len,"loadBalancing:        0x%04X\n", lp->loadBalancing );
3308   	    len += sprintf(buf+len,"mediumDistribution:   0x%04X\n", lp->mediumDistribution );
3309   	    len += sprintf(buf+len,"txPowLevel:           0x%04X\n", lp->txPowLevel );
3310//   	    len += sprintf(buf+len,"shortRetryLimit:    0x%04X\n", lp->shortRetryLimit );
3311//   	    len += sprintf(buf+len,"longRetryLimit:     0x%04X\n", lp->longRetryLimit );
3312//x		hcf_16                      srsc[2];
3313//x		hcf_16                      brsc[2];
3314   	    len += sprintf(buf+len,"connectionControl:    0x%04X\n", lp->connectionControl );
3315//x		//hcf_16                      probeDataRates[2];
3316   	    len += sprintf(buf+len,"ownBeaconInterval:    0x%04X\n", lp->ownBeaconInterval );
3317   	    len += sprintf(buf+len,"coexistence:          0x%04X\n", lp->coexistence );
3318//x		WVLAN_FRAME                 "txF:                0x%04X\n", lp->txF );
3319//x		WVLAN_LFRAME                txList[DEFAULT_NUM_TX_FRAMES];
3320//x		struct list_head            "txFree:             0x%04X\n", lp->txFree );
3321//x		struct list_head            txQ[WVLAN_MAX_TX_QUEUES];
3322   	    len += sprintf(buf+len,"netif_queue_on:       0x%04X\n", lp->netif_queue_on );
3323   	    len += sprintf(buf+len,"txQ_count:            0x%04X\n", lp->txQ_count );
3324//x		DESC_STRCT                  "desc_rx:            0x%04X\n", lp->desc_rx );
3325//x		DESC_STRCT                  "desc_tx:            0x%04X\n", lp->desc_tx );
3326//x		WVLAN_PORT_STATE            "portState:          0x%04X\n", lp->portState );
3327//x		ScanResult                  "scan_results:       0x%04X\n", lp->scan_results );
3328//x		ProbeResult                 "probe_results:      0x%04X\n", lp->probe_results );
3329   	    len += sprintf(buf+len,"probe_num_aps:        0x%04X\n", lp->probe_num_aps );
3330   	    len += sprintf(buf+len,"use_dma:              0x%04X\n", lp->use_dma );
3331//x		DMA_STRCT                   "dma:                0x%04X\n", lp->dma );
3332#ifdef USE_RTS
3333   	    len += sprintf(buf+len,"useRTS:               0x%04X\n", lp->useRTS );
3334#endif  // USE_RTS
3335		//;?should we restore this to allow smaller memory footprint
3336		//;?I guess not. This should be brought under Debug mode only
3337   	    len += sprintf(buf+len,"DTIMPeriod:           0x%04X\n", lp->DTIMPeriod );         // 1 - 255 (1)
3338   	    len += sprintf(buf+len,"multicastPMBuffering: 0x%04X\n", lp->multicastPMBuffering );
3339   	    len += sprintf(buf+len,"RejectAny:            0x%04X\n", lp->RejectAny );          // 0 - 1 (0)
3340   	    len += sprintf(buf+len,"ExcludeUnencrypted:   0x%04X\n", lp->ExcludeUnencrypted ); // 0 - 1 (1)
3341   	    len += sprintf(buf+len,"intraBSSRelay:        0x%04X\n", lp->intraBSSRelay );
3342   	    len += sprintf(buf+len,"wlags49_type:             0x%08lX\n", lp->wlags49_type );
3343#ifdef USE_WDS
3344//x		WVLAN_WDS_IF                wds_port[NUM_WDS_PORTS];
3345#endif // USE_WDS
3346	} else if ( lp->wlags49_type == 2 ){
3347        len += sprintf(buf+len,"tallies to be added\n" );
3348//Hermes Tallies (IFB substructure) {
3349   	    p = &lp->hcfCtx.IFB_NIC_Tallies;
3350        len += sprintf(buf+len,"TxUnicastFrames:          %08lX\n", p->TxUnicastFrames );
3351        len += sprintf(buf+len,"TxMulticastFrames:        %08lX\n", p->TxMulticastFrames );
3352        len += sprintf(buf+len,"TxFragments:              %08lX\n", p->TxFragments );
3353        len += sprintf(buf+len,"TxUnicastOctets:          %08lX\n", p->TxUnicastOctets );
3354        len += sprintf(buf+len,"TxMulticastOctets:        %08lX\n", p->TxMulticastOctets );
3355        len += sprintf(buf+len,"TxDeferredTransmissions:  %08lX\n", p->TxDeferredTransmissions );
3356        len += sprintf(buf+len,"TxSingleRetryFrames:      %08lX\n", p->TxSingleRetryFrames );
3357        len += sprintf(buf+len,"TxMultipleRetryFrames:    %08lX\n", p->TxMultipleRetryFrames );
3358        len += sprintf(buf+len,"TxRetryLimitExceeded:     %08lX\n", p->TxRetryLimitExceeded );
3359        len += sprintf(buf+len,"TxDiscards:               %08lX\n", p->TxDiscards );
3360        len += sprintf(buf+len,"RxUnicastFrames:          %08lX\n", p->RxUnicastFrames );
3361        len += sprintf(buf+len,"RxMulticastFrames:        %08lX\n", p->RxMulticastFrames );
3362        len += sprintf(buf+len,"RxFragments:              %08lX\n", p->RxFragments );
3363        len += sprintf(buf+len,"RxUnicastOctets:          %08lX\n", p->RxUnicastOctets );
3364        len += sprintf(buf+len,"RxMulticastOctets:        %08lX\n", p->RxMulticastOctets );
3365        len += sprintf(buf+len,"RxFCSErrors:              %08lX\n", p->RxFCSErrors );
3366        len += sprintf(buf+len,"RxDiscardsNoBuffer:       %08lX\n", p->RxDiscardsNoBuffer );
3367        len += sprintf(buf+len,"TxDiscardsWrongSA:        %08lX\n", p->TxDiscardsWrongSA );
3368        len += sprintf(buf+len,"RxWEPUndecryptable:       %08lX\n", p->RxWEPUndecryptable );
3369        len += sprintf(buf+len,"RxMsgInMsgFragments:      %08lX\n", p->RxMsgInMsgFragments );
3370        len += sprintf(buf+len,"RxMsgInBadMsgFragments:   %08lX\n", p->RxMsgInBadMsgFragments );
3371        len += sprintf(buf+len,"RxDiscardsWEPICVError:    %08lX\n", p->RxDiscardsWEPICVError );
3372        len += sprintf(buf+len,"RxDiscardsWEPExcluded:    %08lX\n", p->RxDiscardsWEPExcluded );
3373#if (HCF_EXT) & HCF_EXT_TALLIES_FW
3374        //to be added ;?
3375#endif // HCF_EXT_TALLIES_FW
3376	} else if ( lp->wlags49_type & 0x8000 ) {	//;?kludgy but it is unclear to me were else to place this
3377#if DBG
3378		DbgInfo->DebugFlag = lp->wlags49_type & 0x7FFF;
3379#endif // DBG
3380		lp->wlags49_type = 0;				//default to IFB again ;?
3381	} else {
3382        len += sprintf(buf+len,"unknown value for wlags49_type: 0x%08lX\n", lp->wlags49_type );
3383        len += sprintf(buf+len,"0x0000 - IFB\n" );
3384        len += sprintf(buf+len,"0x0001 - wl_private\n" );
3385        len += sprintf(buf+len,"0x0002 - Tallies\n" );
3386        len += sprintf(buf+len,"0x8xxx - Change debufflag\n" );
3387        len += sprintf(buf+len,"ERROR    0001\nWARNING  0002\nNOTICE   0004\nTRACE    0008\n" );
3388        len += sprintf(buf+len,"VERBOSE  0010\nPARAM    0020\nBREAK    0040\nRX       0100\n" );
3389        len += sprintf(buf+len,"TX       0200\nDS       0400\n" );
3390	}
3391    return len;
3392} // scull_read_procmem
3393
3394static void proc_write(const char *name, write_proc_t *w, void *data)
3395{
3396	struct proc_dir_entry * entry = create_proc_entry(name, S_IFREG | S_IWUSR, NULL);
3397	if (entry) {
3398		entry->write_proc = w;
3399		entry->data = data;
3400	}
3401} // proc_write
3402
3403static int write_int(struct file *file, const char *buffer, unsigned long count, void *data)
3404{
3405	static char		proc_number[11];
3406	unsigned int	nr = 0;
3407
3408	DBG_FUNC( "write_int" );
3409	DBG_ENTER( DbgInfo );
3410
3411	if (count > 9) {
3412		count = -EINVAL;
3413	} else if ( copy_from_user(proc_number, buffer, count) ) {
3414		count = -EFAULT;
3415	}
3416	if  (count > 0 ) {
3417		proc_number[count] = 0;
3418		nr = simple_strtoul(proc_number , NULL, 0);
3419 		*(unsigned int *)data = nr;
3420		if ( nr & 0x8000 ) {	//;?kludgy but it is unclear to me were else to place this
3421#if DBG
3422			DbgInfo->DebugFlag = nr & 0x7FFF;
3423#endif // DBG
3424		}
3425	}
3426	DBG_PRINT( "value: %08X\n", nr );
3427	DBG_LEAVE( DbgInfo );
3428	return count;
3429} // write_int
3430
3431#endif /* SCULL_USE_PROC */
3432
3433#ifdef DN554
3434#define RUN_AT(x)		(jiffies+(x))		//"borrowed" from include/pcmcia/k_compat.h
3435#define DS_OOR	0x8000		//Deepsleep OutOfRange Status
3436
3437		lp->timer_oor_cnt = DS_OOR;
3438		init_timer( &lp->timer_oor );
3439		lp->timer_oor.function = timer_oor;
3440		lp->timer_oor.data = (unsigned long)lp;
3441		lp->timer_oor.expires = RUN_AT( 3 * HZ );
3442		add_timer( &lp->timer_oor );
3443		printk( "<5>wl_enable: %ld\n", jiffies );		//;?remove me 1 day
3444#endif //DN554
3445#ifdef DN554
3446/*******************************************************************************
3447 *	timer_oor()
3448 *******************************************************************************
3449 *
3450 *  DESCRIPTION:
3451 *
3452 *
3453 *  PARAMETERS:
3454 *
3455 *      arg - a u_long representing a pointer to a dev_link_t structure for the
3456 *            device to be released.
3457 *
3458 *  RETURNS:
3459 *
3460 *      N/A
3461 *
3462 ******************************************************************************/
3463void timer_oor( u_long arg )
3464{
3465	struct wl_private       *lp = (struct wl_private *)arg;
3466
3467    /*------------------------------------------------------------------------*/
3468
3469    DBG_FUNC( "timer_oor" );
3470    DBG_ENTER( DbgInfo );
3471    DBG_PARAM( DbgInfo, "arg", "0x%08lx", arg );
3472
3473	printk( "<5>timer_oor: %ld 0x%04X\n", jiffies, lp->timer_oor_cnt );		//;?remove me 1 day
3474	lp->timer_oor_cnt += 10;
3475    if ( (lp->timer_oor_cnt & ~DS_OOR) > 300 ) {
3476		lp->timer_oor_cnt = 300;
3477	}
3478	lp->timer_oor_cnt |= DS_OOR;
3479	init_timer( &lp->timer_oor );
3480	lp->timer_oor.function = timer_oor;
3481	lp->timer_oor.data = (unsigned long)lp;
3482	lp->timer_oor.expires = RUN_AT( (lp->timer_oor_cnt & ~DS_OOR) * HZ );
3483	add_timer( &lp->timer_oor );
3484
3485    DBG_LEAVE( DbgInfo );
3486} // timer_oor
3487#endif //DN554
3488
3489MODULE_LICENSE("Dual BSD/GPL");
3490