1 /*******************************************************************************
3 * Wireless device driver for Linux (wlags49).
5 * Copyright (c) 1998-2003 Agere Systems Inc.
9 * Initially developed by TriplePoint, Inc.
10 * http://www.triplepoint.com
12 *------------------------------------------------------------------------------
14 * This file defines handling routines for the private IOCTLs
16 *------------------------------------------------------------------------------
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.
25 * Copyright © 2003 Agere Systems Inc.
26 * All rights reserved.
28 * Redistribution and use in source or binary forms, with or without
29 * modifications, are permitted provided that the following conditions are met:
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
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.
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.
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
59 ******************************************************************************/
61 /*******************************************************************************
63 ******************************************************************************/
64 #include <wl_version.h>
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>
77 #include <wl_internal.h>
82 #include <wl_netdev.h>
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);
93 int cfg_driver_info(struct uilreq *urq, struct wl_private *lp);
94 int cfg_driver_identity(struct uilreq *urq, struct wl_private *lp);
97 /* If USE_UIL is not defined, then none of the UIL Interface code below will
98 be included in the build */
101 /*******************************************************************************
103 *******************************************************************************
107 * The handler function for the UIL interface.
111 * urq - a pointer to the UIL request buffer
112 * lp - a pointer to the device's private adapter structure
117 * errno value otherwise
119 ******************************************************************************/
120 int wvlan_uil(struct uilreq *urq, struct wl_private *lp)
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);
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);
134 DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- WVLAN2_UIL_ACTION\n");
135 ioctl_ret = wvlan_uil_action(urq, lp);
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);
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);
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);
150 DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL -- UNSUPPORTED UIL CODE: 0x%X", urq->command);
151 ioctl_ret = -EOPNOTSUPP;
156 /*============================================================================*/
161 /*******************************************************************************
162 * wvlan_uil_connect()
163 *******************************************************************************
167 * Connect to the UIL in order to make a request.
171 * urq - a pointer to the UIL request buffer
172 * lp - a pointer to the device's private adapter structure
177 * UIL_ERR_xxx value otherwise
179 ******************************************************************************/
180 int wvlan_uil_connect(struct uilreq *urq, struct wl_private *lp)
182 if (!(lp->flags & WVLAN2_UIL_CONNECTED)) {
183 lp->flags |= WVLAN2_UIL_CONNECTED;
184 urq->hcfCtx = &(lp->hcfCtx);
185 urq->result = UIL_SUCCESS;
187 DBG_WARNING(DbgInfo, "UIL_ERR_IN_USE\n");
188 urq->result = UIL_ERR_IN_USE;
192 } /* wvlan_uil_connect */
193 /*============================================================================*/
198 /*******************************************************************************
199 * wvlan_uil_disconnect()
200 *******************************************************************************
204 * Disconnect from the UIL after a request has been completed.
208 * urq - a pointer to the UIL request buffer
209 * lp - a pointer to the device's private adapter structure
214 * UIL_ERR_xxx value otherwise
216 ******************************************************************************/
217 int wvlan_uil_disconnect(struct uilreq *urq, struct wl_private *lp)
219 if (urq->hcfCtx == &(lp->hcfCtx)) {
220 if (lp->flags & WVLAN2_UIL_CONNECTED) {
221 lp->flags &= ~WVLAN2_UIL_CONNECTED;
223 if (lp->flags & WVLAN2_UIL_BUSY) {
224 lp->flags &= ~WVLAN2_UIL_BUSY;
225 netif_start_queue(lp->dev);
231 urq->result = UIL_SUCCESS;
233 DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
234 urq->result = UIL_ERR_WRONG_IFB;
238 } /* wvlan_uil_disconnect */
239 /*============================================================================*/
244 /*******************************************************************************
246 *******************************************************************************
250 * Handler for the UIL_ACT_xxx subcodes associated with UIL_FUN_ACTION
254 * urq - a pointer to the UIL request buffer
255 * lp - a pointer to the device's private adapter structure
260 * UIL_ERR_xxx value otherwise
262 ******************************************************************************/
263 int wvlan_uil_action(struct uilreq *urq, struct wl_private *lp)
268 if (urq->hcfCtx == &(lp->hcfCtx)) {
269 /* Make sure there's an LTV in the request buffer */
270 ltv = (ltv_t *)urq->data;
272 /* Switch on the Type field of the LTV contained in the request
276 DBG_TRACE(DbgInfo, "UIL_ACT_BLOCK\n");
277 result = wvlan_uil_block(urq, lp);
279 case UIL_ACT_UNBLOCK:
280 DBG_TRACE(DbgInfo, "UIL_ACT_UNBLOCK\n");
281 result = wvlan_uil_unblock(urq, lp);
284 DBG_TRACE(DbgInfo, "UIL_ACT_SCAN\n");
285 urq->result = hcf_action(&(lp->hcfCtx), MDD_ACT_SCAN);
288 DBG_TRACE(DbgInfo, "UIL_ACT_APPLY\n");
289 urq->result = wl_apply(lp);
292 DBG_TRACE(DbgInfo, "UIL_ACT_RESET\n");
293 urq->result = wl_go(lp);
296 DBG_WARNING(DbgInfo, "Unknown action code: 0x%x\n", ltv->typ);
300 DBG_ERROR(DbgInfo, "Bad LTV for this action\n");
301 urq->result = UIL_ERR_LEN;
304 DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
305 urq->result = UIL_ERR_WRONG_IFB;
309 } /* wvlan_uil_action */
310 /*============================================================================*/
315 /*******************************************************************************
317 *******************************************************************************
321 * Sets a block in the driver to prevent access to the card by other
326 * urq - a pointer to the UIL request buffer
327 * lp - a pointer to the device's private adapter structure
332 * UIL_ERR_xxx value otherwise
334 ******************************************************************************/
336 int wvlan_uil_block(struct uilreq *urq, struct wl_private *lp)
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;
347 DBG_ERROR(DbgInfo, "EPERM\n");
348 urq->result = UIL_FAILURE;
352 DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
353 urq->result = UIL_ERR_WRONG_IFB;
357 } /* wvlan_uil_block */
358 /*============================================================================*/
363 /*******************************************************************************
364 * wvlan_uil_unblock()
365 *******************************************************************************
369 * Unblocks the driver to restore access to the card by other processes.
373 * urq - a pointer to the UIL request buffer
374 * lp - a pointer to the device's private adapter structure
379 * UIL_ERR_xxx value otherwise
381 ******************************************************************************/
382 int wvlan_uil_unblock(struct uilreq *urq, struct wl_private *lp)
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);
394 DBG_ERROR(DbgInfo, "EPERM\n");
395 urq->result = UIL_FAILURE;
399 DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
400 urq->result = UIL_ERR_WRONG_IFB;
404 } /* wvlan_uil_unblock */
405 /*============================================================================*/
410 /*******************************************************************************
411 * wvlan_uil_send_diag_msg()
412 *******************************************************************************
416 * Sends a diagnostic message to the card.
420 * urq - a pointer to the UIL request buffer
421 * lp - a pointer to the device's private adapter structure
426 * UIL_ERR_xxx value otherwise
428 ******************************************************************************/
429 int wvlan_uil_send_diag_msg(struct uilreq *urq, struct wl_private *lp)
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) {
440 /* Verify the user buffer */
441 result = verify_area(VERIFY_READ, urq->data, urq->len);
443 DBG_ERROR(DbgInfo, "verify_area failed, result: %d\n", result);
444 urq->result = UIL_FAILURE;
448 data = kmalloc(urq->len, GFP_KERNEL);
450 memset(Descp, 0, sizeof(DESC_STRCT));
451 memcpy(data, urq->data, urq->len);
453 Descp[0].buf_addr = (wci_bufp)data;
454 Descp[0].BUF_CNT = urq->len;
455 Descp[0].next_desc_addr = 0; /* terminate list */
457 hcf_send_msg(&(lp->hcfCtx), &Descp[0], HCF_PORT_0);
460 DBG_ERROR(DbgInfo, "ENOMEM\n");
461 urq->result = UIL_FAILURE;
467 urq->result = UIL_ERR_BUSY;
471 urq->result = UIL_FAILURE;
474 DBG_ERROR(DbgInfo, "EPERM\n");
475 urq->result = UIL_FAILURE;
479 DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
480 urq->result = UIL_ERR_WRONG_IFB;
484 } /* wvlan_uil_send_diag_msg */
485 /*============================================================================*/
488 /*******************************************************************************
489 * wvlan_uil_put_info()
490 *******************************************************************************
494 * Sends a specific RID directly to the driver to set configuration info.
498 * urq - a pointer to the UIL request buffer
499 * lp - a pointer to the device's private adapter structure
504 * UIL_ERR_xxx value otherwise
506 ******************************************************************************/
507 int wvlan_uil_put_info(struct uilreq *urq, struct wl_private *lp)
511 bool_t ltvAllocated = FALSE;
512 ENCSTRCT sEncryption;
516 hcf_16 hcfPort = HCF_PORT_0;
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");
531 /* Verify the user buffer */
532 result = verify_area(VERIFY_READ, urq->data, urq->len);
534 urq->result = UIL_FAILURE;
535 DBG_ERROR(DbgInfo, "verify_area(), VERIFY_READ FAILED\n");
539 /* Get only the command and length information. */
540 copy_from_user(&(lp->ltvRecord), urq->data, sizeof(hcf_16) * 2);
542 /* Make sure the incoming LTV record length is within the bounds of the
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");
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);
559 DBG_ERROR(DbgInfo, "Alloc FAILED\n");
560 urq->len = sizeof(lp->ltvRecord);
561 urq->result = UIL_ERR_LEN;
566 pLtv = &(lp->ltvRecord);
569 /* Copy the data from the user's buffer into the local LTV
571 copy_from_user(pLtv, urq->data, urq->len);
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 */
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]);
582 case CFG_CNF_OWN_MAC_ADDR:
583 /* TODO: determine if we are going to store anything based on this */
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]);
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]);
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]);
600 case CFG_CNF_MAX_DATA_LEN:
601 /* TODO: determine if we are going to store anything based
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
657 /* case CFG_PROBE_DATA_RATE: */
658 #endif /* HERMES25 */
660 #if 1 /* ;? (HCF_TYPE) & HCF_TYPE_AP */
661 /* ;?should we restore this to allow smaller memory footprint */
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]);
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]);
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]);
678 case CFG_CNF_WDS_ADDR1:
679 memcpy(&lp->wds_port[0].wdsAddress, &pLtv->u.u8[0], ETH_ALEN);
680 hcfPort = HCF_PORT_1;
682 case CFG_CNF_WDS_ADDR2:
683 memcpy(&lp->wds_port[1].wdsAddress, &pLtv->u.u8[0], ETH_ALEN);
684 hcfPort = HCF_PORT_2;
686 case CFG_CNF_WDS_ADDR3:
687 memcpy(&lp->wds_port[2].wdsAddress, &pLtv->u.u8[0], ETH_ALEN);
688 hcfPort = HCF_PORT_3;
690 case CFG_CNF_WDS_ADDR4:
691 memcpy(&lp->wds_port[3].wdsAddress, &pLtv->u.u8[0], ETH_ALEN);
692 hcfPort = HCF_PORT_4;
694 case CFG_CNF_WDS_ADDR5:
695 memcpy(&lp->wds_port[4].wdsAddress, &pLtv->u.u8[0], ETH_ALEN);
696 hcfPort = HCF_PORT_5;
698 case CFG_CNF_WDS_ADDR6:
699 memcpy(&lp->wds_port[5].wdsAddress, &pLtv->u.u8[0], ETH_ALEN);
700 hcfPort = HCF_PORT_6;
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]);
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]);
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]);
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]);
722 #if 1 /* ;? (HCF_TYPE) & HCF_TYPE_AP */
723 /* ;?should we restore this to allow smaller memory footprint */
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]);
729 case CFG_CNF_MCAST_RATE:
730 /* TODO: determine if we are going to store anything based on this */
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]);
738 case CFG_CNF_MICRO_WAVE:
739 /* TODO: determine if we are going to store anything based on this */
741 /*case CFG_CNF_LOAD_BALANCING:*/
742 /* TODO: determine if we are going to store anything based on this */
744 /* case CFG_CNF_MEDIUM_DISTRIBUTION: */
745 /* TODO: determine if we are going to store anything based on this */
747 /* case CFG_CNF_RX_ALL_GROUP_ADDRESS: */
748 /* TODO: determine if we are going to store anything based on this */
750 /* case CFG_CNF_COUNTRY_INFO: */
751 /* TODO: determine if we are going to store anything based on this */
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]);
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] */
771 /* TODO: determine if we are going to store anything based on this */
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]);
778 lp->RTSThreshold = pLtv->u.u16[0];
779 pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
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]);
787 case CFG_PROMISCUOUS_MODE:
788 /* TODO: determine if we are going to store anything based on this */
790 /* case CFG_WAKE_ON_LAN: */
791 /* TODO: determine if we are going to store anything based on this */
793 #if 1 /* ;? #if (HCF_TYPE) & HCF_TYPE_AP */
794 /* ;?should we restore this to allow smaller memory footprint */
796 lp->RTSThreshold = pLtv->u.u16[0];
797 pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
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]);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
865 #endif /* (HCF_TYPE) & HCF_TYPE_AP */
867 case CFG_DEFAULT_KEYS:
869 CFG_DEFAULT_KEYS_STRCT *pKeys = (CFG_DEFAULT_KEYS_STRCT *)pLtv;
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);
876 memcpy((void *)&(lp->DefaultKeys), (void *)pKeys,
877 sizeof(CFG_DEFAULT_KEYS_STRCT));
881 lp->TransmitKeyID = pLtv->u.u16[0];
882 pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
885 /* TODO: determine if we are going to store anything based on this */
888 /* TODO: determine if we are going to store anything based on this */
890 /* these RIDS are Info RIDs, and should they be allowed for puts??? */
891 case CFG_MAX_LOAD_TIME:
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:
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:
930 /* case CFG_CURRENT_COUNTRY_INFO: */
932 case CFG_CUR_CHANNEL:
933 /* case CFG_CURRENT_POWER_STATE: */
934 /* case CFG_CCAMODE: */
935 case CFG_SUPPORTED_DATA_RATES:
938 /*;? lp->DownloadFirmware = (pLtv->u.u16[0]) + 1; */
939 DBG_ERROR(DbgInfo, "set CFG_AP_MODE no longer supported\n");
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,
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;
959 memcpy(&lp->DefaultKeys, &sEncryption.EncStr,
960 sizeof(CFG_DEFAULT_KEYS_STRCT));
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]);
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]);
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]);
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]);
980 case CFG_DISASSOCIATE_ADDR:
981 pLtv->u.u16[ETH_ALEN / 2] = CNV_INT_TO_LITTLE(pLtv->u.u16[ETH_ALEN / 2]);
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]);
988 case CFG_ADD_TKIP_MAPPED_KEY:
990 case CFG_REMOVE_TKIP_MAPPED_KEY:
992 /* some RIDs just can't be put */
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
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:
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:
1027 case CFG_CNF_OWN_BEACON_INTERVAL: /* Own Beacon Interval */
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:
1037 case CFG_CNF_MCAST_PM_BUF:
1038 case CFG_CNF_REJECT_ANY:
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 */
1046 case CFG_CNF_EXCL_UNENCRYPTED:
1047 case CFG_CNF_MCAST_RATE:
1048 case CFG_CNF_INTRA_BSS_RELAY:
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: */
1058 case CFG_ENCRYPT_STRING:
1059 /* case CFG_DRIVER_ENABLE: */
1060 case CFG_WOLAS_ENABLE:
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);
1070 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISABLE | HCF_PORT_0);
1071 hcf_cntl(&(lp->hcfCtx), HCF_CNTL_DISCONNECT);
1076 urq->result = hcf_put_info(&(lp->hcfCtx), (LTVP) pLtv);
1084 urq->result = UIL_FAILURE;
1087 DBG_ERROR(DbgInfo, "EPERM\n");
1088 urq->result = UIL_FAILURE;
1092 DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
1093 urq->result = UIL_ERR_WRONG_IFB;
1097 } /* wvlan_uil_put_info */
1099 /*============================================================================*/
1101 /*******************************************************************************
1102 * wvlan_uil_get_info()
1103 *******************************************************************************
1107 * Sends a specific RID directly to the driver to retrieve configuration
1112 * urq - a pointer to the UIL request buffer
1113 * lp - a pointer to the device's private adapter structure
1118 * UIL_ERR_xxx value otherwise
1120 ******************************************************************************/
1121 int wvlan_uil_get_info(struct uilreq *urq, struct wl_private *lp)
1126 if (urq->hcfCtx == &(lp->hcfCtx)) {
1127 if ((urq->data != NULL) && (urq->len != 0)) {
1129 bool_t ltvAllocated = FALSE;
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;
1140 /* Verify the user's LTV record header. */
1141 result = verify_area(VERIFY_READ, urq->data, sizeof(hcf_16) * 2);
1143 DBG_ERROR(DbgInfo, "verify_area(), VERIFY_READ FAILED\n");
1144 urq->result = UIL_FAILURE;
1148 /* Get only the command and length information. */
1149 result = copy_from_user(&(lp->ltvRecord), urq->data, sizeof(hcf_16) * 2);
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;
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));
1165 case CFG_PRI_IDENTITY:
1166 memcpy(&lp->ltvRecord.u.u8[0], &lp->PrimaryIdentity, sizeof(lp->PrimaryIdentity));
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;
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;
1182 DBG_TRACE(DbgInfo, "Intercept CFG_DRV_INFO\n");
1183 result = cfg_driver_info(urq, lp);
1185 case CFG_DRV_IDENTITY:
1186 DBG_TRACE(DbgInfo, "Intercept CFG_DRV_IDENTITY\n");
1187 result = cfg_driver_identity(urq, lp);
1190 /* IFB can be a security hole */
1191 if (!capable(CAP_NET_ADMIN)) {
1196 /* Else fall through to the default */
1198 case CFG_FW_IDENTITY: /* For Hermes-1, this is cached */
1201 /* Verify the user buffer */
1202 result = verify_area(VERIFY_WRITE, urq->data, urq->len);
1204 DBG_ERROR(DbgInfo, "verify_area(), VERIFY_WRITE FAILED\n");
1205 urq->result = UIL_FAILURE;
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);
1215 ltvAllocated = TRUE;
1217 /* Copy the command/length information into the new buffer. */
1218 memcpy(pLtv, &(lp->ltvRecord), sizeof(hcf_16) * 2);
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");
1228 pLtv = &(lp->ltvRecord);
1232 urq->result = hcf_get_info(&(lp->hcfCtx), (LTVP) pLtv);
1235 /* Copy the LTV into the user's buffer. */
1236 /*copy_to_user(urq->data, pLtv, urq->len); */
1243 /* urq->result = UIL_SUCCESS; */
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:
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:
1278 case CFG_PROMISCUOUS_MODE:
1279 /*case CFG_WAKE_ON_LAN: */
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:
1296 case CFG_MAX_LOAD_TIME:
1297 case CFG_NIC_TEMP_TYPE:
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: */
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]); */
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:
1330 lp->ltvRecord.u.u16[0] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[0]);
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:
1344 case CFG_NIC_MAC_ADDR:
1345 case CFG_SUPPORTED_DATA_RATES: /* need to ensure we can treat this as a string */
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. */
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]);
1353 for(i = 4; i < lp->ltvRecord.len; i++) {
1354 lp->ltvRecord.u.u16[i] = CNV_INT_TO_LITTLE(lp->ltvRecord.u.u16[i]);
1359 case CFG_DEFAULT_KEYS:
1361 CFG_DEFAULT_KEYS_STRCT *pKeys = (CFG_DEFAULT_KEYS_STRCT *)&lp->ltvRecord.u.u8[0];
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);
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]);
1377 case CFG_NIC_IDENTITY:
1378 case CFG_COMMS_QUALITY:
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]);
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]);
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]);
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]);
1408 /* done at init time, and endian handled then */
1409 case CFG_PRI_IDENTITY:
1412 /* wvlanEndianTranslateMailbox(pLtv); */
1414 /* MSF and HCF RIDS */
1418 case CFG_ENCRYPT_STRING:
1419 case CFG_COUNTRY_STRING:
1420 case CFG_DRIVER_ENABLE:
1421 case CFG_WOLAS_ENABLE:
1426 /* Copy the LTV into the user's buffer. */
1427 copy_to_user(urq->data, &(lp->ltvRecord), urq->len);
1430 kfree(&(lp->ltvRecord));
1431 urq->result = UIL_SUCCESS;
1433 urq->result = UIL_FAILURE;
1436 DBG_ERROR(DbgInfo, "UIL_ERR_WRONG_IFB\n");
1437 urq->result = UIL_ERR_WRONG_IFB;
1441 } /* wvlan_uil_get_info */
1442 /*============================================================================*/
1448 /*******************************************************************************
1450 *******************************************************************************
1454 * Retrieves driver information.
1458 * urq - a pointer to the UIL request buffer
1459 * lp - a pointer to the device's private adapter structure
1464 * UIL_ERR_xxx value otherwise
1466 ******************************************************************************/
1467 int cfg_driver_info(struct uilreq *urq, struct wl_private *lp)
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;
1478 /* Verify the user buffer. */
1479 result = verify_area(VERIFY_WRITE, urq->data, sizeof(lp->driverInfo));
1481 urq->result = UIL_FAILURE;
1485 lp->driverInfo.card_stat = lp->hcfCtx.IFB_CardStat;
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));
1492 } /* cfg_driver_info */
1493 /*============================================================================*/
1498 /*******************************************************************************
1499 * cfg_driver_identity()
1500 *******************************************************************************
1504 * Retrieves ID information from the card.
1508 * urq - a pointer to the UIL request buffer
1509 * lp - a pointer to the device's private adapter structure
1514 * UIL_ERR_xxx value otherwise
1516 ******************************************************************************/
1517 int cfg_driver_identity(struct uilreq *urq, struct wl_private *lp)
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;
1528 /* Verify the user buffer. */
1529 result = verify_area(VERIFY_WRITE, urq->data, sizeof(lp->driverIdentity));
1531 urq->result = UIL_FAILURE;
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));
1540 } /* cfg_driver_identity */
1541 /*============================================================================*/
1544 #endif /* USE_UIL */
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? */
1553 /*******************************************************************************
1554 * wvlan_set_netname()
1555 *******************************************************************************
1559 * Set the ESSID of the card.
1563 * wrq - a pointer to the wireless request buffer
1564 * lp - a pointer to the device's private adapter structure
1569 * errno value otherwise
1571 ******************************************************************************/
1572 int wvlan_set_netname(struct net_device *dev,
1573 struct iw_request_info *info,
1574 union iwreq_data *wrqu,
1577 struct wl_private *lp = wl_priv(dev);
1578 unsigned long flags;
1580 wl_lock(lp, &flags);
1582 memset(lp->NetworkName, 0, sizeof(lp->NetworkName));
1583 memcpy(lp->NetworkName, extra, wrqu->data.length);
1585 /* Commit the adapter parameters */
1587 wl_unlock(lp, &flags);
1590 } /* wvlan_set_netname */
1591 /*============================================================================*/
1596 /*******************************************************************************
1597 * wvlan_get_netname()
1598 *******************************************************************************
1602 * Get the ESSID of the card.
1606 * wrq - a pointer to the wireless request buffer
1607 * lp - a pointer to the device's private adapter structure
1612 * errno value otherwise
1614 ******************************************************************************/
1615 int wvlan_get_netname(struct net_device *dev,
1616 struct iw_request_info *info,
1617 union iwreq_data *wrqu,
1620 struct wl_private *lp = wl_priv(dev);
1621 unsigned long flags;
1626 wl_lock(lp, &flags);
1628 /* Get the current network name */
1629 lp->ltvRecord.len = 1 + (sizeof(*pName) / sizeof(hcf_16));
1630 lp->ltvRecord.typ = CFG_CUR_SSID;
1632 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1634 if (status == HCF_SUCCESS) {
1635 pName = (wvName_t *)&(lp->ltvRecord.u.u32);
1637 memset(extra, '\0', HCF_MAX_NAME_LEN);
1638 wrqu->data.length = pName->length;
1640 memcpy(extra, pName->name, pName->length);
1645 wl_unlock(lp, &flags);
1648 } /* wvlan_get_netname */
1649 /*============================================================================*/
1654 /*******************************************************************************
1655 * wvlan_set_station_nickname()
1656 *******************************************************************************
1660 * Set the card's station nickname.
1664 * wrq - a pointer to the wireless request buffer
1665 * lp - a pointer to the device's private adapter structure
1670 * errno value otherwise
1672 ******************************************************************************/
1673 int wvlan_set_station_nickname(struct net_device *dev,
1674 struct iw_request_info *info,
1675 union iwreq_data *wrqu,
1678 struct wl_private *lp = wl_priv(dev);
1679 unsigned long flags;
1682 wl_lock(lp, &flags);
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);
1688 /* Commit the adapter parameters */
1690 wl_unlock(lp, &flags);
1693 } /* wvlan_set_station_nickname */
1694 /*============================================================================*/
1699 /*******************************************************************************
1700 * wvlan_get_station_nickname()
1701 *******************************************************************************
1705 * Get the card's station nickname.
1709 * wrq - a pointer to the wireless request buffer
1710 * lp - a pointer to the device's private adapter structure
1715 * errno value otherwise
1717 ******************************************************************************/
1718 int wvlan_get_station_nickname(struct net_device *dev,
1719 struct iw_request_info *info,
1720 union iwreq_data *wrqu,
1723 struct wl_private *lp = wl_priv(dev);
1724 unsigned long flags;
1729 wl_lock(lp, &flags);
1731 /* Get the current station name */
1732 lp->ltvRecord.len = 1 + (sizeof(*pName) / sizeof(hcf_16));
1733 lp->ltvRecord.typ = CFG_CNF_OWN_NAME;
1735 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1737 if (status == HCF_SUCCESS) {
1738 pName = (wvName_t *)&(lp->ltvRecord.u.u32);
1740 memset(extra, '\0', HCF_MAX_NAME_LEN);
1741 wrqu->data.length = pName->length;
1742 memcpy(extra, pName->name, pName->length);
1747 wl_unlock(lp, &flags);
1751 } /* wvlan_get_station_nickname */
1752 /*============================================================================*/
1757 /*******************************************************************************
1758 * wvlan_set_porttype()
1759 *******************************************************************************
1763 * Set the card's porttype
1767 * wrq - a pointer to the wireless request buffer
1768 * lp - a pointer to the device's private adapter structure
1773 * errno value otherwise
1775 ******************************************************************************/
1776 int wvlan_set_porttype(struct net_device *dev,
1777 struct iw_request_info *info,
1778 union iwreq_data *wrqu,
1781 struct wl_private *lp = wl_priv(dev);
1782 unsigned long flags;
1786 wl_lock(lp, &flags);
1788 /* Validate the new value */
1789 portType = *((__u32 *)extra);
1791 if (!((portType == 1) || (portType == 3))) {
1796 lp->PortType = portType;
1798 /* Commit the adapter parameters */
1802 wl_unlock(lp, &flags);
1808 /*============================================================================*/
1811 /*******************************************************************************
1812 * wvlan_get_porttype()
1813 *******************************************************************************
1817 * Get the card's porttype
1821 * wrq - a pointer to the wireless request buffer
1822 * lp - a pointer to the device's private adapter structure
1827 * errno value otherwise
1829 ******************************************************************************/
1830 int wvlan_get_porttype(struct net_device *dev,
1831 struct iw_request_info *info,
1832 union iwreq_data *wrqu,
1835 struct wl_private *lp = wl_priv(dev);
1836 unsigned long flags;
1840 __u32 *pData = (__u32 *)extra;
1842 wl_lock(lp, &flags);
1844 /* Get the current port type */
1845 lp->ltvRecord.len = 1 + (sizeof(*pPortType) / sizeof(hcf_16));
1846 lp->ltvRecord.typ = CFG_CNF_PORT_TYPE;
1848 status = hcf_get_info(&(lp->hcfCtx), (LTVP)&(lp->ltvRecord));
1850 if (status == HCF_SUCCESS) {
1851 pPortType = (hcf_16 *)&(lp->ltvRecord.u.u32);
1853 *pData = CNV_LITTLE_TO_INT(*pPortType);
1858 wl_unlock(lp, &flags);
1862 } /* wvlan_get_porttype */
1863 /*============================================================================*/
1865 #endif /* WIRELESS_EXT */
1871 /*******************************************************************************
1873 *******************************************************************************
1877 * IOCTL handler for RTS commands
1881 * rrq - a pointer to the rts request buffer
1882 * lp - a pointer to the device's private adapter structure
1887 * errno value otherwise
1889 ******************************************************************************/
1890 int wvlan_rts(struct rtsreq *rrq, __u32 io_base)
1894 DBG_PRINT("io_base: 0x%08x\n", io_base);
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]));
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]));
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));
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));
1919 DBG_TRACE(DbgInfo, "IOCTL: WVLAN2_IOCTL_RTS -- UNSUPPORTED RTS CODE: 0x%X", rrq->typ);
1920 ioctl_ret = -EOPNOTSUPP;
1926 /*============================================================================*/
1928 #endif /* USE_RTS */