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