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