]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/staging/wlan-ng/prism2sta.c
Staging: wlan-ng: Delete a pile of unused mibs. And fix WEXT SET_TXPOWER.
[mirror_ubuntu-artful-kernel.git] / drivers / staging / wlan-ng / prism2sta.c
CommitLineData
00b3ed16
GKH
1/* src/prism2/driver/prism2sta.c
2*
3* Implements the station functionality for prism2
4*
5* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
6* --------------------------------------------------------------------
7*
8* linux-wlan
9*
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/
14*
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.
19*
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.
30*
31* --------------------------------------------------------------------
32*
33* Inquiries regarding the linux-wlan Open Source project can be
34* made directly to:
35*
36* AbsoluteValue Systems Inc.
37* info@linux-wlan.com
38* http://www.linux-wlan.com
39*
40* --------------------------------------------------------------------
41*
42* Portions of the development of this software were funded by
43* Intersil Corporation as part of PRISM(R) chipset product development.
44*
45* --------------------------------------------------------------------
46*
47* This file implements the module and linux pcmcia routines for the
48* prism2 driver.
49*
50* --------------------------------------------------------------------
51*/
52
53/*================================================================*/
54/* System Includes */
55#define WLAN_DBVAR prism2_debug
56
00b3ed16 57#include <linux/version.h>
00b3ed16 58#include <linux/module.h>
00b3ed16 59#include <linux/moduleparam.h>
00b3ed16
GKH
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>
00b3ed16 67#include <linux/workqueue.h>
00b3ed16
GKH
68
69#include <asm/io.h>
70#include <linux/delay.h>
71#include <asm/byteorder.h>
72#include <linux/if_arp.h>
73
00b3ed16
GKH
74#include "wlan_compat.h"
75
00b3ed16
GKH
76/*================================================================*/
77/* Project Includes */
78
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"
88#include "hfa384x.h"
89#include "prism2mgmt.h"
90
91/*================================================================*/
92/* Local Constants */
93
94/*================================================================*/
95/* Local Macros */
96
97/*================================================================*/
98/* Local Types */
99
100/*================================================================*/
101/* Local Static Definitions */
102
00b3ed16 103typedef char* dev_info_t;
00b3ed16 104
dff1dc8c 105static dev_info_t dev_info = "prism2_usb";
00b3ed16
GKH
106
107static wlandevice_t *create_wlan(void);
108
109/*----------------------------------------------------------------*/
110/* --Module Parameters */
111
112int prism2_reset_holdtime=30; /* Reset hold time in ms */
113int prism2_reset_settletime=100; /* Reset settle time in ms */
114
00b3ed16 115static int prism2_doreset=0; /* Do a reset at init? */
00b3ed16
GKH
116
117#ifdef WLAN_INCLUDE_DEBUG
118int prism2_debug=0;
119module_param( prism2_debug, int, 0644);
120MODULE_PARM_DESC(prism2_debug, "prism2 debugging");
121#endif
122
123module_param( prism2_doreset, int, 0644);
124MODULE_PARM_DESC(prism2_doreset, "Issue a reset on initialization");
125
126module_param( prism2_reset_holdtime, int, 0644);
127MODULE_PARM_DESC( prism2_reset_holdtime, "reset hold time in ms");
128module_param( prism2_reset_settletime, int, 0644);
129MODULE_PARM_DESC( prism2_reset_settletime, "reset settle time in ms");
130
00b3ed16
GKH
131MODULE_LICENSE("Dual MPL/GPL");
132
133/*================================================================*/
134/* Local Function Declarations */
135
136static int prism2sta_open(wlandevice_t *wlandev);
137static int prism2sta_close(wlandevice_t *wlandev);
138static void prism2sta_reset(wlandevice_t *wlandev );
139static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb, p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep);
140static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg);
141static int prism2sta_getcardinfo(wlandevice_t *wlandev);
142static int prism2sta_globalsetup(wlandevice_t *wlandev);
143static int prism2sta_setmulticast(wlandevice_t *wlandev,
144 netdevice_t *dev);
145
146static void prism2sta_inf_handover(
147 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
148static void prism2sta_inf_tallies(
149 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
150static void prism2sta_inf_hostscanresults(
151 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
152static void prism2sta_inf_scanresults(
153 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
154static void prism2sta_inf_chinforesults(
155 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
156static void prism2sta_inf_linkstatus(
157 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
158static void prism2sta_inf_assocstatus(
159 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
160static void prism2sta_inf_authreq(
161 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
162static void prism2sta_inf_authreq_defer(
163 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
164static void prism2sta_inf_psusercnt(
165 wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
166
00b3ed16
GKH
167/*================================================================*/
168/* Function Definitions */
169
170/*----------------------------------------------------------------
171* dmpmem
172*
173* Debug utility function to dump memory to the kernel debug log.
174*
175* Arguments:
176* buf ptr data we want dumped
177* len length of data
178*
179* Returns:
180* nothing
181* Side effects:
182*
183* Call context:
184* process thread
185* interrupt
186----------------------------------------------------------------*/
187inline void dmpmem(void *buf, int n)
188{
189 int c;
190 for ( c= 0; c < n; c++) {
191 if ( (c % 16) == 0 ) printk(KERN_DEBUG"dmp[%d]: ", c);
aaad4303 192 printk("%02x ", ((u8*)buf)[c]);
00b3ed16
GKH
193 if ( (c % 16) == 15 ) printk("\n");
194 }
195 if ( (c % 16) != 0 ) printk("\n");
196}
197
198
199/*----------------------------------------------------------------
200* prism2sta_open
201*
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
205* from clear to set.
206*
207* Arguments:
208* wlandev wlan device structure
209*
210* Returns:
211* 0 success
212* >0 f/w reported error
213* <0 driver reported error
214*
215* Side effects:
216*
217* Call context:
218* process thread
219----------------------------------------------------------------*/
220static int prism2sta_open(wlandevice_t *wlandev)
221{
222 DBFENTER;
223
00b3ed16
GKH
224 /* We don't currently have to do anything else.
225 * The setup of the MAC should be subsequently completed via
226 * the mlme commands.
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.
230 */
231
232 DBFEXIT;
233 return 0;
234}
235
236
237/*----------------------------------------------------------------
238* prism2sta_close
239*
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
243* from set to clear.
244*
245* Arguments:
246* wlandev wlan device structure
247*
248* Returns:
249* 0 success
250* >0 f/w reported error
251* <0 driver reported error
252*
253* Side effects:
254*
255* Call context:
256* process thread
257----------------------------------------------------------------*/
258static int prism2sta_close(wlandevice_t *wlandev)
259{
260 DBFENTER;
261
00b3ed16
GKH
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.
266 */
267
268 DBFEXIT;
269 return 0;
270}
271
272
273/*----------------------------------------------------------------
274* prism2sta_reset
275*
276* Not currently implented.
277*
278* Arguments:
279* wlandev wlan device structure
280* none
281*
282* Returns:
283* nothing
284*
285* Side effects:
286*
287* Call context:
288* process thread
289----------------------------------------------------------------*/
290static void prism2sta_reset(wlandevice_t *wlandev )
291{
292 DBFENTER;
293 DBFEXIT;
294 return;
295}
296
297
298/*----------------------------------------------------------------
299* prism2sta_txframe
300*
301* Takes a frame from p80211 and queues it for transmission.
302*
303* Arguments:
304* wlandev wlan device structure
305* pb packet buffer struct. Contains an 802.11
306* data frame.
307* p80211_hdr points to the 802.11 header for the packet.
308* Returns:
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
313*
314* Side effects:
315*
316* Call context:
317* process thread
318----------------------------------------------------------------*/
319static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb,
320 p80211_hdr_t *p80211_hdr,
321 p80211_metawep_t *p80211_wep)
322{
323 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
324 int result;
325 DBFENTER;
326
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));
330 }
331
332 result = hfa384x_drvr_txframe(hw, skb, p80211_hdr, p80211_wep);
333
334 DBFEXIT;
335 return result;
336}
337
338
339/*----------------------------------------------------------------
340* prism2sta_mlmerequest
341*
342* wlan command message handler. All we do here is pass the message
343* over to the prism2sta_mgmt_handler.
344*
345* Arguments:
346* wlandev wlan device structure
347* msg wlan command message
348* Returns:
349* 0 success
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
356* the message.
357*
358* Side effects:
359*
360* Call context:
361* process thread
362----------------------------------------------------------------*/
363static int prism2sta_mlmerequest(wlandevice_t *wlandev, p80211msg_t *msg)
364{
365 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
366
367 int result = 0;
368 DBFENTER;
369
370 switch( msg->msgcode )
371 {
372 case DIDmsg_dot11req_mibget :
373 WLAN_LOG_DEBUG(2,"Received mibget request\n");
374 result = prism2mgmt_mibset_mibget(wlandev, msg);
375 break;
376 case DIDmsg_dot11req_mibset :
377 WLAN_LOG_DEBUG(2,"Received mibset request\n");
378 result = prism2mgmt_mibset_mibget(wlandev, msg);
379 break;
00b3ed16
GKH
380 case DIDmsg_dot11req_scan :
381 WLAN_LOG_DEBUG(2,"Received scan request\n");
382 result = prism2mgmt_scan(wlandev, msg);
383 break;
384 case DIDmsg_dot11req_scan_results :
385 WLAN_LOG_DEBUG(2,"Received scan_results request\n");
386 result = prism2mgmt_scan_results(wlandev, msg);
387 break;
00b3ed16
GKH
388 case DIDmsg_dot11req_start :
389 WLAN_LOG_DEBUG(2,"Received mlme start request\n");
390 result = prism2mgmt_start(wlandev, msg);
391 break;
392 /*
393 * Prism2 specific messages
394 */
00b3ed16
GKH
395 case DIDmsg_p2req_readpda :
396 WLAN_LOG_DEBUG(2,"Received mlme readpda request\n");
397 result = prism2mgmt_readpda(wlandev, msg);
398 break;
00b3ed16
GKH
399 case DIDmsg_p2req_ramdl_state :
400 WLAN_LOG_DEBUG(2,"Received mlme ramdl_state request\n");
401 result = prism2mgmt_ramdl_state(wlandev, msg);
402 break;
403 case DIDmsg_p2req_ramdl_write :
404 WLAN_LOG_DEBUG(2,"Received mlme ramdl_write request\n");
405 result = prism2mgmt_ramdl_write(wlandev, msg);
406 break;
407 case DIDmsg_p2req_flashdl_state :
408 WLAN_LOG_DEBUG(2,"Received mlme flashdl_state request\n");
409 result = prism2mgmt_flashdl_state(wlandev, msg);
410 break;
411 case DIDmsg_p2req_flashdl_write :
412 WLAN_LOG_DEBUG(2,"Received mlme flashdl_write request\n");
413 result = prism2mgmt_flashdl_write(wlandev, msg);
414 break;
00b3ed16
GKH
415 /*
416 * Linux specific messages
417 */
418 case DIDmsg_lnxreq_hostwep :
419 break; // ignore me.
420 case DIDmsg_lnxreq_ifstate :
421 {
422 p80211msg_lnxreq_ifstate_t *ifstatemsg;
423 WLAN_LOG_DEBUG(2,"Received mlme ifstate request\n");
424 ifstatemsg = (p80211msg_lnxreq_ifstate_t*)msg;
425 result = prism2sta_ifstate(wlandev, ifstatemsg->ifstate.data);
426 ifstatemsg->resultcode.status =
427 P80211ENUM_msgitem_status_data_ok;
428 ifstatemsg->resultcode.data = result;
429 result = 0;
430 }
431 break;
432 case DIDmsg_lnxreq_wlansniff :
433 WLAN_LOG_DEBUG(2,"Received mlme wlansniff request\n");
434 result = prism2mgmt_wlansniff(wlandev, msg);
435 break;
436 case DIDmsg_lnxreq_autojoin :
437 WLAN_LOG_DEBUG(2,"Received mlme autojoin request\n");
438 result = prism2mgmt_autojoin(wlandev, msg);
439 break;
00b3ed16
GKH
440 case DIDmsg_lnxreq_commsquality: {
441 p80211msg_lnxreq_commsquality_t *qualmsg;
442
443 WLAN_LOG_DEBUG(2,"Received commsquality request\n");
444
00b3ed16
GKH
445 qualmsg = (p80211msg_lnxreq_commsquality_t*) msg;
446
447 qualmsg->link.status = P80211ENUM_msgitem_status_data_ok;
448 qualmsg->level.status = P80211ENUM_msgitem_status_data_ok;
449 qualmsg->noise.status = P80211ENUM_msgitem_status_data_ok;
450
451
452 qualmsg->link.data = hfa384x2host_16(hw->qual.CQ_currBSS);
453 qualmsg->level.data = hfa384x2host_16(hw->qual.ASL_currBSS);
454 qualmsg->noise.data = hfa384x2host_16(hw->qual.ANL_currFC);
455
456 break;
457 }
458 default:
459 WLAN_LOG_WARNING("Unknown mgmt request message 0x%08x", msg->msgcode);
460 break;
461 }
462
463 DBFEXIT;
464 return result;
465}
466
467
468/*----------------------------------------------------------------
469* prism2sta_ifstate
470*
471* Interface state. This is the primary WLAN interface enable/disable
472* handler. Following the driver/load/deviceprobe sequence, this
473* function must be called with a state of "enable" before any other
474* commands will be accepted.
475*
476* Arguments:
477* wlandev wlan device structure
478* msgp ptr to msg buffer
479*
480* Returns:
481* A p80211 message resultcode value.
482*
483* Side effects:
484*
485* Call context:
486* process thread (usually)
487* interrupt
488----------------------------------------------------------------*/
aaad4303 489u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate)
00b3ed16
GKH
490{
491 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
aaad4303 492 u32 result;
00b3ed16
GKH
493 DBFENTER;
494
495 result = P80211ENUM_resultcode_implementation_failure;
496
497 WLAN_LOG_DEBUG(2, "Current MSD state(%d), requesting(%d)\n",
498 wlandev->msdstate, ifstate);
499 switch (ifstate)
500 {
501 case P80211ENUM_ifstate_fwload:
502 switch (wlandev->msdstate) {
503 case WLAN_MSD_HWPRESENT:
504 wlandev->msdstate = WLAN_MSD_FWLOAD_PENDING;
505 /*
506 * Initialize the device+driver sufficiently
507 * for firmware loading.
508 */
00b3ed16
GKH
509 if ((result=hfa384x_drvr_start(hw))) {
510 WLAN_LOG_ERROR(
511 "hfa384x_drvr_start() failed,"
512 "result=%d\n", (int)result);
513 result =
514 P80211ENUM_resultcode_implementation_failure;
515 wlandev->msdstate = WLAN_MSD_HWPRESENT;
516 break;
517 }
00b3ed16
GKH
518 wlandev->msdstate = WLAN_MSD_FWLOAD;
519 result = P80211ENUM_resultcode_success;
520 break;
521 case WLAN_MSD_FWLOAD:
522 hfa384x_cmd_initialize(hw);
523 result = P80211ENUM_resultcode_success;
524 break;
525 case WLAN_MSD_RUNNING:
526 WLAN_LOG_WARNING(
527 "Cannot enter fwload state from enable state,"
528 "you must disable first.\n");
529 result = P80211ENUM_resultcode_invalid_parameters;
530 break;
531 case WLAN_MSD_HWFAIL:
532 default:
533 /* probe() had a problem or the msdstate contains
534 * an unrecognized value, there's nothing we can do.
535 */
536 result = P80211ENUM_resultcode_implementation_failure;
537 break;
538 }
539 break;
540 case P80211ENUM_ifstate_enable:
541 switch (wlandev->msdstate) {
542 case WLAN_MSD_HWPRESENT:
543 case WLAN_MSD_FWLOAD:
544 wlandev->msdstate = WLAN_MSD_RUNNING_PENDING;
545 /* Initialize the device+driver for full
546 * operation. Note that this might me an FWLOAD to
547 * to RUNNING transition so we must not do a chip
548 * or board level reset. Note that on failure,
549 * the MSD state is set to HWPRESENT because we
550 * can't make any assumptions about the state
551 * of the hardware or a previous firmware load.
552 */
553 if ((result=hfa384x_drvr_start(hw))) {
554 WLAN_LOG_ERROR(
555 "hfa384x_drvr_start() failed,"
556 "result=%d\n", (int)result);
557 result =
558 P80211ENUM_resultcode_implementation_failure;
559 wlandev->msdstate = WLAN_MSD_HWPRESENT;
560 break;
561 }
562
563 if ((result=prism2sta_getcardinfo(wlandev))) {
564 WLAN_LOG_ERROR(
565 "prism2sta_getcardinfo() failed,"
566 "result=%d\n", (int)result);
567 result =
568 P80211ENUM_resultcode_implementation_failure;
569 hfa384x_drvr_stop(hw);
570 wlandev->msdstate = WLAN_MSD_HWPRESENT;
571 break;
572 }
573 if ((result=prism2sta_globalsetup(wlandev))) {
574 WLAN_LOG_ERROR(
575 "prism2sta_globalsetup() failed,"
576 "result=%d\n", (int)result);
577 result =
578 P80211ENUM_resultcode_implementation_failure;
579 hfa384x_drvr_stop(hw);
580 wlandev->msdstate = WLAN_MSD_HWPRESENT;
581 break;
582 }
583 wlandev->msdstate = WLAN_MSD_RUNNING;
584 hw->join_ap = 0;
585 hw->join_retries = 60;
586 result = P80211ENUM_resultcode_success;
587 break;
588 case WLAN_MSD_RUNNING:
589 /* Do nothing, we're already in this state.*/
590 result = P80211ENUM_resultcode_success;
591 break;
592 case WLAN_MSD_HWFAIL:
593 default:
594 /* probe() had a problem or the msdstate contains
595 * an unrecognized value, there's nothing we can do.
596 */
597 result = P80211ENUM_resultcode_implementation_failure;
598 break;
599 }
600 break;
601 case P80211ENUM_ifstate_disable:
602 switch (wlandev->msdstate) {
603 case WLAN_MSD_HWPRESENT:
604 /* Do nothing, we're already in this state.*/
605 result = P80211ENUM_resultcode_success;
606 break;
607 case WLAN_MSD_FWLOAD:
608 case WLAN_MSD_RUNNING:
609 wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING;
610 /*
611 * TODO: Shut down the MAC completely. Here a chip
612 * or board level reset is probably called for.
613 * After a "disable" _all_ results are lost, even
614 * those from a fwload.
615 */
616 if (!wlandev->hwremoved)
617 netif_carrier_off(wlandev->netdev);
618
619 hfa384x_drvr_stop(hw);
620
621 wlandev->macmode = WLAN_MACMODE_NONE;
622 wlandev->msdstate = WLAN_MSD_HWPRESENT;
623 result = P80211ENUM_resultcode_success;
624 break;
625 case WLAN_MSD_HWFAIL:
626 default:
627 /* probe() had a problem or the msdstate contains
628 * an unrecognized value, there's nothing we can do.
629 */
630 result = P80211ENUM_resultcode_implementation_failure;
631 break;
632 }
633 break;
634 default:
635 result = P80211ENUM_resultcode_invalid_parameters;
636 break;
637 }
638
639 DBFEXIT;
640 return result;
641}
642
643
644/*----------------------------------------------------------------
645* prism2sta_getcardinfo
646*
647* Collect the NICID, firmware version and any other identifiers
648* we'd like to have in host-side data structures.
649*
650* Arguments:
651* wlandev wlan device structure
652*
653* Returns:
654* 0 success
655* >0 f/w reported error
656* <0 driver reported error
657*
658* Side effects:
659*
660* Call context:
661* Either.
662----------------------------------------------------------------*/
663static int prism2sta_getcardinfo(wlandevice_t *wlandev)
664{
665 int result = 0;
666 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
aaad4303
SP
667 u16 temp;
668 u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN];
00b3ed16
GKH
669 char pstr[(HFA384x_RID_NICSERIALNUMBER_LEN * 4) + 1];
670
671 DBFENTER;
672
673 /* Collect version and compatibility info */
674 /* Some are critical, some are not */
675 /* NIC identity */
676 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICIDENTITY,
677 &hw->ident_nic, sizeof(hfa384x_compident_t));
678 if ( result ) {
679 WLAN_LOG_ERROR("Failed to retrieve NICIDENTITY\n");
680 goto failed;
681 }
682
683 /* get all the nic id fields in host byte order */
684 hw->ident_nic.id = hfa384x2host_16(hw->ident_nic.id);
685 hw->ident_nic.variant = hfa384x2host_16(hw->ident_nic.variant);
686 hw->ident_nic.major = hfa384x2host_16(hw->ident_nic.major);
687 hw->ident_nic.minor = hfa384x2host_16(hw->ident_nic.minor);
688
689 WLAN_LOG_INFO( "ident: nic h/w: id=0x%02x %d.%d.%d\n",
690 hw->ident_nic.id, hw->ident_nic.major,
691 hw->ident_nic.minor, hw->ident_nic.variant);
692
693 /* Primary f/w identity */
694 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRIIDENTITY,
695 &hw->ident_pri_fw, sizeof(hfa384x_compident_t));
696 if ( result ) {
697 WLAN_LOG_ERROR("Failed to retrieve PRIIDENTITY\n");
698 goto failed;
699 }
700
701 /* get all the private fw id fields in host byte order */
702 hw->ident_pri_fw.id = hfa384x2host_16(hw->ident_pri_fw.id);
703 hw->ident_pri_fw.variant = hfa384x2host_16(hw->ident_pri_fw.variant);
704 hw->ident_pri_fw.major = hfa384x2host_16(hw->ident_pri_fw.major);
705 hw->ident_pri_fw.minor = hfa384x2host_16(hw->ident_pri_fw.minor);
706
707 WLAN_LOG_INFO( "ident: pri f/w: id=0x%02x %d.%d.%d\n",
708 hw->ident_pri_fw.id, hw->ident_pri_fw.major,
709 hw->ident_pri_fw.minor, hw->ident_pri_fw.variant);
710
711 /* Station (Secondary?) f/w identity */
712 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STAIDENTITY,
713 &hw->ident_sta_fw, sizeof(hfa384x_compident_t));
714 if ( result ) {
715 WLAN_LOG_ERROR("Failed to retrieve STAIDENTITY\n");
716 goto failed;
717 }
718
719 if (hw->ident_nic.id < 0x8000) {
720 WLAN_LOG_ERROR("FATAL: Card is not an Intersil Prism2/2.5/3\n");
721 result = -1;
722 goto failed;
723 }
724
725 /* get all the station fw id fields in host byte order */
726 hw->ident_sta_fw.id = hfa384x2host_16(hw->ident_sta_fw.id);
727 hw->ident_sta_fw.variant = hfa384x2host_16(hw->ident_sta_fw.variant);
728 hw->ident_sta_fw.major = hfa384x2host_16(hw->ident_sta_fw.major);
729 hw->ident_sta_fw.minor = hfa384x2host_16(hw->ident_sta_fw.minor);
730
731 /* strip out the 'special' variant bits */
732 hw->mm_mods = hw->ident_sta_fw.variant & (BIT14 | BIT15);
aaad4303 733 hw->ident_sta_fw.variant &= ~((u16)(BIT14 | BIT15));
00b3ed16
GKH
734
735 if ( hw->ident_sta_fw.id == 0x1f ) {
00b3ed16
GKH
736 WLAN_LOG_INFO(
737 "ident: sta f/w: id=0x%02x %d.%d.%d\n",
738 hw->ident_sta_fw.id, hw->ident_sta_fw.major,
739 hw->ident_sta_fw.minor, hw->ident_sta_fw.variant);
740 } else {
00b3ed16
GKH
741 WLAN_LOG_INFO(
742 "ident: ap f/w: id=0x%02x %d.%d.%d\n",
743 hw->ident_sta_fw.id, hw->ident_sta_fw.major,
744 hw->ident_sta_fw.minor, hw->ident_sta_fw.variant);
5db8dcc9
SP
745 WLAN_LOG_ERROR("Unsupported Tertiary AP firmeare loaded!\n");
746 goto failed;
00b3ed16
GKH
747 }
748
749 /* Compatibility range, Modem supplier */
750 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_MFISUPRANGE,
751 &hw->cap_sup_mfi, sizeof(hfa384x_caplevel_t));
752 if ( result ) {
753 WLAN_LOG_ERROR("Failed to retrieve MFISUPRANGE\n");
754 goto failed;
755 }
756
757 /* get all the Compatibility range, modem interface supplier
758 fields in byte order */
759 hw->cap_sup_mfi.role = hfa384x2host_16(hw->cap_sup_mfi.role);
760 hw->cap_sup_mfi.id = hfa384x2host_16(hw->cap_sup_mfi.id);
761 hw->cap_sup_mfi.variant = hfa384x2host_16(hw->cap_sup_mfi.variant);
762 hw->cap_sup_mfi.bottom = hfa384x2host_16(hw->cap_sup_mfi.bottom);
763 hw->cap_sup_mfi.top = hfa384x2host_16(hw->cap_sup_mfi.top);
764
765 WLAN_LOG_INFO(
766 "MFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
767 hw->cap_sup_mfi.role, hw->cap_sup_mfi.id,
768 hw->cap_sup_mfi.variant, hw->cap_sup_mfi.bottom,
769 hw->cap_sup_mfi.top);
770
771 /* Compatibility range, Controller supplier */
772 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CFISUPRANGE,
773 &hw->cap_sup_cfi, sizeof(hfa384x_caplevel_t));
774 if ( result ) {
775 WLAN_LOG_ERROR("Failed to retrieve CFISUPRANGE\n");
776 goto failed;
777 }
778
779 /* get all the Compatibility range, controller interface supplier
780 fields in byte order */
781 hw->cap_sup_cfi.role = hfa384x2host_16(hw->cap_sup_cfi.role);
782 hw->cap_sup_cfi.id = hfa384x2host_16(hw->cap_sup_cfi.id);
783 hw->cap_sup_cfi.variant = hfa384x2host_16(hw->cap_sup_cfi.variant);
784 hw->cap_sup_cfi.bottom = hfa384x2host_16(hw->cap_sup_cfi.bottom);
785 hw->cap_sup_cfi.top = hfa384x2host_16(hw->cap_sup_cfi.top);
786
787 WLAN_LOG_INFO(
788 "CFI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
789 hw->cap_sup_cfi.role, hw->cap_sup_cfi.id,
790 hw->cap_sup_cfi.variant, hw->cap_sup_cfi.bottom,
791 hw->cap_sup_cfi.top);
792
793 /* Compatibility range, Primary f/w supplier */
794 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRISUPRANGE,
795 &hw->cap_sup_pri, sizeof(hfa384x_caplevel_t));
796 if ( result ) {
797 WLAN_LOG_ERROR("Failed to retrieve PRISUPRANGE\n");
798 goto failed;
799 }
800
801 /* get all the Compatibility range, primary firmware supplier
802 fields in byte order */
803 hw->cap_sup_pri.role = hfa384x2host_16(hw->cap_sup_pri.role);
804 hw->cap_sup_pri.id = hfa384x2host_16(hw->cap_sup_pri.id);
805 hw->cap_sup_pri.variant = hfa384x2host_16(hw->cap_sup_pri.variant);
806 hw->cap_sup_pri.bottom = hfa384x2host_16(hw->cap_sup_pri.bottom);
807 hw->cap_sup_pri.top = hfa384x2host_16(hw->cap_sup_pri.top);
808
809 WLAN_LOG_INFO(
810 "PRI:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
811 hw->cap_sup_pri.role, hw->cap_sup_pri.id,
812 hw->cap_sup_pri.variant, hw->cap_sup_pri.bottom,
813 hw->cap_sup_pri.top);
814
815 /* Compatibility range, Station f/w supplier */
816 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STASUPRANGE,
817 &hw->cap_sup_sta, sizeof(hfa384x_caplevel_t));
818 if ( result ) {
819 WLAN_LOG_ERROR("Failed to retrieve STASUPRANGE\n");
820 goto failed;
821 }
822
823 /* get all the Compatibility range, station firmware supplier
824 fields in byte order */
825 hw->cap_sup_sta.role = hfa384x2host_16(hw->cap_sup_sta.role);
826 hw->cap_sup_sta.id = hfa384x2host_16(hw->cap_sup_sta.id);
827 hw->cap_sup_sta.variant = hfa384x2host_16(hw->cap_sup_sta.variant);
828 hw->cap_sup_sta.bottom = hfa384x2host_16(hw->cap_sup_sta.bottom);
829 hw->cap_sup_sta.top = hfa384x2host_16(hw->cap_sup_sta.top);
830
831 if ( hw->cap_sup_sta.id == 0x04 ) {
832 WLAN_LOG_INFO(
833 "STA:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
834 hw->cap_sup_sta.role, hw->cap_sup_sta.id,
835 hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom,
836 hw->cap_sup_sta.top);
837 } else {
838 WLAN_LOG_INFO(
839 "AP:SUP:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
840 hw->cap_sup_sta.role, hw->cap_sup_sta.id,
841 hw->cap_sup_sta.variant, hw->cap_sup_sta.bottom,
842 hw->cap_sup_sta.top);
843 }
844
845 /* Compatibility range, primary f/w actor, CFI supplier */
846 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_PRI_CFIACTRANGES,
847 &hw->cap_act_pri_cfi, sizeof(hfa384x_caplevel_t));
848 if ( result ) {
849 WLAN_LOG_ERROR("Failed to retrieve PRI_CFIACTRANGES\n");
850 goto failed;
851 }
852
853 /* get all the Compatibility range, primary f/w actor, CFI supplier
854 fields in byte order */
855 hw->cap_act_pri_cfi.role = hfa384x2host_16(hw->cap_act_pri_cfi.role);
856 hw->cap_act_pri_cfi.id = hfa384x2host_16(hw->cap_act_pri_cfi.id);
857 hw->cap_act_pri_cfi.variant = hfa384x2host_16(hw->cap_act_pri_cfi.variant);
858 hw->cap_act_pri_cfi.bottom = hfa384x2host_16(hw->cap_act_pri_cfi.bottom);
859 hw->cap_act_pri_cfi.top = hfa384x2host_16(hw->cap_act_pri_cfi.top);
860
861 WLAN_LOG_INFO(
862 "PRI-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
863 hw->cap_act_pri_cfi.role, hw->cap_act_pri_cfi.id,
864 hw->cap_act_pri_cfi.variant, hw->cap_act_pri_cfi.bottom,
865 hw->cap_act_pri_cfi.top);
866
867 /* Compatibility range, sta f/w actor, CFI supplier */
868 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_CFIACTRANGES,
869 &hw->cap_act_sta_cfi, sizeof(hfa384x_caplevel_t));
870 if ( result ) {
871 WLAN_LOG_ERROR("Failed to retrieve STA_CFIACTRANGES\n");
872 goto failed;
873 }
874
875 /* get all the Compatibility range, station f/w actor, CFI supplier
876 fields in byte order */
877 hw->cap_act_sta_cfi.role = hfa384x2host_16(hw->cap_act_sta_cfi.role);
878 hw->cap_act_sta_cfi.id = hfa384x2host_16(hw->cap_act_sta_cfi.id);
879 hw->cap_act_sta_cfi.variant = hfa384x2host_16(hw->cap_act_sta_cfi.variant);
880 hw->cap_act_sta_cfi.bottom = hfa384x2host_16(hw->cap_act_sta_cfi.bottom);
881 hw->cap_act_sta_cfi.top = hfa384x2host_16(hw->cap_act_sta_cfi.top);
882
883 WLAN_LOG_INFO(
884 "STA-CFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
885 hw->cap_act_sta_cfi.role, hw->cap_act_sta_cfi.id,
886 hw->cap_act_sta_cfi.variant, hw->cap_act_sta_cfi.bottom,
887 hw->cap_act_sta_cfi.top);
888
889 /* Compatibility range, sta f/w actor, MFI supplier */
890 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_STA_MFIACTRANGES,
891 &hw->cap_act_sta_mfi, sizeof(hfa384x_caplevel_t));
892 if ( result ) {
893 WLAN_LOG_ERROR("Failed to retrieve STA_MFIACTRANGES\n");
894 goto failed;
895 }
896
897 /* get all the Compatibility range, station f/w actor, MFI supplier
898 fields in byte order */
899 hw->cap_act_sta_mfi.role = hfa384x2host_16(hw->cap_act_sta_mfi.role);
900 hw->cap_act_sta_mfi.id = hfa384x2host_16(hw->cap_act_sta_mfi.id);
901 hw->cap_act_sta_mfi.variant = hfa384x2host_16(hw->cap_act_sta_mfi.variant);
902 hw->cap_act_sta_mfi.bottom = hfa384x2host_16(hw->cap_act_sta_mfi.bottom);
903 hw->cap_act_sta_mfi.top = hfa384x2host_16(hw->cap_act_sta_mfi.top);
904
905 WLAN_LOG_INFO(
906 "STA-MFI:ACT:role=0x%02x:id=0x%02x:var=0x%02x:b/t=%d/%d\n",
907 hw->cap_act_sta_mfi.role, hw->cap_act_sta_mfi.id,
908 hw->cap_act_sta_mfi.variant, hw->cap_act_sta_mfi.bottom,
909 hw->cap_act_sta_mfi.top);
910
911 /* Serial Number */
912 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER,
913 snum, HFA384x_RID_NICSERIALNUMBER_LEN);
914 if ( !result ) {
915 wlan_mkprintstr(snum, HFA384x_RID_NICSERIALNUMBER_LEN,
916 pstr, sizeof(pstr));
917 WLAN_LOG_INFO("Prism2 card SN: %s\n", pstr);
918 } else {
919 WLAN_LOG_ERROR("Failed to retrieve Prism2 Card SN\n");
920 goto failed;
921 }
922
923 /* Collect the MAC address */
924 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CNFOWNMACADDR,
925 wlandev->netdev->dev_addr, WLAN_ADDR_LEN);
926 if ( result != 0 ) {
927 WLAN_LOG_ERROR("Failed to retrieve mac address\n");
928 goto failed;
929 }
930
931 /* short preamble is always implemented */
932 wlandev->nsdcaps |= P80211_NSDCAP_SHORT_PREAMBLE;
933
934 /* find out if hardware wep is implemented */
935 hfa384x_drvr_getconfig16(hw, HFA384x_RID_PRIVACYOPTIMP, &temp);
936 if (temp)
937 wlandev->nsdcaps |= P80211_NSDCAP_HARDWAREWEP;
938
939 /* get the dBm Scaling constant */
940 hfa384x_drvr_getconfig16(hw, HFA384x_RID_CNFDBMADJUST, &temp);
941 hw->dbmadjust = temp;
942
943 /* Only enable scan by default on newer firmware */
944 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
945 hw->ident_sta_fw.minor,
946 hw->ident_sta_fw.variant) <
947 HFA384x_FIRMWARE_VERSION(1,5,5)) {
948 wlandev->nsdcaps |= P80211_NSDCAP_NOSCAN;
949 }
950
951 /* TODO: Set any internally managed config items */
952
953 goto done;
954failed:
955 WLAN_LOG_ERROR("Failed, result=%d\n", result);
956done:
957 DBFEXIT;
958 return result;
959}
960
961
962/*----------------------------------------------------------------
963* prism2sta_globalsetup
964*
965* Set any global RIDs that we want to set at device activation.
966*
967* Arguments:
968* wlandev wlan device structure
969*
970* Returns:
971* 0 success
972* >0 f/w reported error
973* <0 driver reported error
974*
975* Side effects:
976*
977* Call context:
978* process thread
979----------------------------------------------------------------*/
980static int prism2sta_globalsetup(wlandevice_t *wlandev)
981{
982 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
983
984 /* Set the maximum frame size */
985 return hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN,
986 WLAN_DATA_MAXLEN);
987}
988
989static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev)
990{
991 int result = 0;
992 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
993
aaad4303 994 u16 promisc;
00b3ed16
GKH
995
996 DBFENTER;
997
998 /* If we're not ready, what's the point? */
999 if ( hw->state != HFA384x_STATE_RUNNING )
1000 goto exit;
1001
00b3ed16
GKH
1002 if ( (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0 )
1003 promisc = P80211ENUM_truth_true;
1004 else
1005 promisc = P80211ENUM_truth_false;
1006
1007 result = hfa384x_drvr_setconfig16_async(hw, HFA384x_RID_PROMISCMODE, promisc);
1008
1009 /* XXX TODO: configure the multicast list */
1010 // CLEAR_HW_MULTICAST_LIST
1011 // struct dev_mc_list element = dev->mc_list;
1012 // while (element != null) {
1013 // HW_ADD_MULTICAST_ADDR(element->dmi_addr, dmi_addrlen)
1014 // element = element->next;
1015 // }
1016
1017 exit:
1018 DBFEXIT;
1019 return result;
1020}
1021
1022/*----------------------------------------------------------------
1023* prism2sta_inf_handover
1024*
1025* Handles the receipt of a Handover info frame. Should only be present
1026* in APs only.
1027*
1028* Arguments:
1029* wlandev wlan device structure
1030* inf ptr to info frame (contents in hfa384x order)
1031*
1032* Returns:
1033* nothing
1034*
1035* Side effects:
1036*
1037* Call context:
1038* interrupt
1039----------------------------------------------------------------*/
1040static void prism2sta_inf_handover(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
1041{
1042 DBFENTER;
1043 WLAN_LOG_DEBUG(2,"received infoframe:HANDOVER (unhandled)\n");
1044 DBFEXIT;
1045 return;
1046}
1047
1048
1049/*----------------------------------------------------------------
1050* prism2sta_inf_tallies
1051*
1052* Handles the receipt of a CommTallies info frame.
1053*
1054* Arguments:
1055* wlandev wlan device structure
1056* inf ptr to info frame (contents in hfa384x order)
1057*
1058* Returns:
1059* nothing
1060*
1061* Side effects:
1062*
1063* Call context:
1064* interrupt
1065----------------------------------------------------------------*/
1066static void prism2sta_inf_tallies(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
1067{
1068 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
aaad4303
SP
1069 u16 *src16;
1070 u32 *dst;
1071 u32 *src32;
00b3ed16
GKH
1072 int i;
1073 int cnt;
1074
1075 DBFENTER;
1076
1077 /*
1078 ** Determine if these are 16-bit or 32-bit tallies, based on the
1079 ** record length of the info record.
1080 */
1081
aaad4303 1082 cnt = sizeof(hfa384x_CommTallies32_t) / sizeof(u32);
00b3ed16 1083 if (inf->framelen > 22) {
aaad4303
SP
1084 dst = (u32 *) &hw->tallies;
1085 src32 = (u32 *) &inf->info.commtallies32;
00b3ed16
GKH
1086 for (i = 0; i < cnt; i++, dst++, src32++)
1087 *dst += hfa384x2host_32(*src32);
1088 } else {
aaad4303
SP
1089 dst = (u32 *) &hw->tallies;
1090 src16 = (u16 *) &inf->info.commtallies16;
00b3ed16
GKH
1091 for (i = 0; i < cnt; i++, dst++, src16++)
1092 *dst += hfa384x2host_16(*src16);
1093 }
1094
1095 DBFEXIT;
1096
1097 return;
1098}
1099
1100/*----------------------------------------------------------------
1101* prism2sta_inf_scanresults
1102*
1103* Handles the receipt of a Scan Results info frame.
1104*
1105* Arguments:
1106* wlandev wlan device structure
1107* inf ptr to info frame (contents in hfa384x order)
1108*
1109* Returns:
1110* nothing
1111*
1112* Side effects:
1113*
1114* Call context:
1115* interrupt
1116----------------------------------------------------------------*/
1117static void prism2sta_inf_scanresults(wlandevice_t *wlandev,
1118 hfa384x_InfFrame_t *inf)
1119{
1120
1121 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1122 int nbss;
1123 hfa384x_ScanResult_t *sr = &(inf->info.scanresult);
1124 int i;
1125 hfa384x_JoinRequest_data_t joinreq;
1126 int result;
1127 DBFENTER;
1128
1129 /* Get the number of results, first in bytes, then in results */
aaad4303 1130 nbss = (inf->framelen * sizeof(u16)) -
00b3ed16
GKH
1131 sizeof(inf->infotype) -
1132 sizeof(inf->info.scanresult.scanreason);
1133 nbss /= sizeof(hfa384x_ScanResultSub_t);
1134
1135 /* Print em */
1136 WLAN_LOG_DEBUG(1,"rx scanresults, reason=%d, nbss=%d:\n",
1137 inf->info.scanresult.scanreason, nbss);
1138 for ( i = 0; i < nbss; i++) {
1139 WLAN_LOG_DEBUG(1, "chid=%d anl=%d sl=%d bcnint=%d\n",
1140 sr->result[i].chid,
1141 sr->result[i].anl,
1142 sr->result[i].sl,
1143 sr->result[i].bcnint);
1144 WLAN_LOG_DEBUG(1, " capinfo=0x%04x proberesp_rate=%d\n",
1145 sr->result[i].capinfo,
1146 sr->result[i].proberesp_rate);
1147 }
1148 /* issue a join request */
1149 joinreq.channel = sr->result[0].chid;
1150 memcpy( joinreq.bssid, sr->result[0].bssid, WLAN_BSSID_LEN);
1151 result = hfa384x_drvr_setconfig( hw,
1152 HFA384x_RID_JOINREQUEST,
1153 &joinreq, HFA384x_RID_JOINREQUEST_LEN);
1154 if (result) {
1155 WLAN_LOG_ERROR("setconfig(joinreq) failed, result=%d\n", result);
1156 }
1157
1158 DBFEXIT;
1159 return;
1160}
1161
1162/*----------------------------------------------------------------
1163* prism2sta_inf_hostscanresults
1164*
1165* Handles the receipt of a Scan Results info frame.
1166*
1167* Arguments:
1168* wlandev wlan device structure
1169* inf ptr to info frame (contents in hfa384x order)
1170*
1171* Returns:
1172* nothing
1173*
1174* Side effects:
1175*
1176* Call context:
1177* interrupt
1178----------------------------------------------------------------*/
1179static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev,
1180 hfa384x_InfFrame_t *inf)
1181{
1182 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1183 int nbss;
1184 DBFENTER;
1185
1186 nbss = (inf->framelen - 3) / 32;
1187 WLAN_LOG_DEBUG(1, "Received %d hostscan results\n", nbss);
1188
1189 if (nbss > 32)
1190 nbss = 32;
1191
1192 if (hw->scanresults)
1193 kfree(hw->scanresults);
1194
1195 hw->scanresults = kmalloc(sizeof(hfa384x_InfFrame_t), GFP_ATOMIC);
1196 memcpy(hw->scanresults, inf, sizeof(hfa384x_InfFrame_t));
1197
1198 if (nbss == 0)
1199 nbss = -1;
1200
1201 /* Notify/wake the sleeping caller. */
1202 hw->scanflag = nbss;
1203 wake_up_interruptible(&hw->cmdq);
1204
1205 DBFEXIT;
1206};
1207
1208/*----------------------------------------------------------------
1209* prism2sta_inf_chinforesults
1210*
1211* Handles the receipt of a Channel Info Results info frame.
1212*
1213* Arguments:
1214* wlandev wlan device structure
1215* inf ptr to info frame (contents in hfa384x order)
1216*
1217* Returns:
1218* nothing
1219*
1220* Side effects:
1221*
1222* Call context:
1223* interrupt
1224----------------------------------------------------------------*/
1225static void prism2sta_inf_chinforesults(wlandevice_t *wlandev,
1226 hfa384x_InfFrame_t *inf)
1227{
1228 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1229 unsigned int i, n;
1230
1231 DBFENTER;
1232 hw->channel_info.results.scanchannels =
1233 hfa384x2host_16(inf->info.chinforesult.scanchannels);
1234#if 0
1235 memcpy(&inf->info.chinforesult, &hw->channel_info.results, sizeof(hfa384x_ChInfoResult_t));
1236#endif
1237
1238 for (i=0, n=0; i<HFA384x_CHINFORESULT_MAX; i++) {
1239 if (hw->channel_info.results.scanchannels & (1<<i)) {
1240 int channel=hfa384x2host_16(inf->info.chinforesult.result[n].chid)-1;
1241 hfa384x_ChInfoResultSub_t *chinforesult=&hw->channel_info.results.result[channel];
1242 chinforesult->chid = channel;
1243 chinforesult->anl = hfa384x2host_16(inf->info.chinforesult.result[n].anl);
1244 chinforesult->pnl = hfa384x2host_16(inf->info.chinforesult.result[n].pnl);
1245 chinforesult->active = hfa384x2host_16(inf->info.chinforesult.result[n].active);
1246 WLAN_LOG_DEBUG(2, "chinfo: channel %d, %s level (avg/peak)=%d/%d dB, pcf %d\n",
1247 channel+1,
1248 chinforesult->active &
1249 HFA384x_CHINFORESULT_BSSACTIVE ? "signal" : "noise",
1250 chinforesult->anl, chinforesult->pnl,
1251 chinforesult->active & HFA384x_CHINFORESULT_PCFACTIVE ? 1 : 0
1252 );
1253 n++;
1254 }
1255 }
1256 atomic_set(&hw->channel_info.done, 2);
1257
1258 hw->channel_info.count = n;
1259 DBFEXIT;
1260 return;
1261}
1262
1263void prism2sta_processing_defer(struct work_struct *data)
1264{
1265 hfa384x_t *hw = container_of(data, struct hfa384x, link_bh);
1266 wlandevice_t *wlandev = hw->wlandev;
1267 hfa384x_bytestr32_t ssid;
1268 int result;
1269
1270 DBFENTER;
1271 /* First let's process the auth frames */
1272 {
1273 struct sk_buff *skb;
1274 hfa384x_InfFrame_t *inf;
1275
1276 while ( (skb = skb_dequeue(&hw->authq)) ) {
1277 inf = (hfa384x_InfFrame_t *) skb->data;
1278 prism2sta_inf_authreq_defer(wlandev, inf);
1279 }
1280
1281 }
1282
1283 /* Now let's handle the linkstatus stuff */
1284 if (hw->link_status == hw->link_status_new)
1285 goto failed;
1286
1287 hw->link_status = hw->link_status_new;
1288
1289 switch(hw->link_status) {
1290 case HFA384x_LINK_NOTCONNECTED:
1291 /* I'm currently assuming that this is the initial link
1292 * state. It should only be possible immediately
1293 * following an Enable command.
1294 * Response:
1295 * Block Transmits, Ignore receives of data frames
1296 */
1297 netif_carrier_off(wlandev->netdev);
1298
1299 WLAN_LOG_INFO("linkstatus=NOTCONNECTED (unhandled)\n");
1300 break;
1301
1302 case HFA384x_LINK_CONNECTED:
1303 /* This one indicates a successful scan/join/auth/assoc.
1304 * When we have the full MLME complement, this event will
1305 * signify successful completion of both mlme_authenticate
1306 * and mlme_associate. State management will get a little
1307 * ugly here.
1308 * Response:
1309 * Indicate authentication and/or association
1310 * Enable Transmits, Receives and pass up data frames
1311 */
1312
1313 netif_carrier_on(wlandev->netdev);
1314
1315 /* If we are joining a specific AP, set our state and reset retries */
1316 if(hw->join_ap == 1)
1317 hw->join_ap = 2;
1318 hw->join_retries = 60;
1319
1320 /* Don't call this in monitor mode */
1321 if ( wlandev->netdev->type == ARPHRD_ETHER ) {
aaad4303 1322 u16 portstatus;
00b3ed16
GKH
1323
1324 WLAN_LOG_INFO("linkstatus=CONNECTED\n");
1325
1326 /* For non-usb devices, we can use the sync versions */
1327 /* Collect the BSSID, and set state to allow tx */
1328
1329 result = hfa384x_drvr_getconfig(hw,
1330 HFA384x_RID_CURRENTBSSID,
1331 wlandev->bssid, WLAN_BSSID_LEN);
1332 if ( result ) {
1333 WLAN_LOG_DEBUG(1,
1334 "getconfig(0x%02x) failed, result = %d\n",
1335 HFA384x_RID_CURRENTBSSID, result);
1336 goto failed;
1337 }
1338
1339 result = hfa384x_drvr_getconfig(hw,
1340 HFA384x_RID_CURRENTSSID,
1341 &ssid, sizeof(ssid));
1342 if ( result ) {
1343 WLAN_LOG_DEBUG(1,
1344 "getconfig(0x%02x) failed, result = %d\n",
1345 HFA384x_RID_CURRENTSSID, result);
1346 goto failed;
1347 }
1348 prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid,
1349 (p80211pstrd_t *) &wlandev->ssid);
1350
1351 /* Collect the port status */
1352 result = hfa384x_drvr_getconfig16(hw,
1353 HFA384x_RID_PORTSTATUS, &portstatus);
1354 if ( result ) {
1355 WLAN_LOG_DEBUG(1,
1356 "getconfig(0x%02x) failed, result = %d\n",
1357 HFA384x_RID_PORTSTATUS, result);
1358 goto failed;
1359 }
1360 wlandev->macmode =
1361 (portstatus == HFA384x_PSTATUS_CONN_IBSS) ?
1362 WLAN_MACMODE_IBSS_STA : WLAN_MACMODE_ESS_STA;
1363
1364 /* Get the ball rolling on the comms quality stuff */
1365 prism2sta_commsqual_defer(&hw->commsqual_bh);
1366 }
1367 break;
1368
1369 case HFA384x_LINK_DISCONNECTED:
1370 /* This one indicates that our association is gone. We've
1371 * lost connection with the AP and/or been disassociated.
1372 * This indicates that the MAC has completely cleared it's
1373 * associated state. We * should send a deauth indication
1374 * (implying disassoc) up * to the MLME.
1375 * Response:
1376 * Indicate Deauthentication
1377 * Block Transmits, Ignore receives of data frames
1378 */
1379 if(hw->join_ap == 2)
1380 {
1381 hfa384x_JoinRequest_data_t joinreq;
1382 joinreq = hw->joinreq;
1383 /* Send the join request */
1384 hfa384x_drvr_setconfig( hw,
1385 HFA384x_RID_JOINREQUEST,
1386 &joinreq, HFA384x_RID_JOINREQUEST_LEN);
1387 WLAN_LOG_INFO("linkstatus=DISCONNECTED (re-submitting join)\n");
1388 } else {
1389 if (wlandev->netdev->type == ARPHRD_ETHER)
1390 WLAN_LOG_INFO("linkstatus=DISCONNECTED (unhandled)\n");
1391 }
1392 wlandev->macmode = WLAN_MACMODE_NONE;
1393
1394 netif_carrier_off(wlandev->netdev);
1395
1396 break;
1397
1398 case HFA384x_LINK_AP_CHANGE:
1399 /* This one indicates that the MAC has decided to and
1400 * successfully completed a change to another AP. We
1401 * should probably implement a reassociation indication
1402 * in response to this one. I'm thinking that the the
1403 * p80211 layer needs to be notified in case of
1404 * buffering/queueing issues. User mode also needs to be
1405 * notified so that any BSS dependent elements can be
1406 * updated.
1407 * associated state. We * should send a deauth indication
1408 * (implying disassoc) up * to the MLME.
1409 * Response:
1410 * Indicate Reassociation
1411 * Enable Transmits, Receives and pass up data frames
1412 */
1413 WLAN_LOG_INFO("linkstatus=AP_CHANGE\n");
1414
1415 result = hfa384x_drvr_getconfig(hw,
1416 HFA384x_RID_CURRENTBSSID,
1417 wlandev->bssid, WLAN_BSSID_LEN);
1418 if ( result ) {
1419 WLAN_LOG_DEBUG(1,
1420 "getconfig(0x%02x) failed, result = %d\n",
1421 HFA384x_RID_CURRENTBSSID, result);
1422 goto failed;
1423 }
1424
1425 result = hfa384x_drvr_getconfig(hw,
1426 HFA384x_RID_CURRENTSSID,
1427 &ssid, sizeof(ssid));
1428 if ( result ) {
1429 WLAN_LOG_DEBUG(1,
1430 "getconfig(0x%02x) failed, result = %d\n",
1431 HFA384x_RID_CURRENTSSID, result);
1432 goto failed;
1433 }
1434 prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid,
1435 (p80211pstrd_t *) &wlandev->ssid);
1436
1437
1438 hw->link_status = HFA384x_LINK_CONNECTED;
1439 netif_carrier_on(wlandev->netdev);
1440
1441 break;
1442
1443 case HFA384x_LINK_AP_OUTOFRANGE:
1444 /* This one indicates that the MAC has decided that the
1445 * AP is out of range, but hasn't found a better candidate
1446 * so the MAC maintains its "associated" state in case
1447 * we get back in range. We should block transmits and
1448 * receives in this state. Do we need an indication here?
1449 * Probably not since a polling user-mode element would
1450 * get this status from from p2PortStatus(FD40). What about
1451 * p80211?
1452 * Response:
1453 * Block Transmits, Ignore receives of data frames
1454 */
1455 WLAN_LOG_INFO("linkstatus=AP_OUTOFRANGE (unhandled)\n");
1456
1457 netif_carrier_off(wlandev->netdev);
1458
1459 break;
1460
1461 case HFA384x_LINK_AP_INRANGE:
1462 /* This one indicates that the MAC has decided that the
1463 * AP is back in range. We continue working with our
1464 * existing association.
1465 * Response:
1466 * Enable Transmits, Receives and pass up data frames
1467 */
1468 WLAN_LOG_INFO("linkstatus=AP_INRANGE\n");
1469
1470 hw->link_status = HFA384x_LINK_CONNECTED;
1471 netif_carrier_on(wlandev->netdev);
1472
1473 break;
1474
1475 case HFA384x_LINK_ASSOCFAIL:
1476 /* This one is actually a peer to CONNECTED. We've
1477 * requested a join for a given SSID and optionally BSSID.
1478 * We can use this one to indicate authentication and
1479 * association failures. The trick is going to be
1480 * 1) identifying the failure, and 2) state management.
1481 * Response:
1482 * Disable Transmits, Ignore receives of data frames
1483 */
1484 if(hw->join_ap && --hw->join_retries > 0)
1485 {
1486 hfa384x_JoinRequest_data_t joinreq;
1487 joinreq = hw->joinreq;
1488 /* Send the join request */
1489 hfa384x_drvr_setconfig( hw,
1490 HFA384x_RID_JOINREQUEST,
1491 &joinreq, HFA384x_RID_JOINREQUEST_LEN);
1492 WLAN_LOG_INFO("linkstatus=ASSOCFAIL (re-submitting join)\n");
1493 } else {
1494 WLAN_LOG_INFO("linkstatus=ASSOCFAIL (unhandled)\n");
1495 }
1496
1497 netif_carrier_off(wlandev->netdev);
1498
1499 break;
1500
1501 default:
1502 /* This is bad, IO port problems? */
1503 WLAN_LOG_WARNING(
1504 "unknown linkstatus=0x%02x\n", hw->link_status);
1505 goto failed;
1506 break;
1507 }
1508
1509 wlandev->linkstatus = (hw->link_status == HFA384x_LINK_CONNECTED);
1510#ifdef WIRELESS_EXT
1511 p80211wext_event_associated(wlandev, wlandev->linkstatus);
1512#endif
1513
1514 failed:
1515 DBFEXIT;
1516}
1517
1518/*----------------------------------------------------------------
1519* prism2sta_inf_linkstatus
1520*
1521* Handles the receipt of a Link Status info frame.
1522*
1523* Arguments:
1524* wlandev wlan device structure
1525* inf ptr to info frame (contents in hfa384x order)
1526*
1527* Returns:
1528* nothing
1529*
1530* Side effects:
1531*
1532* Call context:
1533* interrupt
1534----------------------------------------------------------------*/
1535static void prism2sta_inf_linkstatus(wlandevice_t *wlandev,
1536 hfa384x_InfFrame_t *inf)
1537{
1538 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1539
1540 DBFENTER;
1541
1542 hw->link_status_new = hfa384x2host_16(inf->info.linkstatus.linkstatus);
1543
1544 schedule_work(&hw->link_bh);
1545
1546 DBFEXIT;
1547 return;
1548}
1549
1550/*----------------------------------------------------------------
1551* prism2sta_inf_assocstatus
1552*
1553* Handles the receipt of an Association Status info frame. Should
1554* be present in APs only.
1555*
1556* Arguments:
1557* wlandev wlan device structure
1558* inf ptr to info frame (contents in hfa384x order)
1559*
1560* Returns:
1561* nothing
1562*
1563* Side effects:
1564*
1565* Call context:
1566* interrupt
1567----------------------------------------------------------------*/
1568static void prism2sta_inf_assocstatus(wlandevice_t *wlandev,
1569 hfa384x_InfFrame_t *inf)
1570{
1571 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1572 hfa384x_AssocStatus_t rec;
1573 int i;
1574
1575 DBFENTER;
1576
1577 memcpy(&rec, &inf->info.assocstatus, sizeof(rec));
1578 rec.assocstatus = hfa384x2host_16(rec.assocstatus);
1579 rec.reason = hfa384x2host_16(rec.reason);
1580
1581 /*
1582 ** Find the address in the list of authenticated stations. If it wasn't
1583 ** found, then this address has not been previously authenticated and
1584 ** something weird has happened if this is anything other than an
1585 ** "authentication failed" message. If the address was found, then
1586 ** set the "associated" flag for that station, based on whether the
1587 ** station is associating or losing its association. Something weird
1588 ** has also happened if we find the address in the list of authenticated
1589 ** stations but we are getting an "authentication failed" message.
1590 */
1591
1592 for (i = 0; i < hw->authlist.cnt; i++)
1593 if (memcmp(rec.sta_addr, hw->authlist.addr[i], WLAN_ADDR_LEN) == 0)
1594 break;
1595
1596 if (i >= hw->authlist.cnt) {
1597 if (rec.assocstatus != HFA384x_ASSOCSTATUS_AUTHFAIL)
1598 WLAN_LOG_WARNING("assocstatus info frame received for non-authenticated station.\n");
1599 } else {
1600 hw->authlist.assoc[i] =
1601 (rec.assocstatus == HFA384x_ASSOCSTATUS_STAASSOC ||
1602 rec.assocstatus == HFA384x_ASSOCSTATUS_REASSOC);
1603
1604 if (rec.assocstatus == HFA384x_ASSOCSTATUS_AUTHFAIL)
1605 WLAN_LOG_WARNING("authfail assocstatus info frame received for authenticated station.\n");
1606 }
1607
1608 DBFEXIT;
1609
1610 return;
1611}
1612
1613/*----------------------------------------------------------------
1614* prism2sta_inf_authreq
1615*
1616* Handles the receipt of an Authentication Request info frame. Should
1617* be present in APs only.
1618*
1619* Arguments:
1620* wlandev wlan device structure
1621* inf ptr to info frame (contents in hfa384x order)
1622*
1623* Returns:
1624* nothing
1625*
1626* Side effects:
1627*
1628* Call context:
1629* interrupt
1630*
1631----------------------------------------------------------------*/
1632static void prism2sta_inf_authreq(wlandevice_t *wlandev,
1633 hfa384x_InfFrame_t *inf)
1634{
1635 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1636 struct sk_buff *skb;
1637
1638 DBFENTER;
1639
1640 skb = dev_alloc_skb(sizeof(*inf));
1641 if (skb) {
1642 skb_put(skb, sizeof(*inf));
1643 memcpy(skb->data, inf, sizeof(*inf));
1644 skb_queue_tail(&hw->authq, skb);
1645 schedule_work(&hw->link_bh);
1646 }
1647
1648 DBFEXIT;
1649}
1650
1651static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev,
1652 hfa384x_InfFrame_t *inf)
1653{
1654 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1655 hfa384x_authenticateStation_data_t rec;
1656
1657 int i, added, result, cnt;
aaad4303 1658 u8 *addr;
00b3ed16
GKH
1659
1660 DBFENTER;
1661
1662 /*
1663 ** Build the AuthenticateStation record. Initialize it for denying
1664 ** authentication.
1665 */
1666
1667 memcpy(rec.address, inf->info.authreq.sta_addr, WLAN_ADDR_LEN);
1668 rec.status = P80211ENUM_status_unspec_failure;
1669
1670 /*
1671 ** Authenticate based on the access mode.
1672 */
1673
1674 switch (hw->accessmode) {
1675 case WLAN_ACCESS_NONE:
1676
1677 /*
1678 ** Deny all new authentications. However, if a station
1679 ** is ALREADY authenticated, then accept it.
1680 */
1681
1682 for (i = 0; i < hw->authlist.cnt; i++)
1683 if (memcmp(rec.address, hw->authlist.addr[i],
1684 WLAN_ADDR_LEN) == 0) {
1685 rec.status = P80211ENUM_status_successful;
1686 break;
1687 }
1688
1689 break;
1690
1691 case WLAN_ACCESS_ALL:
1692
1693 /*
1694 ** Allow all authentications.
1695 */
1696
1697 rec.status = P80211ENUM_status_successful;
1698 break;
1699
1700 case WLAN_ACCESS_ALLOW:
1701
1702 /*
1703 ** Only allow the authentication if the MAC address
1704 ** is in the list of allowed addresses.
1705 **
1706 ** Since this is the interrupt handler, we may be here
1707 ** while the access list is in the middle of being
1708 ** updated. Choose the list which is currently okay.
1709 ** See "prism2mib_priv_accessallow()" for details.
1710 */
1711
1712 if (hw->allow.modify == 0) {
1713 cnt = hw->allow.cnt;
1714 addr = hw->allow.addr[0];
1715 } else {
1716 cnt = hw->allow.cnt1;
1717 addr = hw->allow.addr1[0];
1718 }
1719
1720 for (i = 0; i < cnt; i++, addr += WLAN_ADDR_LEN)
1721 if (memcmp(rec.address, addr, WLAN_ADDR_LEN) == 0) {
1722 rec.status = P80211ENUM_status_successful;
1723 break;
1724 }
1725
1726 break;
1727
1728 case WLAN_ACCESS_DENY:
1729
1730 /*
1731 ** Allow the authentication UNLESS the MAC address is
1732 ** in the list of denied addresses.
1733 **
1734 ** Since this is the interrupt handler, we may be here
1735 ** while the access list is in the middle of being
1736 ** updated. Choose the list which is currently okay.
1737 ** See "prism2mib_priv_accessdeny()" for details.
1738 */
1739
1740 if (hw->deny.modify == 0) {
1741 cnt = hw->deny.cnt;
1742 addr = hw->deny.addr[0];
1743 } else {
1744 cnt = hw->deny.cnt1;
1745 addr = hw->deny.addr1[0];
1746 }
1747
1748 rec.status = P80211ENUM_status_successful;
1749
1750 for (i = 0; i < cnt; i++, addr += WLAN_ADDR_LEN)
1751 if (memcmp(rec.address, addr, WLAN_ADDR_LEN) == 0) {
1752 rec.status = P80211ENUM_status_unspec_failure;
1753 break;
1754 }
1755
1756 break;
1757 }
1758
1759 /*
1760 ** If the authentication is okay, then add the MAC address to the list
1761 ** of authenticated stations. Don't add the address if it is already in
1762 ** the list. (802.11b does not seem to disallow a station from issuing
1763 ** an authentication request when the station is already authenticated.
1764 ** Does this sort of thing ever happen? We might as well do the check
1765 ** just in case.)
1766 */
1767
1768 added = 0;
1769
1770 if (rec.status == P80211ENUM_status_successful) {
1771 for (i = 0; i < hw->authlist.cnt; i++)
1772 if (memcmp(rec.address, hw->authlist.addr[i], WLAN_ADDR_LEN) == 0)
1773 break;
1774
1775 if (i >= hw->authlist.cnt) {
1776 if (hw->authlist.cnt >= WLAN_AUTH_MAX) {
1777 rec.status = P80211ENUM_status_ap_full;
1778 } else {
1779 memcpy(hw->authlist.addr[hw->authlist.cnt],
1780 rec.address, WLAN_ADDR_LEN);
1781 hw->authlist.cnt++;
1782 added = 1;
1783 }
1784 }
1785 }
1786
1787 /*
1788 ** Send back the results of the authentication. If this doesn't work,
1789 ** then make sure to remove the address from the authenticated list if
1790 ** it was added.
1791 */
1792
1793 rec.status = host2hfa384x_16(rec.status);
1794 rec.algorithm = inf->info.authreq.algorithm;
1795
1796 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_AUTHENTICATESTA,
1797 &rec, sizeof(rec));
1798 if (result) {
1799 if (added) hw->authlist.cnt--;
1800 WLAN_LOG_ERROR("setconfig(authenticatestation) failed, result=%d\n", result);
1801 }
1802
1803 DBFEXIT;
1804
1805 return;
1806}
1807
1808
1809/*----------------------------------------------------------------
1810* prism2sta_inf_psusercnt
1811*
1812* Handles the receipt of a PowerSaveUserCount info frame. Should
1813* be present in APs only.
1814*
1815* Arguments:
1816* wlandev wlan device structure
1817* inf ptr to info frame (contents in hfa384x order)
1818*
1819* Returns:
1820* nothing
1821*
1822* Side effects:
1823*
1824* Call context:
1825* interrupt
1826----------------------------------------------------------------*/
1827static void prism2sta_inf_psusercnt(wlandevice_t *wlandev,
1828 hfa384x_InfFrame_t *inf)
1829{
1830 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1831
1832 DBFENTER;
1833
1834 hw->psusercount = hfa384x2host_16(inf->info.psusercnt.usercnt);
1835
1836 DBFEXIT;
1837
1838 return;
1839}
1840
1841/*----------------------------------------------------------------
1842* prism2sta_ev_dtim
1843*
1844* Handles the DTIM early warning event.
1845*
1846* Arguments:
1847* wlandev wlan device structure
1848*
1849* Returns:
1850* nothing
1851*
1852* Side effects:
1853*
1854* Call context:
1855* interrupt
1856----------------------------------------------------------------*/
1857void prism2sta_ev_dtim(wlandevice_t *wlandev)
1858{
1859#if 0
1860 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1861#endif
1862 DBFENTER;
1863 WLAN_LOG_DEBUG(3, "DTIM event, currently unhandled.\n");
1864 DBFEXIT;
1865 return;
1866}
1867
1868
1869/*----------------------------------------------------------------
1870* prism2sta_ev_infdrop
1871*
1872* Handles the InfDrop event.
1873*
1874* Arguments:
1875* wlandev wlan device structure
1876*
1877* Returns:
1878* nothing
1879*
1880* Side effects:
1881*
1882* Call context:
1883* interrupt
1884----------------------------------------------------------------*/
1885void prism2sta_ev_infdrop(wlandevice_t *wlandev)
1886{
1887#if 0
1888 hfa384x_t *hw = (hfa384x_t *)wlandev->priv;
1889#endif
1890 DBFENTER;
1891 WLAN_LOG_DEBUG(3, "Info frame dropped due to card mem low.\n");
1892 DBFEXIT;
1893 return;
1894}
1895
1896
1897/*----------------------------------------------------------------
1898* prism2sta_ev_info
1899*
1900* Handles the Info event.
1901*
1902* Arguments:
1903* wlandev wlan device structure
1904* inf ptr to a generic info frame
1905*
1906* Returns:
1907* nothing
1908*
1909* Side effects:
1910*
1911* Call context:
1912* interrupt
1913----------------------------------------------------------------*/
1914void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf)
1915{
1916 DBFENTER;
1917 inf->infotype = hfa384x2host_16(inf->infotype);
1918 /* Dispatch */
1919 switch ( inf->infotype ) {
1920 case HFA384x_IT_HANDOVERADDR:
1921 prism2sta_inf_handover(wlandev, inf);
1922 break;
1923 case HFA384x_IT_COMMTALLIES:
1924 prism2sta_inf_tallies(wlandev, inf);
1925 break;
1926 case HFA384x_IT_HOSTSCANRESULTS:
1927 prism2sta_inf_hostscanresults(wlandev, inf);
1928 break;
1929 case HFA384x_IT_SCANRESULTS:
1930 prism2sta_inf_scanresults(wlandev, inf);
1931 break;
1932 case HFA384x_IT_CHINFORESULTS:
1933 prism2sta_inf_chinforesults(wlandev, inf);
1934 break;
1935 case HFA384x_IT_LINKSTATUS:
1936 prism2sta_inf_linkstatus(wlandev, inf);
1937 break;
1938 case HFA384x_IT_ASSOCSTATUS:
1939 prism2sta_inf_assocstatus(wlandev, inf);
1940 break;
1941 case HFA384x_IT_AUTHREQ:
1942 prism2sta_inf_authreq(wlandev, inf);
1943 break;
1944 case HFA384x_IT_PSUSERCNT:
1945 prism2sta_inf_psusercnt(wlandev, inf);
1946 break;
1947 case HFA384x_IT_KEYIDCHANGED:
1948 WLAN_LOG_WARNING("Unhandled IT_KEYIDCHANGED\n");
1949 break;
1950 case HFA384x_IT_ASSOCREQ:
1951 WLAN_LOG_WARNING("Unhandled IT_ASSOCREQ\n");
1952 break;
1953 case HFA384x_IT_MICFAILURE:
1954 WLAN_LOG_WARNING("Unhandled IT_MICFAILURE\n");
1955 break;
1956 default:
1957 WLAN_LOG_WARNING(
1958 "Unknown info type=0x%02x\n", inf->infotype);
1959 break;
1960 }
1961 DBFEXIT;
1962 return;
1963}
1964
1965
1966/*----------------------------------------------------------------
1967* prism2sta_ev_txexc
1968*
1969* Handles the TxExc event. A Transmit Exception event indicates
1970* that the MAC's TX process was unsuccessful - so the packet did
1971* not get transmitted.
1972*
1973* Arguments:
1974* wlandev wlan device structure
1975* status tx frame status word
1976*
1977* Returns:
1978* nothing
1979*
1980* Side effects:
1981*
1982* Call context:
1983* interrupt
1984----------------------------------------------------------------*/
aaad4303 1985void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status)
00b3ed16
GKH
1986{
1987 DBFENTER;
1988
1989 WLAN_LOG_DEBUG(3, "TxExc status=0x%x.\n", status);
1990
1991 DBFEXIT;
1992 return;
1993}
1994
1995
1996/*----------------------------------------------------------------
1997* prism2sta_ev_tx
1998*
1999* Handles the Tx event.
2000*
2001* Arguments:
2002* wlandev wlan device structure
2003* status tx frame status word
2004* Returns:
2005* nothing
2006*
2007* Side effects:
2008*
2009* Call context:
2010* interrupt
2011----------------------------------------------------------------*/
aaad4303 2012void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status)
00b3ed16
GKH
2013{
2014 DBFENTER;
2015 WLAN_LOG_DEBUG(4, "Tx Complete, status=0x%04x\n", status);
2016 /* update linux network stats */
2017 wlandev->linux_stats.tx_packets++;
2018 DBFEXIT;
2019 return;
2020}
2021
2022
2023/*----------------------------------------------------------------
2024* prism2sta_ev_rx
2025*
2026* Handles the Rx event.
2027*
2028* Arguments:
2029* wlandev wlan device structure
2030*
2031* Returns:
2032* nothing
2033*
2034* Side effects:
2035*
2036* Call context:
2037* interrupt
2038----------------------------------------------------------------*/
2039void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb)
2040{
2041 DBFENTER;
2042
2043 p80211netdev_rx(wlandev, skb);
2044
2045 DBFEXIT;
2046 return;
2047}
2048
2049/*----------------------------------------------------------------
2050* prism2sta_ev_alloc
2051*
2052* Handles the Alloc event.
2053*
2054* Arguments:
2055* wlandev wlan device structure
2056*
2057* Returns:
2058* nothing
2059*
2060* Side effects:
2061*
2062* Call context:
2063* interrupt
2064----------------------------------------------------------------*/
2065void prism2sta_ev_alloc(wlandevice_t *wlandev)
2066{
2067 DBFENTER;
2068
cbec30c4 2069 netif_wake_queue(wlandev->netdev);
00b3ed16
GKH
2070
2071 DBFEXIT;
2072 return;
2073}
2074
00b3ed16
GKH
2075/*----------------------------------------------------------------
2076* create_wlan
2077*
2078* Called at module init time. This creates the wlandevice_t structure
2079* and initializes it with relevant bits.
2080*
2081* Arguments:
2082* none
2083*
2084* Returns:
2085* the created wlandevice_t structure.
2086*
2087* Side effects:
2088* also allocates the priv/hw structures.
2089*
2090* Call context:
2091* process thread
2092*
2093----------------------------------------------------------------*/
2094static wlandevice_t *create_wlan(void)
2095{
2096 wlandevice_t *wlandev = NULL;
2097 hfa384x_t *hw = NULL;
2098
2099 /* Alloc our structures */
2100 wlandev = kmalloc(sizeof(wlandevice_t), GFP_KERNEL);
2101 hw = kmalloc(sizeof(hfa384x_t), GFP_KERNEL);
2102
2103 if (!wlandev || !hw) {
2104 WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info);
2105 if (wlandev) kfree(wlandev);
2106 if (hw) kfree(hw);
2107 return NULL;
2108 }
2109
2110 /* Clear all the structs */
2111 memset(wlandev, 0, sizeof(wlandevice_t));
2112 memset(hw, 0, sizeof(hfa384x_t));
2113
2114 /* Initialize the network device object. */
2115 wlandev->nsdname = dev_info;
2116 wlandev->msdstate = WLAN_MSD_HWPRESENT_PENDING;
2117 wlandev->priv = hw;
2118 wlandev->open = prism2sta_open;
2119 wlandev->close = prism2sta_close;
2120 wlandev->reset = prism2sta_reset;
00b3ed16
GKH
2121 wlandev->txframe = prism2sta_txframe;
2122 wlandev->mlmerequest = prism2sta_mlmerequest;
2123 wlandev->set_multicast_list = prism2sta_setmulticast;
2124 wlandev->tx_timeout = hfa384x_tx_timeout;
2125
2126 wlandev->nsdcaps = P80211_NSDCAP_HWFRAGMENT |
2127 P80211_NSDCAP_AUTOJOIN;
2128
2129 /* Initialize the device private data stucture. */
2130 hw->dot11_desired_bss_type = 1;
2131
2132 return wlandev;
2133}
2134
00b3ed16
GKH
2135void prism2sta_commsqual_defer(struct work_struct *data)
2136{
2137 hfa384x_t *hw = container_of(data, struct hfa384x, commsqual_bh);
2138 wlandevice_t *wlandev = hw->wlandev;
2139 hfa384x_bytestr32_t ssid;
2140 int result = 0;
2141
2142 DBFENTER;
2143
2144 if (hw->wlandev->hwremoved)
2145 goto done;
2146
2147 /* we don't care if we're in AP mode */
2148 if ((wlandev->macmode == WLAN_MACMODE_NONE) ||
2149 (wlandev->macmode == WLAN_MACMODE_ESS_AP)) {
2150 goto done;
2151 }
2152
2153 /* It only makes sense to poll these in non-IBSS */
2154 if (wlandev->macmode != WLAN_MACMODE_IBSS_STA) {
2155 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DBMCOMMSQUALITY,
2156 &hw->qual,
2157 HFA384x_RID_DBMCOMMSQUALITY_LEN);
2158
2159 if (result) {
2160 WLAN_LOG_ERROR("error fetching commsqual\n");
2161 goto done;
2162 }
2163
2164 // qual.CQ_currBSS; // link
2165 // ASL_currBSS; // level
2166 // qual.ANL_currFC; // noise
2167
2168 WLAN_LOG_DEBUG(3, "commsqual %d %d %d\n",
2169 hfa384x2host_16(hw->qual.CQ_currBSS),
2170 hfa384x2host_16(hw->qual.ASL_currBSS),
2171 hfa384x2host_16(hw->qual.ANL_currFC));
2172 }
2173
2174 /* Lastly, we need to make sure the BSSID didn't change on us */
2175 result = hfa384x_drvr_getconfig(hw,
2176 HFA384x_RID_CURRENTBSSID,
2177 wlandev->bssid, WLAN_BSSID_LEN);
2178 if ( result ) {
2179 WLAN_LOG_DEBUG(1,
2180 "getconfig(0x%02x) failed, result = %d\n",
2181 HFA384x_RID_CURRENTBSSID, result);
2182 goto done;
2183 }
2184
2185 result = hfa384x_drvr_getconfig(hw,
2186 HFA384x_RID_CURRENTSSID,
2187 &ssid, sizeof(ssid));
2188 if ( result ) {
2189 WLAN_LOG_DEBUG(1,
2190 "getconfig(0x%02x) failed, result = %d\n",
2191 HFA384x_RID_CURRENTSSID, result);
2192 goto done;
2193 }
2194 prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *)&ssid,
2195 (p80211pstrd_t *) &wlandev->ssid);
2196
2197
2198 /* Reschedule timer */
2199 mod_timer(&hw->commsqual_timer, jiffies + HZ);
2200
2201 done:
2202 DBFEXIT;
2203}
2204
2205void prism2sta_commsqual_timer(unsigned long data)
2206{
2207 hfa384x_t *hw = (hfa384x_t *) data;
2208
2209 DBFENTER;
2210
2211 schedule_work(&hw->commsqual_bh);
2212
2213 DBFEXIT;
2214}