• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
106 static char *dev_info = "prism2_usb";
107 static wlandevice_t *create_wlan(void);
108 
109 int prism2_reset_holdtime = 30;	/* Reset hold time in ms */
110 int prism2_reset_settletime = 100;	/* Reset settle time in ms */
111 
112 static int prism2_doreset;	/* Do a reset at init? */
113 
114 module_param(prism2_doreset, int, 0644);
115 MODULE_PARM_DESC(prism2_doreset, "Issue a reset on initialization");
116 
117 module_param(prism2_reset_holdtime, int, 0644);
118 MODULE_PARM_DESC(prism2_reset_holdtime, "reset hold time in ms");
119 module_param(prism2_reset_settletime, int, 0644);
120 MODULE_PARM_DESC(prism2_reset_settletime, "reset settle time in ms");
121 
122 MODULE_LICENSE("Dual MPL/GPL");
123 
124 void prism2_connect_result(wlandevice_t *wlandev, u8 failed);
125 void prism2_disconnected(wlandevice_t *wlandev);
126 void prism2_roamed(wlandevice_t *wlandev);
127 
128 static int prism2sta_open(wlandevice_t *wlandev);
129 static int prism2sta_close(wlandevice_t *wlandev);
130 static void prism2sta_reset(wlandevice_t *wlandev);
131 static int prism2sta_txframe(wlandevice_t *wlandev, struct sk_buff *skb,
132 			     union p80211_hdr *p80211_hdr,
133 			     struct p80211_metawep *p80211_wep);
134 static int prism2sta_mlmerequest(wlandevice_t *wlandev, struct p80211msg *msg);
135 static int prism2sta_getcardinfo(wlandevice_t *wlandev);
136 static int prism2sta_globalsetup(wlandevice_t *wlandev);
137 static int prism2sta_setmulticast(wlandevice_t *wlandev, netdevice_t *dev);
138 
139 static void prism2sta_inf_handover(wlandevice_t *wlandev,
140 				   hfa384x_InfFrame_t *inf);
141 static void prism2sta_inf_tallies(wlandevice_t *wlandev,
142 				  hfa384x_InfFrame_t *inf);
143 static void prism2sta_inf_hostscanresults(wlandevice_t *wlandev,
144 					  hfa384x_InfFrame_t *inf);
145 static void prism2sta_inf_scanresults(wlandevice_t *wlandev,
146 				      hfa384x_InfFrame_t *inf);
147 static void prism2sta_inf_chinforesults(wlandevice_t *wlandev,
148 					hfa384x_InfFrame_t *inf);
149 static void prism2sta_inf_linkstatus(wlandevice_t *wlandev,
150 				     hfa384x_InfFrame_t *inf);
151 static void prism2sta_inf_assocstatus(wlandevice_t *wlandev,
152 				      hfa384x_InfFrame_t *inf);
153 static void prism2sta_inf_authreq(wlandevice_t *wlandev,
154 				  hfa384x_InfFrame_t *inf);
155 static void prism2sta_inf_authreq_defer(wlandevice_t *wlandev,
156 					hfa384x_InfFrame_t *inf);
157 static 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 ----------------------------------------------------------------*/
prism2sta_open(wlandevice_t * wlandev)181 static 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 ----------------------------------------------------------------*/
prism2sta_close(wlandevice_t * wlandev)215 static 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 ----------------------------------------------------------------*/
prism2sta_reset(wlandevice_t * wlandev)243 static 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 ----------------------------------------------------------------*/
prism2sta_txframe(wlandevice_t * wlandev,struct sk_buff * skb,union p80211_hdr * p80211_hdr,struct p80211_metawep * p80211_wep)269 static 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 ----------------------------------------------------------------*/
prism2sta_mlmerequest(wlandevice_t * wlandev,struct p80211msg * msg)311 static 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 ----------------------------------------------------------------*/
prism2sta_ifstate(wlandevice_t * wlandev,u32 ifstate)439 u32 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 ----------------------------------------------------------------*/
prism2sta_getcardinfo(wlandevice_t * wlandev)613 static 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;
913 failed:
914 	printk(KERN_ERR "Failed, result=%d\n", result);
915 done:
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 ----------------------------------------------------------------*/
prism2sta_globalsetup(wlandevice_t * wlandev)937 static 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 
prism2sta_setmulticast(wlandevice_t * wlandev,netdevice_t * dev)946 static 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);
965 exit:
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 ----------------------------------------------------------------*/
prism2sta_inf_handover(wlandevice_t * wlandev,hfa384x_InfFrame_t * inf)987 static 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 ----------------------------------------------------------------*/
prism2sta_inf_tallies(wlandevice_t * wlandev,hfa384x_InfFrame_t * inf)1011 static 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 ----------------------------------------------------------------*/
prism2sta_inf_scanresults(wlandevice_t * wlandev,hfa384x_InfFrame_t * inf)1059 static 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 ----------------------------------------------------------------*/
prism2sta_inf_hostscanresults(wlandevice_t * wlandev,hfa384x_InfFrame_t * inf)1117 static 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 ----------------------------------------------------------------*/
prism2sta_inf_chinforesults(wlandevice_t * wlandev,hfa384x_InfFrame_t * inf)1159 static 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 
prism2sta_processing_defer(struct work_struct * data)1200 void 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 
1452 failed:
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 ----------------------------------------------------------------*/
prism2sta_inf_linkstatus(wlandevice_t * wlandev,hfa384x_InfFrame_t * inf)1473 static 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 ----------------------------------------------------------------*/
prism2sta_inf_assocstatus(wlandevice_t * wlandev,hfa384x_InfFrame_t * inf)1503 static 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 ----------------------------------------------------------------*/
prism2sta_inf_authreq(wlandevice_t * wlandev,hfa384x_InfFrame_t * inf)1566 static 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 
prism2sta_inf_authreq_defer(wlandevice_t * wlandev,hfa384x_InfFrame_t * inf)1581 static 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 ----------------------------------------------------------------*/
prism2sta_inf_psusercnt(wlandevice_t * wlandev,hfa384x_InfFrame_t * inf)1755 static 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 ----------------------------------------------------------------*/
prism2sta_ev_info(wlandevice_t * wlandev,hfa384x_InfFrame_t * inf)1782 void 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 ----------------------------------------------------------------*/
prism2sta_ev_txexc(wlandevice_t * wlandev,u16 status)1850 void 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 ----------------------------------------------------------------*/
prism2sta_ev_tx(wlandevice_t * wlandev,u16 status)1873 void 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 ----------------------------------------------------------------*/
prism2sta_ev_rx(wlandevice_t * wlandev,struct sk_buff * skb)1897 void 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 ----------------------------------------------------------------*/
prism2sta_ev_alloc(wlandevice_t * wlandev)1919 void 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 ----------------------------------------------------------------*/
create_wlan(void)1944 static 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 
prism2sta_commsqual_defer(struct work_struct * data)1984 void 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 
2072 done:
2073 	;
2074 }
2075 
prism2sta_commsqual_timer(unsigned long data)2076 void prism2sta_commsqual_timer(unsigned long data)
2077 {
2078 	hfa384x_t *hw = (hfa384x_t *) data;
2079 
2080 	schedule_work(&hw->commsqual_bh);
2081 }
2082