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