1 /* src/prism2/driver/prism2sta.c
3 * Implements the station functionality for prism2
5 * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
6 * --------------------------------------------------------------------
10 * The contents of this file are subject to the Mozilla Public
11 * License Version 1.1 (the "License"); you may not use this file
12 * except in compliance with the License. You may obtain a copy of
13 * the License at http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS
16 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
17 * implied. See the License for the specific language governing
18 * rights and limitations under the License.
20 * Alternatively, the contents of this file may be used under the
21 * terms of the GNU Public License version 2 (the "GPL"), in which
22 * case the provisions of the GPL are applicable instead of the
23 * above. If you wish to allow the use of your version of this file
24 * only under the terms of the GPL and not to allow others to use
25 * your version of this file under the MPL, indicate your decision
26 * by deleting the provisions above and replace them with the notice
27 * and other provisions required by the GPL. If you do not delete
28 * the provisions above, a recipient may use your version of this
29 * file under either the MPL or the GPL.
31 * --------------------------------------------------------------------
33 * Inquiries regarding the linux-wlan Open Source project can be
36 * AbsoluteValue Systems Inc.
38 * http://www.linux-wlan.com
40 * --------------------------------------------------------------------
42 * Portions of the development of this software were funded by
43 * Intersil Corporation as part of PRISM(R) chipset product development.
45 * --------------------------------------------------------------------
47 * This file implements the module and linux pcmcia routines for the
50 * --------------------------------------------------------------------
53 /*================================================================*/
55 #define WLAN_DBVAR prism2_debug
57 #include <linux/version.h>
58 #include <linux/module.h>
59 #include <linux/moduleparam.h>
60 #include <linux/kernel.h>
61 #include <linux/sched.h>
62 #include <linux/types.h>
63 #include <linux/init.h>
64 #include <linux/slab.h>
65 #include <linux/wireless.h>
66 #include <linux/netdevice.h>
67 #include <linux/workqueue.h>
70 #include <linux/delay.h>
71 #include <asm/byteorder.h>
72 #include <linux/if_arp.h>
74 #include "wlan_compat.h"
76 /*================================================================*/
77 /* Project Includes */
79 #include "p80211types.h"
80 #include "p80211hdr.h"
81 #include "p80211mgmt.h"
82 #include "p80211conv.h"
83 #include "p80211msg.h"
84 #include "p80211netdev.h"
85 #include "p80211req.h"
86 #include "p80211metadef.h"
87 #include "p80211metastruct.h"
89 #include "prism2mgmt.h"
91 /*================================================================*/
94 /*================================================================*/
97 /*================================================================*/
100 /*================================================================*/
101 /* Local Static Definitions */
103 typedef char* dev_info_t;
105 static dev_info_t dev_info = "prism2_usb";
107 static wlandevice_t *create_wlan(void);
109 /*----------------------------------------------------------------*/
110 /* --Module Parameters */
112 int prism2_reset_holdtime=30; /* Reset hold time in ms */
113 int prism2_reset_settletime=100; /* Reset settle time in ms */
115 static int prism2_doreset=0; /* Do a reset at init? */
117 #ifdef WLAN_INCLUDE_DEBUG
119 module_param( prism2_debug, int, 0644);
120 MODULE_PARM_DESC(prism2_debug, "prism2 debugging");
123 module_param( prism2_doreset, int, 0644);
124 MODULE_PARM_DESC(prism2_doreset, "Issue a reset on initialization");
126 module_param( prism2_reset_holdtime, int, 0644);
127 MODULE_PARM_DESC( prism2_reset_holdtime, "reset hold time in ms");
128 module_param( prism2_reset_settletime, int, 0644);
129 MODULE_PARM_DESC( prism2_reset_settletime, "reset settle time in ms");
131 MODULE_LICENSE("Dual MPL/GPL");
133 /*================================================================*/
134 /* Local Function Declarations */
136 static int prism2sta_open(wlandevice_t *wlandev);
137 static int prism2sta_close(wlandevice_t *wlandev);
138 static void prism2sta_reset(wlandevice_t *wlandev );
139 static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep);
140 static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg);
141 static int prism2sta_getcardinfo(wlandevice_t *wlandev);
142 static int prism2sta_globalsetup(wlandevice_t *wlandev);
143 static int prism2sta_setmulticast(wlandevice_t *wlandev,
146 static void prism2sta_inf_handover(
147 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
148 static void prism2sta_inf_tallies(
149 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
150 static void prism2sta_inf_hostscanresults(
151 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
152 static void prism2sta_inf_scanresults(
153 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
154 static void prism2sta_inf_chinforesults(
155 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
156 static void prism2sta_inf_linkstatus(
157 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
158 static void prism2sta_inf_assocstatus(
159 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
160 static void prism2sta_inf_authreq(
161 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
162 static void prism2sta_inf_authreq_defer(
163 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
164 static void prism2sta_inf_psusercnt(
165 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
167 /*================================================================*/
168 /* Function Definitions */
170 /*----------------------------------------------------------------
173 * Debug utility function to dump memory to the kernel debug log.
176 * buf ptr data we want dumped
186 ----------------------------------------------------------------*/
187 inline void dmpmem(void *buf, int n)
190 for ( c= 0; c < n; c++) {
191 if ( (c % 16) == 0 ) printk(KERN_DEBUG"dmp[%d]: ", c);
192 printk("%02x ", ((u8*)buf)[c]);
193 if ( (c % 16) == 15 ) printk("\n");
195 if ( (c % 16) != 0 ) printk("\n");
199 /*----------------------------------------------------------------
202 * WLAN device open method. Called from p80211netdev when kernel
203 * device open (start) method is called in response to the
204 * SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
208 * wlandev wlan device structure
212 * >0 f/w reported error
213 * <0 driver reported error
219 ----------------------------------------------------------------*/
220 static int prism2sta_open(wlandevice_t *wlandev)
224 /* We don't currently have to do anything else.
225 * The setup of the MAC should be subsequently completed via
227 * Higher layers know we're ready from dev->start==1 and
228 * dev->tbusy==0. Our rx path knows to pass up received/
229 * frames because of dev->flags&IFF_UP is true.
237 /*----------------------------------------------------------------
240 * WLAN device close method. Called from p80211netdev when kernel
241 * device close method is called in response to the
242 * SIOCSIIFFLAGS ioctl changing the flags bit IFF_UP
246 * wlandev wlan device structure
250 * >0 f/w reported error
251 * <0 driver reported error
257 ----------------------------------------------------------------*/
258 static int prism2sta_close(wlandevice_t *wlandev)
262 /* We don't currently have to do anything else.
263 * Higher layers know we're not ready from dev->start==0 and
264 * dev->tbusy==1. Our rx path knows to not pass up received
265 * frames because of dev->flags&IFF_UP is false.
273 /*----------------------------------------------------------------
276 * Not currently implented.
279 * wlandev wlan device structure
289 ----------------------------------------------------------------*/
290 static void prism2sta_reset(wlandevice_t *wlandev )
298 /*----------------------------------------------------------------
301 * Takes a frame from p80211 and queues it for transmission.
304 * wlandev wlan device structure
305 * pb packet buffer struct. Contains an 802.11
307 * p80211_hdr points to the 802.11 header for the packet.
309 * 0 Success and more buffs available
310 * 1 Success but no more buffs
311 * 2 Allocation failure
312 * 4 Buffer full or queue busy
318 ----------------------------------------------------------------*/
319 static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb,
320 p80211_hdr_t *p80211_hdr,
321 p80211_metawep_t *p80211_wep)
323 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
327 /* If necessary, set the 802.11 WEP bit */
328 if ((wlandev->hostwep & (HOSTWEP_PRIVACYINVOKED | HOSTWEP_ENCRYPT)) == HOSTWEP_PRIVACYINVOKED) {
329 p80211_hdr->a3.fc |= host2ieee16(WLAN_SET_FC_ISWEP(1));
332 result = hfa384x_drvr_txframe(hw, skb, p80211_hdr, p80211_wep);
339 /*----------------------------------------------------------------
340 * prism2sta_mlmerequest
342 * wlan command message handler. All we do here is pass the message
343 * over to the prism2sta_mgmt_handler.
346 * wlandev wlan device structure
347 * msg wlan command message
350 * <0 successful acceptance of message, but we're
351 * waiting for an async process to finish before
352 * we're done with the msg. When the asynch
353 * process is done, we'll call the p80211
354 * function p80211req_confirm() .
355 * >0 An error occurred while we were handling
362 ----------------------------------------------------------------*/
363 static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg)
365 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
370 switch( msg->msgcode )
372 case DIDmsg_dot11req_mibget :
373 WLAN_LOG_DEBUG(2,"Received mibget request\n");
374 result = prism2mgmt_mibset_mibget(wlandev, msg);
376 case DIDmsg_dot11req_mibset :
377 WLAN_LOG_DEBUG(2,"Received mibset request\n");
378 result = prism2mgmt_mibset_mibget(wlandev, msg);
380 case DIDmsg_dot11req_scan :
381 WLAN_LOG_DEBUG(2,"Received scan request\n");
382 result = prism2mgmt_scan(wlandev, msg);
384 case DIDmsg_dot11req_scan_results :
385 WLAN_LOG_DEBUG(2,"Received scan_results request\n");
386 result = prism2mgmt_scan_results(wlandev, msg);
388 case DIDmsg_dot11req_associate :
389 WLAN_LOG_DEBUG(2,"Received mlme associate request\n");
390 result = prism2mgmt_associate(wlandev, msg);
392 case DIDmsg_dot11req_reset :
393 WLAN_LOG_DEBUG(2,"Received mlme reset request\n");
394 result = prism2mgmt_reset(wlandev, msg);
396 case DIDmsg_dot11req_start :
397 WLAN_LOG_DEBUG(2,"Received mlme start request\n");
398 result = prism2mgmt_start(wlandev, msg);
401 * Prism2 specific messages
403 case DIDmsg_p2req_join :
404 WLAN_LOG_DEBUG(2,"Received p2 join request\n");
405 result = prism2mgmt_p2_join(wlandev, msg);
407 case DIDmsg_p2req_readpda :
408 WLAN_LOG_DEBUG(2,"Received mlme readpda request\n");
409 result = prism2mgmt_readpda(wlandev, msg);
411 case DIDmsg_p2req_readcis :
412 WLAN_LOG_DEBUG(2,"Received mlme readcis request\n");
413 result = prism2mgmt_readcis(wlandev, msg);
415 case DIDmsg_p2req_auxport_state :
416 WLAN_LOG_DEBUG(2,"Received mlme auxport_state request\n");
417 result = prism2mgmt_auxport_state(wlandev, msg);
419 case DIDmsg_p2req_auxport_read :
420 WLAN_LOG_DEBUG(2,"Received mlme auxport_read request\n");
421 result = prism2mgmt_auxport_read(wlandev, msg);
423 case DIDmsg_p2req_auxport_write :
424 WLAN_LOG_DEBUG(2,"Received mlme auxport_write request\n");
425 result = prism2mgmt_auxport_write(wlandev, msg);
427 case DIDmsg_p2req_low_level :
428 WLAN_LOG_DEBUG(2,"Received mlme low_level request\n");
429 result = prism2mgmt_low_level(wlandev, msg);
431 case DIDmsg_p2req_test_command :
432 WLAN_LOG_DEBUG(2,"Received mlme test_command request\n");
433 result = prism2mgmt_test_command(wlandev, msg);
435 case DIDmsg_p2req_mmi_read :
436 WLAN_LOG_DEBUG(2,"Received mlme mmi_read request\n");
437 result = prism2mgmt_mmi_read(wlandev, msg);
439 case DIDmsg_p2req_mmi_write :
440 WLAN_LOG_DEBUG(2,"Received mlme mmi_write request\n");
441 result = prism2mgmt_mmi_write(wlandev, msg);
443 case DIDmsg_p2req_ramdl_state :
444 WLAN_LOG_DEBUG(2,"Received mlme ramdl_state request\n");
445 result = prism2mgmt_ramdl_state(wlandev, msg);
447 case DIDmsg_p2req_ramdl_write :
448 WLAN_LOG_DEBUG(2,"Received mlme ramdl_write request\n");
449 result = prism2mgmt_ramdl_write(wlandev, msg);
451 case DIDmsg_p2req_flashdl_state :
452 WLAN_LOG_DEBUG(2,"Received mlme flashdl_state request\n");
453 result = prism2mgmt_flashdl_state(wlandev, msg);
455 case DIDmsg_p2req_flashdl_write :
456 WLAN_LOG_DEBUG(2,"Received mlme flashdl_write request\n");
457 result = prism2mgmt_flashdl_write(wlandev, msg);
459 case DIDmsg_p2req_dump_state :
460 WLAN_LOG_DEBUG(2,"Received mlme dump_state request\n");
461 result = prism2mgmt_dump_state(wlandev, msg);
464 * Linux specific messages
466 case DIDmsg_lnxreq_hostwep :
468 case DIDmsg_lnxreq_ifstate :
470 p80211msg_lnxreq_ifstate_t *ifstatemsg;
471 WLAN_LOG_DEBUG(2,"Received mlme ifstate request\n");
472 ifstatemsg = (p80211msg_lnxreq_ifstate_t*)msg;
473 result = prism2sta_ifstate(wlandev, ifstatemsg->ifstate.data);
474 ifstatemsg->resultcode.status =
475 P80211ENUM_msgitem_status_data_ok;
476 ifstatemsg->resultcode.data = result;
480 case DIDmsg_lnxreq_wlansniff :
481 WLAN_LOG_DEBUG(2,"Received mlme wlansniff request\n");
482 result = prism2mgmt_wlansniff(wlandev, msg);
484 case DIDmsg_lnxreq_autojoin :
485 WLAN_LOG_DEBUG(2,"Received mlme autojoin request\n");
486 result = prism2mgmt_autojoin(wlandev, msg);
488 case DIDmsg_lnxreq_commsquality: {
489 p80211msg_lnxreq_commsquality_t *qualmsg;
491 WLAN_LOG_DEBUG(2,"Received commsquality request\n");
493 qualmsg = (p80211msg_lnxreq_commsquality_t*) msg;
495 qualmsg->link.status = P80211ENUM_msgitem_status_data_ok;
496 qualmsg->level.status = P80211ENUM_msgitem_status_data_ok;
497 qualmsg->noise.status = P80211ENUM_msgitem_status_data_ok;
500 qualmsg->link.data = hfa384x2host_16(hw->qual.CQ_currBSS);
501 qualmsg->level.data = hfa384x2host_16(hw->qual.ASL_currBSS);
502 qualmsg->noise.data = hfa384x2host_16(hw->qual.ANL_currFC);
507 WLAN_LOG_WARNING("Unknown mgmt request message 0x%08x", msg->msgcode);
516 /*----------------------------------------------------------------
519 * Interface state. This is the primary WLAN interface enable/disable
520 * handler. Following the driver/load/deviceprobe sequence, this
521 * function must be called with a state of "enable" before any other
522 * commands will be accepted.
525 * wlandev wlan device structure
526 * msgp ptr to msg buffer
529 * A p80211 message resultcode value.
534 * process thread (usually)
536 ----------------------------------------------------------------*/
537 u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate)
539 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
543 result = P80211ENUM_resultcode_implementation_failure;
545 WLAN_LOG_DEBUG(2, "Current MSD state(%d), requesting(%d)\n",
546 wlandev->msdstate, ifstate);
549 case P80211ENUM_ifstate_fwload:
550 switch (wlandev->msdstate) {
551 case WLAN_MSD_HWPRESENT:
552 wlandev->msdstate = WLAN_MSD_FWLOAD_PENDING;
554 * Initialize the device+driver sufficiently
555 * for firmware loading.
557 if ((result=hfa384x_drvr_start(hw))) {
559 "hfa384x_drvr_start() failed,"
560 "result=%d\n", (int)result);
562 P80211ENUM_resultcode_implementation_failure;
563 wlandev->msdstate = WLAN_MSD_HWPRESENT;
566 wlandev->msdstate = WLAN_MSD_FWLOAD;
567 result = P80211ENUM_resultcode_success;
569 case WLAN_MSD_FWLOAD:
570 hfa384x_cmd_initialize(hw);
571 result = P80211ENUM_resultcode_success;
573 case WLAN_MSD_RUNNING:
575 "Cannot enter fwload state from enable state,"
576 "you must disable first.\n");
577 result = P80211ENUM_resultcode_invalid_parameters;
579 case WLAN_MSD_HWFAIL:
581 /* probe() had a problem or the msdstate contains
582 * an unrecognized value, there's nothing we can do.
584 result = P80211ENUM_resultcode_implementation_failure;
588 case P80211ENUM_ifstate_enable:
589 switch (wlandev->msdstate) {
590 case WLAN_MSD_HWPRESENT:
591 case WLAN_MSD_FWLOAD:
592 wlandev->msdstate = WLAN_MSD_RUNNING_PENDING;
593 /* Initialize the device+driver for full
594 * operation. Note that this might me an FWLOAD to
595 * to RUNNING transition so we must not do a chip
596 * or board level reset. Note that on failure,
597 * the MSD state is set to HWPRESENT because we
598 * can't make any assumptions about the state
599 * of the hardware or a previous firmware load.
601 if ((result=hfa384x_drvr_start(hw))) {
603 "hfa384x_drvr_start() failed,"
604 "result=%d\n", (int)result);
606 P80211ENUM_resultcode_implementation_failure;
607 wlandev->msdstate = WLAN_MSD_HWPRESENT;
611 if ((result=prism2sta_getcardinfo(wlandev))) {
613 "prism2sta_getcardinfo() failed,"
614 "result=%d\n", (int)result);
616 P80211ENUM_resultcode_implementation_failure;
617 hfa384x_drvr_stop(hw);
618 wlandev->msdstate = WLAN_MSD_HWPRESENT;
621 if ((result=prism2sta_globalsetup(wlandev))) {
623 "prism2sta_globalsetup() failed,"
624 "result=%d\n", (int)result);
626 P80211ENUM_resultcode_implementation_failure;
627 hfa384x_drvr_stop(hw);
628 wlandev->msdstate = WLAN_MSD_HWPRESENT;
631 wlandev->msdstate = WLAN_MSD_RUNNING;
633 hw->join_retries = 60;
634 result = P80211ENUM_resultcode_success;
636 case WLAN_MSD_RUNNING:
637 /* Do nothing, we're already in this state.*/
638 result = P80211ENUM_resultcode_success;
640 case WLAN_MSD_HWFAIL:
642 /* probe() had a problem or the msdstate contains
643 * an unrecognized value, there's nothing we can do.
645 result = P80211ENUM_resultcode_implementation_failure;
649 case P80211ENUM_ifstate_disable:
650 switch (wlandev->msdstate) {
651 case WLAN_MSD_HWPRESENT:
652 /* Do nothing, we're already in this state.*/
653 result = P80211ENUM_resultcode_success;
655 case WLAN_MSD_FWLOAD:
656 case WLAN_MSD_RUNNING:
657 wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING;
659 * TODO: Shut down the MAC completely. Here a chip
660 * or board level reset is probably called for.
661 * After a "disable" _all_ results are lost, even
662 * those from a fwload.
664 if (!wlandev->hwremoved)
665 netif_carrier_off(wlandev->netdev);
667 hfa384x_drvr_stop(hw);
669 wlandev->macmode = WLAN_MACMODE_NONE;
670 wlandev->msdstate = WLAN_MSD_HWPRESENT;
671 result = P80211ENUM_resultcode_success;
673 case WLAN_MSD_HWFAIL:
675 /* probe() had a problem or the msdstate contains
676 * an unrecognized value, there's nothing we can do.
678 result = P80211ENUM_resultcode_implementation_failure;
683 result = P80211ENUM_resultcode_invalid_parameters;
692 /*----------------------------------------------------------------
693 * prism2sta_getcardinfo
695 * Collect the NICID, firmware version and any other identifiers
696 * we'd like to have in host-side data structures.
699 * wlandev wlan device structure
703 * >0 f/w reported error
704 * <0 driver reported error
710 ----------------------------------------------------------------*/
711 static int prism2sta_getcardinfo(wlandevice_t *wlandev)
714 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
716 u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN];
717 char pstr[(HFA384x_RID_NICSERIALNUMBER_LEN * 4) + 1];
721 /* Collect version and compatibility info */
722 /* Some are critical, some are not */
724 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICIDENTITY,
725 &hw->ident_nic, sizeof(hfa384x_compident_t));
727 WLAN_LOG_ERROR("Failed to retrieve NICIDENTITY\n");
731 /* get all the nic id fields in host byte order */
732 hw->ident_nic.id = hfa384x2host_16(hw->ident_nic.id);
733 hw->ident_nic.variant = hfa384x2host_16(hw->ident_nic.variant);
734 hw->ident_nic.major = hfa384x2host_16(hw->ident_nic.major);
735 hw->ident_nic.minor = hfa384x2host_16(hw->ident_nic.minor);
737 WLAN_LOG_INFO( "ident: nic h/w: id=0x%02x %d.%d.%d\n",
738 hw->ident_nic.id, hw->ident_nic.major,
739 hw->ident_nic.minor, hw->ident_nic.variant);
741 /* Primary f/w identity */
742 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRIIDENTITY,
743 &hw->ident_pri_fw, sizeof(hfa384x_compident_t));
745 WLAN_LOG_ERROR("Failed to retrieve PRIIDENTITY\n");
749 /* get all the private fw id fields in host byte order */
750 hw->ident_pri_fw.id = hfa384x2host_16(hw->ident_pri_fw.id);
751 hw->ident_pri_fw.variant = hfa384x2host_16(hw->ident_pri_fw.variant);
752 hw->ident_pri_fw.major = hfa384x2host_16(hw->ident_pri_fw.major);
753 hw->ident_pri_fw.minor = hfa384x2host_16(hw->ident_pri_fw.minor);
755 WLAN_LOG_INFO( "ident: pri f/w: id=0x%02x %d.%d.%d\n",
756 hw->ident_pri_fw.id, hw->ident_pri_fw.major,
757 hw->ident_pri_fw.minor, hw->ident_pri_fw.variant);
759 /* Station (Secondary?) f/w identity */
760 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STAIDENTITY,
761 &hw->ident_sta_fw, sizeof(hfa384x_compident_t));
763 WLAN_LOG_ERROR("Failed to retrieve STAIDENTITY\n");
767 if (hw->ident_nic.id < 0x8000) {
768 WLAN_LOG_ERROR("FATAL: Card is not an Intersil Prism2/2.5/3\n");
773 /* get all the station fw id fields in host byte order */
774 hw->ident_sta_fw.id = hfa384x2host_16(hw->ident_sta_fw.id);
775 hw->ident_sta_fw.variant = hfa384x2host_16(hw->ident_sta_fw.variant);
776 hw->ident_sta_fw.major = hfa384x2host_16(hw->ident_sta_fw.major);
777 hw->ident_sta_fw.minor = hfa384x2host_16(hw->ident_sta_fw.minor);
779 /* strip out the 'special' variant bits */
780 hw->mm_mods = hw->ident_sta_fw.variant & (BIT14 | BIT15);
781 hw->ident_sta_fw.variant &= ~((u16)(BIT14 | BIT15));
783 if ( hw->ident_sta_fw.id == 0x1f ) {
785 "ident: sta f/w: id=0x%02x %d.%d.%d\n",
786 hw->ident_sta_fw.id, hw->ident_sta_fw.major,
787 hw->ident_sta_fw.minor, hw->ident_sta_fw.variant);
790 "ident: ap f/w: id=0x%02x %d.%d.%d\n",
791 hw->ident_sta_fw.id, hw->ident_sta_fw.major,
792 hw->ident_sta_fw.minor, hw->ident_sta_fw.variant);
793 WLAN_LOG_ERROR("Unsupported Tertiary AP firmeare loaded!\n");
797 /* Compatibility range, Modem supplier */
798 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_MFISUPRANGE,
799 &hw->cap_sup_mfi, sizeof(hfa384x_caplevel_t));
801 WLAN_LOG_ERROR("Failed to retrieve MFISUPRANGE\n");
805 /* get all the Compatibility range, modem interface supplier
806 fields in byte order */
807 hw->cap_sup_mfi.role = hfa384x2host_16(hw->cap_sup_mfi.role);
808 hw->cap_sup_mfi.id = hfa384x2host_16(hw->cap_sup_mfi.id);
809 hw->cap_sup_mfi.variant = hfa384x2host_16(hw->cap_sup_mfi.variant);
810 hw->cap_sup_mfi.bottom = hfa384x2host_16(hw->cap_sup_mfi.bottom);
811 hw->cap_sup_mfi.top = hfa384x2host_16(hw->cap_sup_mfi.top);
814 "MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
815 hw->cap_sup_mfi.role, hw->cap_sup_mfi.id,
816 hw->cap_sup_mfi.variant, hw->cap_sup_mfi.bottom,
817 hw->cap_sup_mfi.top);
819 /* Compatibility range, Controller supplier */
820 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CFISUPRANGE,
821 &hw->cap_sup_cfi, sizeof(hfa384x_caplevel_t));
823 WLAN_LOG_ERROR("Failed to retrieve CFISUPRANGE\n");
827 /* get all the Compatibility range, controller interface supplier
828 fields in byte order */
829 hw->cap_sup_cfi.role = hfa384x2host_16(hw->cap_sup_cfi.role);
830 hw->cap_sup_cfi.id = hfa384x2host_16(hw->cap_sup_cfi.id);
831 hw->cap_sup_cfi.variant = hfa384x2host_16(hw->cap_sup_cfi.variant);
832 hw->cap_sup_cfi.bottom = hfa384x2host_16(hw->cap_sup_cfi.bottom);
833 hw->cap_sup_cfi.top = hfa384x2host_16(hw->cap_sup_cfi.top);
836 "CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
837 hw->cap_sup_cfi.role, hw->cap_sup_cfi.id,
838 hw->cap_sup_cfi.variant, hw->cap_sup_cfi.bottom,
839 hw->cap_sup_cfi.top);
841 /* Compatibility range, Primary f/w supplier */
842 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRISUPRANGE,
843 &hw->cap_sup_pri, sizeof(hfa384x_caplevel_t));
845 WLAN_LOG_ERROR("Failed to retrieve PRISUPRANGE\n");
849 /* get all the Compatibility range, primary firmware supplier
850 fields in byte order */
851 hw->cap_sup_pri.role = hfa384x2host_16(hw->cap_sup_pri.role);
852 hw->cap_sup_pri.id = hfa384x2host_16(hw->cap_sup_pri.id);
853 hw->cap_sup_pri.variant = hfa384x2host_16(hw->cap_sup_pri.variant);
854 hw->cap_sup_pri.bottom = hfa384x2host_16(hw->cap_sup_pri.bottom);
855 hw->cap_sup_pri.top = hfa384x2host_16(hw->cap_sup_pri.top);
858 "PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
859 hw->cap_sup_pri.role, hw->cap_sup_pri.id,
860 hw->cap_sup_pri.variant, hw->cap_sup_pri.bottom,
861 hw->cap_sup_pri.top);
863 /* Compatibility range, Station f/w supplier */
864 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STASUPRANGE,
865 &hw->cap_sup_sta, sizeof(hfa384x_caplevel_t));
867 WLAN_LOG_ERROR("Failed to retrieve STASUPRANGE\n");
871 /* get all the Compatibility range, station firmware supplier
872 fields in byte order */
873 hw->cap_sup_sta.role = hfa384x2host_16(hw->cap_sup_sta.role);
874 hw->cap_sup_sta.id = hfa384x2host_16(hw->cap_sup_sta.id);
875 hw->cap_sup_sta.variant = hfa384x2host_16(hw->cap_sup_sta.variant);
876 hw->cap_sup_sta.bottom = hfa384x2host_16(hw->cap_sup_sta.bottom);
877 hw->cap_sup_sta.top = hfa384x2host_16(hw->cap_sup_sta.top);
879 if ( hw->cap_sup_sta.id == 0x04 ) {
881 "STA:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
882 hw->cap_sup_sta.role, hw->cap_sup_sta.id,
883 hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom,
884 hw->cap_sup_sta.top);
887 "AP:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
888 hw->cap_sup_sta.role, hw->cap_sup_sta.id,
889 hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom,
890 hw->cap_sup_sta.top);
893 /* Compatibility range, primary f/w actor, CFI supplier */
894 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRI_CFIACTRANGES,
895 &hw->cap_act_pri_cfi, sizeof(hfa384x_caplevel_t));
897 WLAN_LOG_ERROR("Failed to retrieve PRI_CFIACTRANGES\n");
901 /* get all the Compatibility range, primary f/w actor, CFI supplier
902 fields in byte order */
903 hw->cap_act_pri_cfi.role = hfa384x2host_16(hw->cap_act_pri_cfi.role);
904 hw->cap_act_pri_cfi.id = hfa384x2host_16(hw->cap_act_pri_cfi.id);
905 hw->cap_act_pri_cfi.variant = hfa384x2host_16(hw->cap_act_pri_cfi.variant);
906 hw->cap_act_pri_cfi.bottom = hfa384x2host_16(hw->cap_act_pri_cfi.bottom);
907 hw->cap_act_pri_cfi.top = hfa384x2host_16(hw->cap_act_pri_cfi.top);
910 "PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
911 hw->cap_act_pri_cfi.role, hw->cap_act_pri_cfi.id,
912 hw->cap_act_pri_cfi.variant, hw->cap_act_pri_cfi.bottom,
913 hw->cap_act_pri_cfi.top);
915 /* Compatibility range, sta f/w actor, CFI supplier */
916 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_CFIACTRANGES,
917 &hw->cap_act_sta_cfi, sizeof(hfa384x_caplevel_t));
919 WLAN_LOG_ERROR("Failed to retrieve STA_CFIACTRANGES\n");
923 /* get all the Compatibility range, station f/w actor, CFI supplier
924 fields in byte order */
925 hw->cap_act_sta_cfi.role = hfa384x2host_16(hw->cap_act_sta_cfi.role);
926 hw->cap_act_sta_cfi.id = hfa384x2host_16(hw->cap_act_sta_cfi.id);
927 hw->cap_act_sta_cfi.variant = hfa384x2host_16(hw->cap_act_sta_cfi.variant);
928 hw->cap_act_sta_cfi.bottom = hfa384x2host_16(hw->cap_act_sta_cfi.bottom);
929 hw->cap_act_sta_cfi.top = hfa384x2host_16(hw->cap_act_sta_cfi.top);
932 "STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
933 hw->cap_act_sta_cfi.role, hw->cap_act_sta_cfi.id,
934 hw->cap_act_sta_cfi.variant, hw->cap_act_sta_cfi.bottom,
935 hw->cap_act_sta_cfi.top);
937 /* Compatibility range, sta f/w actor, MFI supplier */
938 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_MFIACTRANGES,
939 &hw->cap_act_sta_mfi, sizeof(hfa384x_caplevel_t));
941 WLAN_LOG_ERROR("Failed to retrieve STA_MFIACTRANGES\n");
945 /* get all the Compatibility range, station f/w actor, MFI supplier
946 fields in byte order */
947 hw->cap_act_sta_mfi.role = hfa384x2host_16(hw->cap_act_sta_mfi.role);
948 hw->cap_act_sta_mfi.id = hfa384x2host_16(hw->cap_act_sta_mfi.id);
949 hw->cap_act_sta_mfi.variant = hfa384x2host_16(hw->cap_act_sta_mfi.variant);
950 hw->cap_act_sta_mfi.bottom = hfa384x2host_16(hw->cap_act_sta_mfi.bottom);
951 hw->cap_act_sta_mfi.top = hfa384x2host_16(hw->cap_act_sta_mfi.top);
954 "STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
955 hw->cap_act_sta_mfi.role, hw->cap_act_sta_mfi.id,
956 hw->cap_act_sta_mfi.variant, hw->cap_act_sta_mfi.bottom,
957 hw->cap_act_sta_mfi.top);
960 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER,
961 snum, HFA384x_RID_NICSERIALNUMBER_LEN);
963 wlan_mkprintstr(snum, HFA384x_RID_NICSERIALNUMBER_LEN,
965 WLAN_LOG_INFO("Prism2 card SN: %s\n", pstr);
967 WLAN_LOG_ERROR("Failed to retrieve Prism2 Card SN\n");
971 /* Collect the MAC address */
972 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFOWNMACADDR,
973 wlandev->netdev->dev_addr, WLAN_ADDR_LEN);
975 WLAN_LOG_ERROR("Failed to retrieve mac address\n");
979 /* short preamble is always implemented */
980 wlandev->nsdcaps |= P80211_NSDCAP_SHORT_PREAMBLE;
982 /* find out if hardware wep is implemented */
983 hfa384x_drvr_getconfig16(hw, HFA384x_RID_PRIVACYOPTIMP, &temp);
985 wlandev->nsdcaps |= P80211_NSDCAP_HARDWAREWEP;
987 /* get the dBm Scaling constant */
988 hfa384x_drvr_getconfig16(hw, HFA384x_RID_CNFDBMADJUST, &temp);
989 hw->dbmadjust = temp;
991 /* Only enable scan by default on newer firmware */
992 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
993 hw->ident_sta_fw.minor,
994 hw->ident_sta_fw.variant) <
995 HFA384x_FIRMWARE_VERSION(1,5,5)) {
996 wlandev->nsdcaps |= P80211_NSDCAP_NOSCAN;
999 /* TODO: Set any internally managed config items */
1003 WLAN_LOG_ERROR("Failed, result=%d\n", result);
1010 /*----------------------------------------------------------------
1011 * prism2sta_globalsetup
1013 * Set any global RIDs that we want to set at device activation.
1016 * wlandev wlan device structure
1020 * >0 f/w reported error
1021 * <0 driver reported error
1027 ----------------------------------------------------------------*/
1028 static int prism2sta_globalsetup(wlandevice_t *wlandev)
1030 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1032 /* Set the maximum frame size */
1033 return hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN,
1037 static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev)
1040 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1046 /* If we're not ready, what's the point? */
1047 if ( hw->state != HFA384x_STATE_RUNNING )
1050 if ( (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0 )
1051 promisc = P80211ENUM_truth_true;
1053 promisc = P80211ENUM_truth_false;
1055 result = hfa384x_drvr_setconfig16_async(hw, HFA384x_RID_PROMISCMODE, promisc);
1057 /* XXX TODO: configure the multicast list */
1058 // CLEAR_HW_MULTICAST_LIST
1059 // struct dev_mc_list element = dev->mc_list;
1060 // while (element != null) {
1061 // HW_ADD_MULTICAST_ADDR(element->dmi_addr, dmi_addrlen)
1062 // element = element->next;
1070 /*----------------------------------------------------------------
1071 * prism2sta_inf_handover
1073 * Handles the receipt of a Handover info frame. Should only be present
1077 * wlandev wlan device structure
1078 * inf ptr to info frame (contents in hfa384x order)
1087 ----------------------------------------------------------------*/
1088 static void prism2sta_inf_handover(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
1091 WLAN_LOG_DEBUG(2,"received infoframe:HANDOVER (unhandled)\n");
1097 /*----------------------------------------------------------------
1098 * prism2sta_inf_tallies
1100 * Handles the receipt of a CommTallies info frame.
1103 * wlandev wlan device structure
1104 * inf ptr to info frame (contents in hfa384x order)
1113 ----------------------------------------------------------------*/
1114 static void prism2sta_inf_tallies(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
1116 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1126 ** Determine if these are 16-bit or 32-bit tallies, based on the
1127 ** record length of the info record.
1130 cnt = sizeof(hfa384x_CommTallies32_t) / sizeof(u32);
1131 if (inf->framelen > 22) {
1132 dst = (u32 *) &hw->tallies;
1133 src32 = (u32 *) &inf->info.commtallies32;
1134 for (i = 0; i < cnt; i++, dst++, src32++)
1135 *dst += hfa384x2host_32(*src32);
1137 dst = (u32 *) &hw->tallies;
1138 src16 = (u16 *) &inf->info.commtallies16;
1139 for (i = 0; i < cnt; i++, dst++, src16++)
1140 *dst += hfa384x2host_16(*src16);
1148 /*----------------------------------------------------------------
1149 * prism2sta_inf_scanresults
1151 * Handles the receipt of a Scan Results info frame.
1154 * wlandev wlan device structure
1155 * inf ptr to info frame (contents in hfa384x order)
1164 ----------------------------------------------------------------*/
1165 static void prism2sta_inf_scanresults(wlandevice_t *wlandev,
1166 hfa384x_InfFrame_t *inf)
1169 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1171 hfa384x_ScanResult_t *sr = &(inf->info.scanresult);
1173 hfa384x_JoinRequest_data_t joinreq;
1177 /* Get the number of results, first in bytes, then in results */
1178 nbss = (inf->framelen * sizeof(u16)) -
1179 sizeof(inf->infotype) -
1180 sizeof(inf->info.scanresult.scanreason);
1181 nbss /= sizeof(hfa384x_ScanResultSub_t);
1184 WLAN_LOG_DEBUG(1,"rx scanresults, reason=%d, nbss=%d:\n",
1185 inf->info.scanresult.scanreason, nbss);
1186 for ( i = 0; i < nbss; i++) {
1187 WLAN_LOG_DEBUG(1, "chid=%d anl=%d sl=%d bcnint=%d\n",
1191 sr->result[i].bcnint);
1192 WLAN_LOG_DEBUG(1, " capinfo=0x%04x proberesp_rate=%d\n",
1193 sr->result[i].capinfo,
1194 sr->result[i].proberesp_rate);
1196 /* issue a join request */
1197 joinreq.channel = sr->result[0].chid;
1198 memcpy( joinreq.bssid, sr->result[0].bssid, WLAN_BSSID_LEN);
1199 result = hfa384x_drvr_setconfig( hw,
1200 HFA384x_RID_JOINREQUEST,
1201 &joinreq, HFA384x_RID_JOINREQUEST_LEN);
1203 WLAN_LOG_ERROR("setconfig(joinreq) failed, result=%d\n", result);
1210 /*----------------------------------------------------------------
1211 * prism2sta_inf_hostscanresults
1213 * Handles the receipt of a Scan Results info frame.
1216 * wlandev wlan device structure
1217 * inf ptr to info frame (contents in hfa384x order)
1226 ----------------------------------------------------------------*/
1227 static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev,
1228 hfa384x_InfFrame_t *inf)
1230 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1234 nbss = (inf->framelen - 3) / 32;
1235 WLAN_LOG_DEBUG(1, "Received %d hostscan results\n", nbss);
1240 if (hw->scanresults)
1241 kfree(hw->scanresults);
1243 hw->scanresults = kmalloc(sizeof(hfa384x_InfFrame_t), GFP_ATOMIC);
1244 memcpy(hw->scanresults, inf, sizeof(hfa384x_InfFrame_t));
1249 /* Notify/wake the sleeping caller. */
1250 hw->scanflag = nbss;
1251 wake_up_interruptible(&hw->cmdq);
1256 /*----------------------------------------------------------------
1257 * prism2sta_inf_chinforesults
1259 * Handles the receipt of a Channel Info Results info frame.
1262 * wlandev wlan device structure
1263 * inf ptr to info frame (contents in hfa384x order)
1272 ----------------------------------------------------------------*/
1273 static void prism2sta_inf_chinforesults(wlandevice_t *wlandev,
1274 hfa384x_InfFrame_t *inf)
1276 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1280 hw->channel_info.results.scanchannels =
1281 hfa384x2host_16(inf->info.chinforesult.scanchannels);
1283 memcpy(&inf->info.chinforesult, &hw->channel_info.results, sizeof(hfa384x_ChInfoResult_t));
1286 for (i=0, n=0; i<HFA384x_CHINFORESULT_MAX; i++) {
1287 if (hw->channel_info.results.scanchannels & (1<<i)) {
1288 int channel=hfa384x2host_16(inf->info.chinforesult.result[n].chid)-1;
1289 hfa384x_ChInfoResultSub_t *chinforesult=&hw->channel_info.results.result[channel];
1290 chinforesult->chid = channel;
1291 chinforesult->anl = hfa384x2host_16(inf->info.chinforesult.result[n].anl);
1292 chinforesult->pnl = hfa384x2host_16(inf->info.chinforesult.result[n].pnl);
1293 chinforesult->active = hfa384x2host_16(inf->info.chinforesult.result[n].active);
1294 WLAN_LOG_DEBUG(2, "chinfo: channel %d, %s level (avg/peak)=%d/%d dB, pcf %d\n",
1296 chinforesult->active &
1297 HFA384x_CHINFORESULT_BSSACTIVE ? "signal" : "noise",
1298 chinforesult->anl, chinforesult->pnl,
1299 chinforesult->active & HFA384x_CHINFORESULT_PCFACTIVE ? 1 : 0
1304 atomic_set(&hw->channel_info.done, 2);
1306 hw->channel_info.count = n;
1311 void prism2sta_processing_defer(struct work_struct *data)
1313 hfa384x_t *hw = container_of(data, struct hfa384x, link_bh);
1314 wlandevice_t *wlandev = hw->wlandev;
1315 hfa384x_bytestr32_t ssid;
1319 /* First let's process the auth frames */
1321 struct sk_buff *skb;
1322 hfa384x_InfFrame_t *inf;
1324 while ( (skb = skb_dequeue(&hw->authq)) ) {
1325 inf = (hfa384x_InfFrame_t *) skb->data;
1326 prism2sta_inf_authreq_defer(wlandev, inf);
1331 /* Now let's handle the linkstatus stuff */
1332 if (hw->link_status == hw->link_status_new)
1335 hw->link_status = hw->link_status_new;
1337 switch(hw->link_status) {
1338 case HFA384x_LINK_NOTCONNECTED:
1339 /* I'm currently assuming that this is the initial link
1340 * state. It should only be possible immediately
1341 * following an Enable command.
1343 * Block Transmits, Ignore receives of data frames
1345 netif_carrier_off(wlandev->netdev);
1347 WLAN_LOG_INFO("linkstatus=NOTCONNECTED (unhandled)\n");
1350 case HFA384x_LINK_CONNECTED:
1351 /* This one indicates a successful scan/join/auth/assoc.
1352 * When we have the full MLME complement, this event will
1353 * signify successful completion of both mlme_authenticate
1354 * and mlme_associate. State management will get a little
1357 * Indicate authentication and/or association
1358 * Enable Transmits, Receives and pass up data frames
1361 netif_carrier_on(wlandev->netdev);
1363 /* If we are joining a specific AP, set our state and reset retries */
1364 if(hw->join_ap == 1)
1366 hw->join_retries = 60;
1368 /* Don't call this in monitor mode */
1369 if ( wlandev->netdev->type == ARPHRD_ETHER ) {
1372 WLAN_LOG_INFO("linkstatus=CONNECTED\n");
1374 /* For non-usb devices, we can use the sync versions */
1375 /* Collect the BSSID, and set state to allow tx */
1377 result = hfa384x_drvr_getconfig(hw,
1378 HFA384x_RID_CURRENTBSSID,
1379 wlandev->bssid, WLAN_BSSID_LEN);
1382 "getconfig(0x%02x) failed, result = %d\n",
1383 HFA384x_RID_CURRENTBSSID, result);
1387 result = hfa384x_drvr_getconfig(hw,
1388 HFA384x_RID_CURRENTSSID,
1389 &ssid, sizeof(ssid));
1392 "getconfig(0x%02x) failed, result = %d\n",
1393 HFA384x_RID_CURRENTSSID, result);
1396 prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid,
1397 (p80211pstrd_t *) &wlandev->ssid);
1399 /* Collect the port status */
1400 result = hfa384x_drvr_getconfig16(hw,
1401 HFA384x_RID_PORTSTATUS, &portstatus);
1404 "getconfig(0x%02x) failed, result = %d\n",
1405 HFA384x_RID_PORTSTATUS, result);
1409 (portstatus == HFA384x_PSTATUS_CONN_IBSS) ?
1410 WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA;
1412 /* Get the ball rolling on the comms quality stuff */
1413 prism2sta_commsqual_defer(&hw->commsqual_bh);
1417 case HFA384x_LINK_DISCONNECTED:
1418 /* This one indicates that our association is gone. We've
1419 * lost connection with the AP and/or been disassociated.
1420 * This indicates that the MAC has completely cleared it's
1421 * associated state. We * should send a deauth indication
1422 * (implying disassoc) up * to the MLME.
1424 * Indicate Deauthentication
1425 * Block Transmits, Ignore receives of data frames
1427 if(hw->join_ap == 2)
1429 hfa384x_JoinRequest_data_t joinreq;
1430 joinreq = hw->joinreq;
1431 /* Send the join request */
1432 hfa384x_drvr_setconfig( hw,
1433 HFA384x_RID_JOINREQUEST,
1434 &joinreq, HFA384x_RID_JOINREQUEST_LEN);
1435 WLAN_LOG_INFO("linkstatus=DISCONNECTED (re-submitting join)\n");
1437 if (wlandev->netdev->type == ARPHRD_ETHER)
1438 WLAN_LOG_INFO("linkstatus=DISCONNECTED (unhandled)\n");
1440 wlandev->macmode = WLAN_MACMODE_NONE;
1442 netif_carrier_off(wlandev->netdev);
1446 case HFA384x_LINK_AP_CHANGE:
1447 /* This one indicates that the MAC has decided to and
1448 * successfully completed a change to another AP. We
1449 * should probably implement a reassociation indication
1450 * in response to this one. I'm thinking that the the
1451 * p80211 layer needs to be notified in case of
1452 * buffering/queueing issues. User mode also needs to be
1453 * notified so that any BSS dependent elements can be
1455 * associated state. We * should send a deauth indication
1456 * (implying disassoc) up * to the MLME.
1458 * Indicate Reassociation
1459 * Enable Transmits, Receives and pass up data frames
1461 WLAN_LOG_INFO("linkstatus=AP_CHANGE\n");
1463 result = hfa384x_drvr_getconfig(hw,
1464 HFA384x_RID_CURRENTBSSID,
1465 wlandev->bssid, WLAN_BSSID_LEN);
1468 "getconfig(0x%02x) failed, result = %d\n",
1469 HFA384x_RID_CURRENTBSSID, result);
1473 result = hfa384x_drvr_getconfig(hw,
1474 HFA384x_RID_CURRENTSSID,
1475 &ssid, sizeof(ssid));
1478 "getconfig(0x%02x) failed, result = %d\n",
1479 HFA384x_RID_CURRENTSSID, result);
1482 prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid,
1483 (p80211pstrd_t *) &wlandev->ssid);
1486 hw->link_status = HFA384x_LINK_CONNECTED;
1487 netif_carrier_on(wlandev->netdev);
1491 case HFA384x_LINK_AP_OUTOFRANGE:
1492 /* This one indicates that the MAC has decided that the
1493 * AP is out of range, but hasn't found a better candidate
1494 * so the MAC maintains its "associated" state in case
1495 * we get back in range. We should block transmits and
1496 * receives in this state. Do we need an indication here?
1497 * Probably not since a polling user-mode element would
1498 * get this status from from p2PortStatus(FD40). What about
1501 * Block Transmits, Ignore receives of data frames
1503 WLAN_LOG_INFO("linkstatus=AP_OUTOFRANGE (unhandled)\n");
1505 netif_carrier_off(wlandev->netdev);
1509 case HFA384x_LINK_AP_INRANGE:
1510 /* This one indicates that the MAC has decided that the
1511 * AP is back in range. We continue working with our
1512 * existing association.
1514 * Enable Transmits, Receives and pass up data frames
1516 WLAN_LOG_INFO("linkstatus=AP_INRANGE\n");
1518 hw->link_status = HFA384x_LINK_CONNECTED;
1519 netif_carrier_on(wlandev->netdev);
1523 case HFA384x_LINK_ASSOCFAIL:
1524 /* This one is actually a peer to CONNECTED. We've
1525 * requested a join for a given SSID and optionally BSSID.
1526 * We can use this one to indicate authentication and
1527 * association failures. The trick is going to be
1528 * 1) identifying the failure, and 2) state management.
1530 * Disable Transmits, Ignore receives of data frames
1532 if(hw->join_ap && --hw->join_retries > 0)
1534 hfa384x_JoinRequest_data_t joinreq;
1535 joinreq = hw->joinreq;
1536 /* Send the join request */
1537 hfa384x_drvr_setconfig( hw,
1538 HFA384x_RID_JOINREQUEST,
1539 &joinreq, HFA384x_RID_JOINREQUEST_LEN);
1540 WLAN_LOG_INFO("linkstatus=ASSOCFAIL (re-submitting join)\n");
1542 WLAN_LOG_INFO("linkstatus=ASSOCFAIL (unhandled)\n");
1545 netif_carrier_off(wlandev->netdev);
1550 /* This is bad, IO port problems? */
1552 "unknown linkstatus=0x%02x\n", hw->link_status);
1557 wlandev->linkstatus = (hw->link_status == HFA384x_LINK_CONNECTED);
1559 p80211wext_event_associated(wlandev, wlandev->linkstatus);
1566 /*----------------------------------------------------------------
1567 * prism2sta_inf_linkstatus
1569 * Handles the receipt of a Link Status info frame.
1572 * wlandev wlan device structure
1573 * inf ptr to info frame (contents in hfa384x order)
1582 ----------------------------------------------------------------*/
1583 static void prism2sta_inf_linkstatus(wlandevice_t *wlandev,
1584 hfa384x_InfFrame_t *inf)
1586 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1590 hw->link_status_new = hfa384x2host_16(inf->info.linkstatus.linkstatus);
1592 schedule_work(&hw->link_bh);
1598 /*----------------------------------------------------------------
1599 * prism2sta_inf_assocstatus
1601 * Handles the receipt of an Association Status info frame. Should
1602 * be present in APs only.
1605 * wlandev wlan device structure
1606 * inf ptr to info frame (contents in hfa384x order)
1615 ----------------------------------------------------------------*/
1616 static void prism2sta_inf_assocstatus(wlandevice_t *wlandev,
1617 hfa384x_InfFrame_t *inf)
1619 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1620 hfa384x_AssocStatus_t rec;
1625 memcpy(&rec, &inf->info.assocstatus, sizeof(rec));
1626 rec.assocstatus = hfa384x2host_16(rec.assocstatus);
1627 rec.reason = hfa384x2host_16(rec.reason);
1630 ** Find the address in the list of authenticated stations. If it wasn't
1631 ** found, then this address has not been previously authenticated and
1632 ** something weird has happened if this is anything other than an
1633 ** "authentication failed" message. If the address was found, then
1634 ** set the "associated" flag for that station, based on whether the
1635 ** station is associating or losing its association. Something weird
1636 ** has also happened if we find the address in the list of authenticated
1637 ** stations but we are getting an "authentication failed" message.
1640 for (i = 0; i < hw->authlist.cnt; i++)
1641 if (memcmp(rec.sta_addr, hw->authlist.addr[i], WLAN_ADDR_LEN) == 0)
1644 if (i >= hw->authlist.cnt) {
1645 if (rec.assocstatus != HFA384x_ASSOCSTATUS_AUTHFAIL)
1646 WLAN_LOG_WARNING("assocstatus info frame received for non-authenticated station.\n");
1648 hw->authlist.assoc[i] =
1649 (rec.assocstatus == HFA384x_ASSOCSTATUS_STAASSOC ||
1650 rec.assocstatus == HFA384x_ASSOCSTATUS_REASSOC);
1652 if (rec.assocstatus == HFA384x_ASSOCSTATUS_AUTHFAIL)
1653 WLAN_LOG_WARNING("authfail assocstatus info frame received for authenticated station.\n");
1661 /*----------------------------------------------------------------
1662 * prism2sta_inf_authreq
1664 * Handles the receipt of an Authentication Request info frame. Should
1665 * be present in APs only.
1668 * wlandev wlan device structure
1669 * inf ptr to info frame (contents in hfa384x order)
1679 ----------------------------------------------------------------*/
1680 static void prism2sta_inf_authreq(wlandevice_t *wlandev,
1681 hfa384x_InfFrame_t *inf)
1683 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1684 struct sk_buff *skb;
1688 skb = dev_alloc_skb(sizeof(*inf));
1690 skb_put(skb, sizeof(*inf));
1691 memcpy(skb->data, inf, sizeof(*inf));
1692 skb_queue_tail(&hw->authq, skb);
1693 schedule_work(&hw->link_bh);
1699 static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev,
1700 hfa384x_InfFrame_t *inf)
1702 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1703 hfa384x_authenticateStation_data_t rec;
1705 int i, added, result, cnt;
1711 ** Build the AuthenticateStation record. Initialize it for denying
1715 memcpy(rec.address, inf->info.authreq.sta_addr, WLAN_ADDR_LEN);
1716 rec.status = P80211ENUM_status_unspec_failure;
1719 ** Authenticate based on the access mode.
1722 switch (hw->accessmode) {
1723 case WLAN_ACCESS_NONE:
1726 ** Deny all new authentications. However, if a station
1727 ** is ALREADY authenticated, then accept it.
1730 for (i = 0; i < hw->authlist.cnt; i++)
1731 if (memcmp(rec.address, hw->authlist.addr[i],
1732 WLAN_ADDR_LEN) == 0) {
1733 rec.status = P80211ENUM_status_successful;
1739 case WLAN_ACCESS_ALL:
1742 ** Allow all authentications.
1745 rec.status = P80211ENUM_status_successful;
1748 case WLAN_ACCESS_ALLOW:
1751 ** Only allow the authentication if the MAC address
1752 ** is in the list of allowed addresses.
1754 ** Since this is the interrupt handler, we may be here
1755 ** while the access list is in the middle of being
1756 ** updated. Choose the list which is currently okay.
1757 ** See "prism2mib_priv_accessallow()" for details.
1760 if (hw->allow.modify == 0) {
1761 cnt = hw->allow.cnt;
1762 addr = hw->allow.addr[0];
1764 cnt = hw->allow.cnt1;
1765 addr = hw->allow.addr1[0];
1768 for (i = 0; i < cnt; i++, addr += WLAN_ADDR_LEN)
1769 if (memcmp(rec.address, addr, WLAN_ADDR_LEN) == 0) {
1770 rec.status = P80211ENUM_status_successful;
1776 case WLAN_ACCESS_DENY:
1779 ** Allow the authentication UNLESS the MAC address is
1780 ** in the list of denied addresses.
1782 ** Since this is the interrupt handler, we may be here
1783 ** while the access list is in the middle of being
1784 ** updated. Choose the list which is currently okay.
1785 ** See "prism2mib_priv_accessdeny()" for details.
1788 if (hw->deny.modify == 0) {
1790 addr = hw->deny.addr[0];
1792 cnt = hw->deny.cnt1;
1793 addr = hw->deny.addr1[0];
1796 rec.status = P80211ENUM_status_successful;
1798 for (i = 0; i < cnt; i++, addr += WLAN_ADDR_LEN)
1799 if (memcmp(rec.address, addr, WLAN_ADDR_LEN) == 0) {
1800 rec.status = P80211ENUM_status_unspec_failure;
1808 ** If the authentication is okay, then add the MAC address to the list
1809 ** of authenticated stations. Don't add the address if it is already in
1810 ** the list. (802.11b does not seem to disallow a station from issuing
1811 ** an authentication request when the station is already authenticated.
1812 ** Does this sort of thing ever happen? We might as well do the check
1818 if (rec.status == P80211ENUM_status_successful) {
1819 for (i = 0; i < hw->authlist.cnt; i++)
1820 if (memcmp(rec.address, hw->authlist.addr[i], WLAN_ADDR_LEN) == 0)
1823 if (i >= hw->authlist.cnt) {
1824 if (hw->authlist.cnt >= WLAN_AUTH_MAX) {
1825 rec.status = P80211ENUM_status_ap_full;
1827 memcpy(hw->authlist.addr[hw->authlist.cnt],
1828 rec.address, WLAN_ADDR_LEN);
1836 ** Send back the results of the authentication. If this doesn't work,
1837 ** then make sure to remove the address from the authenticated list if
1841 rec.status = host2hfa384x_16(rec.status);
1842 rec.algorithm = inf->info.authreq.algorithm;
1844 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_AUTHENTICATESTA,
1847 if (added) hw->authlist.cnt--;
1848 WLAN_LOG_ERROR("setconfig(authenticatestation) failed, result=%d\n", result);
1857 /*----------------------------------------------------------------
1858 * prism2sta_inf_psusercnt
1860 * Handles the receipt of a PowerSaveUserCount info frame. Should
1861 * be present in APs only.
1864 * wlandev wlan device structure
1865 * inf ptr to info frame (contents in hfa384x order)
1874 ----------------------------------------------------------------*/
1875 static void prism2sta_inf_psusercnt(wlandevice_t *wlandev,
1876 hfa384x_InfFrame_t *inf)
1878 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1882 hw->psusercount = hfa384x2host_16(inf->info.psusercnt.usercnt);
1889 /*----------------------------------------------------------------
1892 * Handles the DTIM early warning event.
1895 * wlandev wlan device structure
1904 ----------------------------------------------------------------*/
1905 void prism2sta_ev_dtim(wlandevice_t *wlandev)
1908 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1911 WLAN_LOG_DEBUG(3, "DTIM event, currently unhandled.\n");
1917 /*----------------------------------------------------------------
1918 * prism2sta_ev_infdrop
1920 * Handles the InfDrop event.
1923 * wlandev wlan device structure
1932 ----------------------------------------------------------------*/
1933 void prism2sta_ev_infdrop(wlandevice_t *wlandev)
1936 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1939 WLAN_LOG_DEBUG(3, "Info frame dropped due to card mem low.\n");
1945 /*----------------------------------------------------------------
1948 * Handles the Info event.
1951 * wlandev wlan device structure
1952 * inf ptr to a generic info frame
1961 ----------------------------------------------------------------*/
1962 void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
1965 inf->infotype = hfa384x2host_16(inf->infotype);
1967 switch ( inf->infotype ) {
1968 case HFA384x_IT_HANDOVERADDR:
1969 prism2sta_inf_handover(wlandev, inf);
1971 case HFA384x_IT_COMMTALLIES:
1972 prism2sta_inf_tallies(wlandev, inf);
1974 case HFA384x_IT_HOSTSCANRESULTS:
1975 prism2sta_inf_hostscanresults(wlandev, inf);
1977 case HFA384x_IT_SCANRESULTS:
1978 prism2sta_inf_scanresults(wlandev, inf);
1980 case HFA384x_IT_CHINFORESULTS:
1981 prism2sta_inf_chinforesults(wlandev, inf);
1983 case HFA384x_IT_LINKSTATUS:
1984 prism2sta_inf_linkstatus(wlandev, inf);
1986 case HFA384x_IT_ASSOCSTATUS:
1987 prism2sta_inf_assocstatus(wlandev, inf);
1989 case HFA384x_IT_AUTHREQ:
1990 prism2sta_inf_authreq(wlandev, inf);
1992 case HFA384x_IT_PSUSERCNT:
1993 prism2sta_inf_psusercnt(wlandev, inf);
1995 case HFA384x_IT_KEYIDCHANGED:
1996 WLAN_LOG_WARNING("Unhandled IT_KEYIDCHANGED\n");
1998 case HFA384x_IT_ASSOCREQ:
1999 WLAN_LOG_WARNING("Unhandled IT_ASSOCREQ\n");
2001 case HFA384x_IT_MICFAILURE:
2002 WLAN_LOG_WARNING("Unhandled IT_MICFAILURE\n");
2006 "Unknown info type=0x%02x\n", inf->infotype);
2014 /*----------------------------------------------------------------
2015 * prism2sta_ev_txexc
2017 * Handles the TxExc event. A Transmit Exception event indicates
2018 * that the MAC's TX process was unsuccessful - so the packet did
2019 * not get transmitted.
2022 * wlandev wlan device structure
2023 * status tx frame status word
2032 ----------------------------------------------------------------*/
2033 void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status)
2037 WLAN_LOG_DEBUG(3, "TxExc status=0x%x.\n", status);
2044 /*----------------------------------------------------------------
2047 * Handles the Tx event.
2050 * wlandev wlan device structure
2051 * status tx frame status word
2059 ----------------------------------------------------------------*/
2060 void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status)
2063 WLAN_LOG_DEBUG(4, "Tx Complete, status=0x%04x\n", status);
2064 /* update linux network stats */
2065 wlandev->linux_stats.tx_packets++;
2071 /*----------------------------------------------------------------
2074 * Handles the Rx event.
2077 * wlandev wlan device structure
2086 ----------------------------------------------------------------*/
2087 void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb)
2091 p80211netdev_rx(wlandev, skb);
2097 /*----------------------------------------------------------------
2098 * prism2sta_ev_alloc
2100 * Handles the Alloc event.
2103 * wlandev wlan device structure
2112 ----------------------------------------------------------------*/
2113 void prism2sta_ev_alloc(wlandevice_t *wlandev)
2117 p80211netdev_wake_queue(wlandev);
2123 /*----------------------------------------------------------------
2126 * Called at module init time. This creates the wlandevice_t structure
2127 * and initializes it with relevant bits.
2133 * the created wlandevice_t structure.
2136 * also allocates the priv/hw structures.
2141 ----------------------------------------------------------------*/
2142 static wlandevice_t *create_wlan(void)
2144 wlandevice_t *wlandev = NULL;
2145 hfa384x_t *hw = NULL;
2147 /* Alloc our structures */
2148 wlandev = kmalloc(sizeof(wlandevice_t), GFP_KERNEL);
2149 hw = kmalloc(sizeof(hfa384x_t), GFP_KERNEL);
2151 if (!wlandev || !hw) {
2152 WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
2153 if (wlandev) kfree(wlandev);
2158 /* Clear all the structs */
2159 memset(wlandev, 0, sizeof(wlandevice_t));
2160 memset(hw, 0, sizeof(hfa384x_t));
2162 /* Initialize the network device object. */
2163 wlandev->nsdname = dev_info;
2164 wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING;
2166 wlandev->open = prism2sta_open;
2167 wlandev->close = prism2sta_close;
2168 wlandev->reset = prism2sta_reset;
2169 wlandev->txframe = prism2sta_txframe;
2170 wlandev->mlmerequest = prism2sta_mlmerequest;
2171 wlandev->set_multicast_list = prism2sta_setmulticast;
2172 wlandev->tx_timeout = hfa384x_tx_timeout;
2174 wlandev->nsdcaps = P80211_NSDCAP_HWFRAGMENT |
2175 P80211_NSDCAP_AUTOJOIN;
2177 /* Initialize the device private data stucture. */
2178 hw->dot11_desired_bss_type = 1;
2183 void prism2sta_commsqual_defer(struct work_struct *data)
2185 hfa384x_t *hw = container_of(data, struct hfa384x, commsqual_bh);
2186 wlandevice_t *wlandev = hw->wlandev;
2187 hfa384x_bytestr32_t ssid;
2192 if (hw->wlandev->hwremoved)
2195 /* we don't care if we're in AP mode */
2196 if ((wlandev->macmode == WLAN_MACMODE_NONE) ||
2197 (wlandev->macmode == WLAN_MACMODE_ESS_AP)) {
2201 /* It only makes sense to poll these in non-IBSS */
2202 if (wlandev->macmode != WLAN_MACMODE_IBSS_STA) {
2203 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DBMCOMMSQUALITY,
2205 HFA384x_RID_DBMCOMMSQUALITY_LEN);
2208 WLAN_LOG_ERROR("error fetching commsqual\n");
2212 // qual.CQ_currBSS; // link
2213 // ASL_currBSS; // level
2214 // qual.ANL_currFC; // noise
2216 WLAN_LOG_DEBUG(3, "commsqual %d %d %d\n",
2217 hfa384x2host_16(hw->qual.CQ_currBSS),
2218 hfa384x2host_16(hw->qual.ASL_currBSS),
2219 hfa384x2host_16(hw->qual.ANL_currFC));
2222 /* Lastly, we need to make sure the BSSID didn't change on us */
2223 result = hfa384x_drvr_getconfig(hw,
2224 HFA384x_RID_CURRENTBSSID,
2225 wlandev->bssid, WLAN_BSSID_LEN);
2228 "getconfig(0x%02x) failed, result = %d\n",
2229 HFA384x_RID_CURRENTBSSID, result);
2233 result = hfa384x_drvr_getconfig(hw,
2234 HFA384x_RID_CURRENTSSID,
2235 &ssid, sizeof(ssid));
2238 "getconfig(0x%02x) failed, result = %d\n",
2239 HFA384x_RID_CURRENTSSID, result);
2242 prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid,
2243 (p80211pstrd_t *) &wlandev->ssid);
2246 /* Reschedule timer */
2247 mod_timer(&hw->commsqual_timer, jiffies + HZ);
2253 void prism2sta_commsqual_timer(unsigned long data)
2255 hfa384x_t *hw = (hfa384x_t *) data;
2259 schedule_work(&hw->commsqual_bh);