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