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