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