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