Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
prism2mgmt.c
Go to the documentation of this file.
1 /* src/prism2/driver/prism2mgmt.c
2 *
3 * Management request handler functions.
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.
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 * The functions in this file handle management requests sent from
48 * user mode.
49 *
50 * Most of these functions have two separate blocks of code that are
51 * conditional on whether this is a station or an AP. This is used
52 * to separate out the STA and AP responses to these management primitives.
53 * It's a choice (good, bad, indifferent?) to have the code in the same
54 * place so it's clear that the same primitive is implemented in both
55 * cases but has different behavior.
56 *
57 * --------------------------------------------------------------------
58 */
59 
60 #include <linux/if_arp.h>
61 #include <linux/module.h>
62 #include <linux/kernel.h>
63 #include <linux/wait.h>
64 #include <linux/sched.h>
65 #include <linux/types.h>
66 #include <linux/wireless.h>
67 #include <linux/netdevice.h>
68 #include <linux/delay.h>
69 #include <linux/io.h>
70 #include <asm/byteorder.h>
71 #include <linux/random.h>
72 #include <linux/usb.h>
73 #include <linux/bitops.h>
74 
75 #include "p80211types.h"
76 #include "p80211hdr.h"
77 #include "p80211mgmt.h"
78 #include "p80211conv.h"
79 #include "p80211msg.h"
80 #include "p80211netdev.h"
81 #include "p80211metadef.h"
82 #include "p80211metastruct.h"
83 #include "hfa384x.h"
84 #include "prism2mgmt.h"
85 
86 /* Converts 802.11 format rate specifications to prism2 */
87 #define p80211rate_to_p2bit(n) ((((n)&~BIT(7)) == 2) ? BIT(0) : \
88  (((n)&~BIT(7)) == 4) ? BIT(1) : \
89  (((n)&~BIT(7)) == 11) ? BIT(2) : \
90  (((n)&~BIT(7)) == 22) ? BIT(3) : 0)
91 
92 /*----------------------------------------------------------------
93 * prism2mgmt_scan
94 *
95 * Initiate a scan for BSSs.
96 *
97 * This function corresponds to MLME-scan.request and part of
98 * MLME-scan.confirm. As far as I can tell in the standard, there
99 * are no restrictions on when a scan.request may be issued. We have
100 * to handle in whatever state the driver/MAC happen to be.
101 *
102 * Arguments:
103 * wlandev wlan device structure
104 * msgp ptr to msg buffer
105 *
106 * Returns:
107 * 0 success and done
108 * <0 success, but we're waiting for something to finish.
109 * >0 an error occurred while handling the message.
110 * Side effects:
111 *
112 * Call context:
113 * process thread (usually)
114 * interrupt
115 ----------------------------------------------------------------*/
116 int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp)
117 {
118  int result = 0;
119  hfa384x_t *hw = wlandev->priv;
120  struct p80211msg_dot11req_scan *msg = msgp;
121  u16 roamingmode, word;
122  int i, timeout;
123  int istmpenable = 0;
124 
126 
127  /* gatekeeper check */
128  if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
129  hw->ident_sta_fw.minor,
130  hw->ident_sta_fw.variant) <
131  HFA384x_FIRMWARE_VERSION(1, 3, 2)) {
133  "HostScan not supported with current firmware (<1.3.2).\n");
134  result = 1;
136  goto exit;
137  }
138 
139  memset(&scanreq, 0, sizeof(scanreq));
140 
141  /* save current roaming mode */
142  result = hfa384x_drvr_getconfig16(hw,
144  &roamingmode);
145  if (result) {
146  printk(KERN_ERR "getconfig(ROAMMODE) failed. result=%d\n",
147  result);
148  msg->resultcode.data =
150  goto exit;
151  }
152 
153  /* drop into mode 3 for the scan */
154  result = hfa384x_drvr_setconfig16(hw,
157  if (result) {
158  printk(KERN_ERR "setconfig(ROAMINGMODE) failed. result=%d\n",
159  result);
160  msg->resultcode.data =
162  goto exit;
163  }
164 
165  /* active or passive? */
166  if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
167  hw->ident_sta_fw.minor,
168  hw->ident_sta_fw.variant) >
169  HFA384x_FIRMWARE_VERSION(1, 5, 0)) {
171  word = cpu_to_le16(msg->maxchanneltime.data);
172  else
173  word = 0;
174 
175  result =
176  hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL,
177  word);
178  if (result) {
179  printk(KERN_WARNING "Passive scan not supported with "
180  "current firmware. (<1.5.1)\n");
181  }
182  }
183 
184  /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
185  word = HFA384x_RATEBIT_2;
186  scanreq.txRate = cpu_to_le16(word);
187 
188  /* set up the channel list */
189  word = 0;
190  for (i = 0; i < msg->channellist.data.len; i++) {
191  u8 channel = msg->channellist.data.data[i];
192  if (channel > 14)
193  continue;
194  /* channel 1 is BIT 0 ... channel 14 is BIT 13 */
195  word |= (1 << (channel - 1));
196  }
197  scanreq.channelList = cpu_to_le16(word);
198 
199  /* set up the ssid, if present. */
200  scanreq.ssid.len = cpu_to_le16(msg->ssid.data.len);
201  memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
202 
203  /* Enable the MAC port if it's not already enabled */
204  result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
205  if (result) {
206  printk(KERN_ERR "getconfig(PORTSTATUS) failed. "
207  "result=%d\n", result);
208  msg->resultcode.data =
210  goto exit;
211  }
212  if (word == HFA384x_PORTSTATUS_DISABLED) {
213  u16 wordbuf[17];
214 
215  result = hfa384x_drvr_setconfig16(hw,
218  if (result) {
220  "setconfig(ROAMINGMODE) failed. result=%d\n",
221  result);
222  msg->resultcode.data =
224  goto exit;
225  }
226  /* Construct a bogus SSID and assign it to OwnSSID and
227  * DesiredSSID
228  */
229  wordbuf[0] = cpu_to_le16(WLAN_SSID_MAXLEN);
230  get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
232  wordbuf,
234  if (result) {
235  printk(KERN_ERR "Failed to set OwnSSID.\n");
236  msg->resultcode.data =
238  goto exit;
239  }
241  wordbuf,
243  if (result) {
244  printk(KERN_ERR "Failed to set DesiredSSID.\n");
245  msg->resultcode.data =
247  goto exit;
248  }
249  /* bsstype */
250  result = hfa384x_drvr_setconfig16(hw,
253  if (result) {
254  printk(KERN_ERR "Failed to set CNFPORTTYPE.\n");
255  msg->resultcode.data =
257  goto exit;
258  }
259  /* ibss options */
260  result = hfa384x_drvr_setconfig16(hw,
263  if (result) {
264  printk(KERN_ERR "Failed to set CREATEIBSS.\n");
265  msg->resultcode.data =
267  goto exit;
268  }
269  result = hfa384x_drvr_enable(hw, 0);
270  if (result) {
271  printk(KERN_ERR "drvr_enable(0) failed. "
272  "result=%d\n", result);
273  msg->resultcode.data =
275  goto exit;
276  }
277  istmpenable = 1;
278  }
279 
280  /* Figure out our timeout first Kus, then HZ */
281  timeout = msg->channellist.data.len * msg->maxchanneltime.data;
282  timeout = (timeout * HZ) / 1000;
283 
284  /* Issue the scan request */
285  hw->scanflag = 0;
286 
287  result = hfa384x_drvr_setconfig(hw,
288  HFA384x_RID_HOSTSCAN, &scanreq,
290  if (result) {
291  printk(KERN_ERR "setconfig(SCANREQUEST) failed. result=%d\n",
292  result);
293  msg->resultcode.data =
295  goto exit;
296  }
297 
298  /* sleep until info frame arrives */
299  wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
300 
302  if (hw->scanflag == -1)
303  hw->scanflag = 0;
304 
305  msg->numbss.data = hw->scanflag;
306 
307  hw->scanflag = 0;
308 
309  /* Disable port if we temporarily enabled it. */
310  if (istmpenable) {
311  result = hfa384x_drvr_disable(hw, 0);
312  if (result) {
313  printk(KERN_ERR "drvr_disable(0) failed. "
314  "result=%d\n", result);
315  msg->resultcode.data =
317  goto exit;
318  }
319  }
320 
321  /* restore original roaming mode */
322  result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
323  roamingmode);
324  if (result) {
325  printk(KERN_ERR "setconfig(ROAMMODE) failed. result=%d\n",
326  result);
327  msg->resultcode.data =
329  goto exit;
330  }
331 
332  result = 0;
334 
335 exit:
337 
338  return result;
339 }
340 
341 /*----------------------------------------------------------------
342 * prism2mgmt_scan_results
343 *
344 * Retrieve the BSS description for one of the BSSs identified in
345 * a scan.
346 *
347 * Arguments:
348 * wlandev wlan device structure
349 * msgp ptr to msg buffer
350 *
351 * Returns:
352 * 0 success and done
353 * <0 success, but we're waiting for something to finish.
354 * >0 an error occurred while handling the message.
355 * Side effects:
356 *
357 * Call context:
358 * process thread (usually)
359 * interrupt
360 ----------------------------------------------------------------*/
361 int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
362 {
363  int result = 0;
365  hfa384x_t *hw = wlandev->priv;
367 
368  int count;
369 
370  req = (struct p80211msg_dot11req_scan_results *) msgp;
371 
373 
374  if (!hw->scanresults) {
376  "dot11req_scan_results can only be used after a successful dot11req_scan.\n");
377  result = 2;
379  goto exit;
380  }
381 
382  count = (hw->scanresults->framelen - 3) / 32;
383  if (count > HFA384x_SCANRESULT_MAX)
384  count = HFA384x_SCANRESULT_MAX;
385 
386  if (req->bssindex.data >= count) {
387  pr_debug("requested index (%d) out of range (%d)\n",
388  req->bssindex.data, count);
389  result = 2;
391  goto exit;
392  }
393 
394  item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]);
395  /* signal and noise */
398  req->signal.data = le16_to_cpu(item->sl);
399  req->noise.data = le16_to_cpu(item->anl);
400 
401  /* BSSID */
403  req->bssid.data.len = WLAN_BSSID_LEN;
404  memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
405 
406  /* SSID */
408  req->ssid.data.len = le16_to_cpu(item->ssid.len);
409  req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_BSSID_LEN);
410  memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
411 
412  /* supported rates */
413  for (count = 0; count < 10; count++)
414  if (item->supprates[count] == 0)
415  break;
416 
417 #define REQBASICRATE(N) \
418  if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \
419  req->basicrate ## N .data = item->supprates[(N)-1]; \
420  req->basicrate ## N .status = \
421  P80211ENUM_msgitem_status_data_ok; \
422  }
423 
424  REQBASICRATE(1);
425  REQBASICRATE(2);
426  REQBASICRATE(3);
427  REQBASICRATE(4);
428  REQBASICRATE(5);
429  REQBASICRATE(6);
430  REQBASICRATE(7);
431  REQBASICRATE(8);
432 
433 #define REQSUPPRATE(N) \
434  if (count >= N) { \
435  req->supprate ## N .data = item->supprates[(N)-1]; \
436  req->supprate ## N .status = \
437  P80211ENUM_msgitem_status_data_ok; \
438  }
439 
440  REQSUPPRATE(1);
441  REQSUPPRATE(2);
442  REQSUPPRATE(3);
443  REQSUPPRATE(4);
444  REQSUPPRATE(5);
445  REQSUPPRATE(6);
446  REQSUPPRATE(7);
447  REQSUPPRATE(8);
448 
449  /* beacon period */
451  req->beaconperiod.data = le16_to_cpu(item->bcnint);
452 
453  /* timestamps */
455  req->timestamp.data = jiffies;
457  req->localtime.data = jiffies;
458 
459  /* atim window */
461  req->ibssatimwindow.data = le16_to_cpu(item->atim);
462 
463  /* Channel */
465  req->dschannel.data = le16_to_cpu(item->chid);
466 
467  /* capinfo bits */
468  count = le16_to_cpu(item->capinfo);
470  req->capinfo.data = count;
471 
472  /* privacy flag */
475 
476  /* cfpollable */
479 
480  /* cfpollreq */
483 
484  /* bsstype */
486  req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
488 
489  result = 0;
491 
492 exit:
493  return result;
494 }
495 
496 /*----------------------------------------------------------------
497 * prism2mgmt_start
498 *
499 * Start a BSS. Any station can do this for IBSS, only AP for ESS.
500 *
501 * Arguments:
502 * wlandev wlan device structure
503 * msgp ptr to msg buffer
504 *
505 * Returns:
506 * 0 success and done
507 * <0 success, but we're waiting for something to finish.
508 * >0 an error occurred while handling the message.
509 * Side effects:
510 *
511 * Call context:
512 * process thread (usually)
513 * interrupt
514 ----------------------------------------------------------------*/
515 int prism2mgmt_start(wlandevice_t *wlandev, void *msgp)
516 {
517  int result = 0;
518  hfa384x_t *hw = wlandev->priv;
519  struct p80211msg_dot11req_start *msg = msgp;
520 
521  p80211pstrd_t *pstr;
522  u8 bytebuf[80];
523  hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf;
524  u16 word;
525 
526  wlandev->macmode = WLAN_MACMODE_NONE;
527 
528  /* Set the SSID */
529  memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
530 
531  /*** ADHOC IBSS ***/
532  /* see if current f/w is less than 8c3 */
533  if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
534  hw->ident_sta_fw.minor,
535  hw->ident_sta_fw.variant) <
536  HFA384x_FIRMWARE_VERSION(0, 8, 3)) {
537  /* Ad-Hoc not quite supported on Prism2 */
540  goto done;
541  }
542 
544 
545  /*** STATION ***/
546  /* Set the REQUIRED config items */
547  /* SSID */
548  pstr = (p80211pstrd_t *) &(msg->ssid.data);
549  prism2mgmt_pstr2bytestr(p2bytestr, pstr);
551  bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
552  if (result) {
553  printk(KERN_ERR "Failed to set CnfOwnSSID\n");
554  goto failed;
555  }
557  bytebuf,
559  if (result) {
560  printk(KERN_ERR "Failed to set CnfDesiredSSID\n");
561  goto failed;
562  }
563 
564  /* bsstype - we use the default in the ap firmware */
565  /* IBSS port */
566  hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
567 
568  /* beacon period */
569  word = msg->beaconperiod.data;
570  result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNint, word);
571  if (result) {
572  printk(KERN_ERR "Failed to set beacon period=%d.\n", word);
573  goto failed;
574  }
575 
576  /* dschannel */
577  word = msg->dschannel.data;
578  result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
579  if (result) {
580  printk(KERN_ERR "Failed to set channel=%d.\n", word);
581  goto failed;
582  }
583  /* Basic rates */
584  word = p80211rate_to_p2bit(msg->basicrate1.data);
586  word |= p80211rate_to_p2bit(msg->basicrate2.data);
587 
589  word |= p80211rate_to_p2bit(msg->basicrate3.data);
590 
592  word |= p80211rate_to_p2bit(msg->basicrate4.data);
593 
595  word |= p80211rate_to_p2bit(msg->basicrate5.data);
596 
598  word |= p80211rate_to_p2bit(msg->basicrate6.data);
599 
601  word |= p80211rate_to_p2bit(msg->basicrate7.data);
602 
604  word |= p80211rate_to_p2bit(msg->basicrate8.data);
605 
606  result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
607  if (result) {
608  printk(KERN_ERR "Failed to set basicrates=%d.\n", word);
609  goto failed;
610  }
611 
612  /* Operational rates (supprates and txratecontrol) */
616 
619 
622 
625 
628 
631 
634 
635  result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
636  if (result) {
637  printk(KERN_ERR "Failed to set supprates=%d.\n", word);
638  goto failed;
639  }
640 
641  result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
642  if (result) {
643  printk(KERN_ERR "Failed to set txrates=%d.\n", word);
644  goto failed;
645  }
646 
647  /* Set the macmode so the frame setup code knows what to do */
649  wlandev->macmode = WLAN_MACMODE_IBSS_STA;
650  /* lets extend the data length a bit */
651  hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
652  }
653 
654  /* Enable the Port */
655  result = hfa384x_drvr_enable(hw, 0);
656  if (result) {
657  printk(KERN_ERR "Enable macport failed, result=%d.\n", result);
658  goto failed;
659  }
660 
662 
663  goto done;
664 failed:
665  pr_debug("Failed to set a config option, result=%d\n", result);
667 
668 done:
669  result = 0;
670 
671  return result;
672 }
673 
674 /*----------------------------------------------------------------
675 * prism2mgmt_readpda
676 *
677 * Collect the PDA data and put it in the message.
678 *
679 * Arguments:
680 * wlandev wlan device structure
681 * msgp ptr to msg buffer
682 *
683 * Returns:
684 * 0 success and done
685 * <0 success, but we're waiting for something to finish.
686 * >0 an error occurred while handling the message.
687 * Side effects:
688 *
689 * Call context:
690 * process thread (usually)
691 ----------------------------------------------------------------*/
692 int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp)
693 {
694  hfa384x_t *hw = wlandev->priv;
695  struct p80211msg_p2req_readpda *msg = msgp;
696  int result;
697 
698  /* We only support collecting the PDA when in the FWLOAD
699  * state.
700  */
701  if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
703  "PDA may only be read " "in the fwload state.\n");
704  msg->resultcode.data =
707  } else {
708  /* Call drvr_readpda(), it handles the auxport enable
709  * and validating the returned PDA.
710  */
711  result = hfa384x_drvr_readpda(hw,
712  msg->pda.data,
714  if (result) {
716  "hfa384x_drvr_readpda() failed, "
717  "result=%d\n", result);
718 
719  msg->resultcode.data =
721  msg->resultcode.status =
723  return 0;
724  }
728  }
729 
730  return 0;
731 }
732 
733 /*----------------------------------------------------------------
734 * prism2mgmt_ramdl_state
735 *
736 * Establishes the beginning/end of a card RAM download session.
737 *
738 * It is expected that the ramdl_write() function will be called
739 * one or more times between the 'enable' and 'disable' calls to
740 * this function.
741 *
742 * Note: This function should not be called when a mac comm port
743 * is active.
744 *
745 * Arguments:
746 * wlandev wlan device structure
747 * msgp ptr to msg buffer
748 *
749 * Returns:
750 * 0 success and done
751 * <0 success, but we're waiting for something to finish.
752 * >0 an error occurred while handling the message.
753 * Side effects:
754 *
755 * Call context:
756 * process thread (usually)
757 ----------------------------------------------------------------*/
758 int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp)
759 {
760  hfa384x_t *hw = wlandev->priv;
761  struct p80211msg_p2req_ramdl_state *msg = msgp;
762 
763  if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
765  "ramdl_state(): may only be called "
766  "in the fwload state.\n");
767  msg->resultcode.data =
770  return 0;
771  }
772 
773  /*
774  ** Note: Interrupts are locked out if this is an AP and are NOT
775  ** locked out if this is a station.
776  */
777 
779  if (msg->enable.data == P80211ENUM_truth_true) {
780  if (hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data)) {
781  msg->resultcode.data =
783  } else {
785  }
786  } else {
789  }
790 
791  return 0;
792 }
793 
794 /*----------------------------------------------------------------
795 * prism2mgmt_ramdl_write
796 *
797 * Writes a buffer to the card RAM using the download state. This
798 * is for writing code to card RAM. To just read or write raw data
799 * use the aux functions.
800 *
801 * Arguments:
802 * wlandev wlan device structure
803 * msgp ptr to msg buffer
804 *
805 * Returns:
806 * 0 success and done
807 * <0 success, but we're waiting for something to finish.
808 * >0 an error occurred while handling the message.
809 * Side effects:
810 *
811 * Call context:
812 * process thread (usually)
813 ----------------------------------------------------------------*/
814 int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp)
815 {
816  hfa384x_t *hw = wlandev->priv;
817  struct p80211msg_p2req_ramdl_write *msg = msgp;
818  u32 addr;
819  u32 len;
820  u8 *buf;
821 
822  if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
824  "ramdl_write(): may only be called "
825  "in the fwload state.\n");
826  msg->resultcode.data =
829  return 0;
830  }
831 
833  /* first validate the length */
834  if (msg->len.data > sizeof(msg->data.data)) {
835  msg->resultcode.status =
837  return 0;
838  }
839  /* call the hfa384x function to do the write */
840  addr = msg->addr.data;
841  len = msg->len.data;
842  buf = msg->data.data;
843  if (hfa384x_drvr_ramdl_write(hw, addr, buf, len))
845 
847 
848  return 0;
849 }
850 
851 /*----------------------------------------------------------------
852 * prism2mgmt_flashdl_state
853 *
854 * Establishes the beginning/end of a card Flash download session.
855 *
856 * It is expected that the flashdl_write() function will be called
857 * one or more times between the 'enable' and 'disable' calls to
858 * this function.
859 *
860 * Note: This function should not be called when a mac comm port
861 * is active.
862 *
863 * Arguments:
864 * wlandev wlan device structure
865 * msgp ptr to msg buffer
866 *
867 * Returns:
868 * 0 success and done
869 * <0 success, but we're waiting for something to finish.
870 * >0 an error occurred while handling the message.
871 * Side effects:
872 *
873 * Call context:
874 * process thread (usually)
875 ----------------------------------------------------------------*/
876 int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
877 {
878  int result = 0;
879  hfa384x_t *hw = wlandev->priv;
880  struct p80211msg_p2req_flashdl_state *msg = msgp;
881 
882  if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
884  "flashdl_state(): may only be called "
885  "in the fwload state.\n");
886  msg->resultcode.data =
889  return 0;
890  }
891 
892  /*
893  ** Note: Interrupts are locked out if this is an AP and are NOT
894  ** locked out if this is a station.
895  */
896 
898  if (msg->enable.data == P80211ENUM_truth_true) {
899  if (hfa384x_drvr_flashdl_enable(hw)) {
900  msg->resultcode.data =
902  } else {
904  }
905  } else {
908  /* NOTE: At this point, the MAC is in the post-reset
909  * state and the driver is in the fwload state.
910  * We need to get the MAC back into the fwload
911  * state. To do this, we set the nsdstate to HWPRESENT
912  * and then call the ifstate function to redo everything
913  * that got us into the fwload state.
914  */
915  wlandev->msdstate = WLAN_MSD_HWPRESENT;
916  result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
917  if (result != P80211ENUM_resultcode_success) {
918  printk(KERN_ERR "prism2sta_ifstate(fwload) failed,"
919  "P80211ENUM_resultcode=%d\n", result);
920  msg->resultcode.data =
922  result = -1;
923  }
924  }
925 
926  return 0;
927 }
928 
929 /*----------------------------------------------------------------
930 * prism2mgmt_flashdl_write
931 *
932 *
933 *
934 * Arguments:
935 * wlandev wlan device structure
936 * msgp ptr to msg buffer
937 *
938 * Returns:
939 * 0 success and done
940 * <0 success, but we're waiting for something to finish.
941 * >0 an error occurred while handling the message.
942 * Side effects:
943 *
944 * Call context:
945 * process thread (usually)
946 ----------------------------------------------------------------*/
947 int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp)
948 {
949  hfa384x_t *hw = wlandev->priv;
950  struct p80211msg_p2req_flashdl_write *msg = msgp;
951  u32 addr;
952  u32 len;
953  u8 *buf;
954 
955  if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
957  "flashdl_write(): may only be called "
958  "in the fwload state.\n");
959  msg->resultcode.data =
962  return 0;
963  }
964 
965  /*
966  ** Note: Interrupts are locked out if this is an AP and are NOT
967  ** locked out if this is a station.
968  */
969 
971  /* first validate the length */
972  if (msg->len.data > sizeof(msg->data.data)) {
973  msg->resultcode.status =
975  return 0;
976  }
977  /* call the hfa384x function to do the write */
978  addr = msg->addr.data;
979  len = msg->len.data;
980  buf = msg->data.data;
981  if (hfa384x_drvr_flashdl_write(hw, addr, buf, len))
983 
985 
986  return 0;
987 }
988 
989 /*----------------------------------------------------------------
990 * prism2mgmt_autojoin
991 *
992 * Associate with an ESS.
993 *
994 * Arguments:
995 * wlandev wlan device structure
996 * msgp ptr to msg buffer
997 *
998 * Returns:
999 * 0 success and done
1000 * <0 success, but we're waiting for something to finish.
1001 * >0 an error occurred while handling the message.
1002 * Side effects:
1003 *
1004 * Call context:
1005 * process thread (usually)
1006 * interrupt
1007 ----------------------------------------------------------------*/
1008 int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
1009 {
1010  hfa384x_t *hw = wlandev->priv;
1011  int result = 0;
1012  u16 reg;
1013  u16 port_type;
1014  struct p80211msg_lnxreq_autojoin *msg = msgp;
1015  p80211pstrd_t *pstr;
1016  u8 bytebuf[256];
1017  hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf;
1018 
1019  wlandev->macmode = WLAN_MACMODE_NONE;
1020 
1021  /* Set the SSID */
1022  memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
1023 
1024  /* Disable the Port */
1025  hfa384x_drvr_disable(hw, 0);
1026 
1027  /*** STATION ***/
1028  /* Set the TxRates */
1029  hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
1030 
1031  /* Set the auth type */
1034  else
1036 
1037  hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
1038 
1039  /* Set the ssid */
1040  memset(bytebuf, 0, 256);
1041  pstr = (p80211pstrd_t *) &(msg->ssid.data);
1042  prism2mgmt_pstr2bytestr(p2bytestr, pstr);
1044  bytebuf,
1046  port_type = HFA384x_PORTTYPE_BSS;
1047  /* Set the PortType */
1048  hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
1049 
1050  /* Enable the Port */
1051  hfa384x_drvr_enable(hw, 0);
1052 
1053  /* Set the resultcode */
1056 
1057  return result;
1058 }
1059 
1060 /*----------------------------------------------------------------
1061 * prism2mgmt_wlansniff
1062 *
1063 * Start or stop sniffing.
1064 *
1065 * Arguments:
1066 * wlandev wlan device structure
1067 * msgp ptr to msg buffer
1068 *
1069 * Returns:
1070 * 0 success and done
1071 * <0 success, but we're waiting for something to finish.
1072 * >0 an error occurred while handling the message.
1073 * Side effects:
1074 *
1075 * Call context:
1076 * process thread (usually)
1077 * interrupt
1078 ----------------------------------------------------------------*/
1079 int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
1080 {
1081  int result = 0;
1082  struct p80211msg_lnxreq_wlansniff *msg = msgp;
1083 
1084  hfa384x_t *hw = wlandev->priv;
1085  u16 word;
1086 
1088  switch (msg->enable.data) {
1090  /* Confirm that we're in monitor mode */
1091  if (wlandev->netdev->type == ARPHRD_ETHER) {
1092  msg->resultcode.data =
1094  result = 0;
1095  goto exit;
1096  }
1097  /* Disable monitor mode */
1099  if (result) {
1100  pr_debug("failed to disable monitor mode, result=%d\n",
1101  result);
1102  goto failed;
1103  }
1104  /* Disable port 0 */
1105  result = hfa384x_drvr_disable(hw, 0);
1106  if (result) {
1107  pr_debug
1108  ("failed to disable port 0 after sniffing, result=%d\n",
1109  result);
1110  goto failed;
1111  }
1112  /* Clear the driver state */
1113  wlandev->netdev->type = ARPHRD_ETHER;
1114 
1115  /* Restore the wepflags */
1116  result = hfa384x_drvr_setconfig16(hw,
1118  hw->presniff_wepflags);
1119  if (result) {
1120  pr_debug
1121  ("failed to restore wepflags=0x%04x, result=%d\n",
1122  hw->presniff_wepflags, result);
1123  goto failed;
1124  }
1125 
1126  /* Set the port to its prior type and enable (if necessary) */
1127  if (hw->presniff_port_type != 0) {
1128  word = hw->presniff_port_type;
1129  result = hfa384x_drvr_setconfig16(hw,
1131  word);
1132  if (result) {
1133  pr_debug
1134  ("failed to restore porttype, result=%d\n",
1135  result);
1136  goto failed;
1137  }
1138 
1139  /* Enable the port */
1140  result = hfa384x_drvr_enable(hw, 0);
1141  if (result) {
1142  pr_debug
1143  ("failed to enable port to presniff setting, result=%d\n",
1144  result);
1145  goto failed;
1146  }
1147  } else {
1148  result = hfa384x_drvr_disable(hw, 0);
1149 
1150  }
1151 
1152  printk(KERN_INFO "monitor mode disabled\n");
1154  result = 0;
1155  goto exit;
1156  break;
1157  case P80211ENUM_truth_true:
1158  /* Disable the port (if enabled), only check Port 0 */
1159  if (hw->port_enabled[0]) {
1160  if (wlandev->netdev->type == ARPHRD_ETHER) {
1161  /* Save macport 0 state */
1162  result = hfa384x_drvr_getconfig16(hw,
1164  &(hw->presniff_port_type));
1165  if (result) {
1166  pr_debug
1167  ("failed to read porttype, result=%d\n",
1168  result);
1169  goto failed;
1170  }
1171  /* Save the wepflags state */
1172  result = hfa384x_drvr_getconfig16(hw,
1174  &(hw->presniff_wepflags));
1175  if (result) {
1176  pr_debug
1177  ("failed to read wepflags, result=%d\n",
1178  result);
1179  goto failed;
1180  }
1181  hfa384x_drvr_stop(hw);
1182  result = hfa384x_drvr_start(hw);
1183  if (result) {
1184  pr_debug
1185  ("failed to restart the card for sniffing, result=%d\n",
1186  result);
1187  goto failed;
1188  }
1189  } else {
1190  /* Disable the port */
1191  result = hfa384x_drvr_disable(hw, 0);
1192  if (result) {
1193  pr_debug
1194  ("failed to enable port for sniffing, result=%d\n",
1195  result);
1196  goto failed;
1197  }
1198  }
1199  } else {
1200  hw->presniff_port_type = 0;
1201  }
1202 
1203  /* Set the channel we wish to sniff */
1204  word = msg->channel.data;
1205  result = hfa384x_drvr_setconfig16(hw,
1207  word);
1208  hw->sniff_channel = word;
1209 
1210  if (result) {
1211  pr_debug("failed to set channel %d, result=%d\n",
1212  word, result);
1213  goto failed;
1214  }
1215 
1216  /* Now if we're already sniffing, we can skip the rest */
1217  if (wlandev->netdev->type != ARPHRD_ETHER) {
1218  /* Set the port type to pIbss */
1220  result = hfa384x_drvr_setconfig16(hw,
1222  word);
1223  if (result) {
1224  pr_debug
1225  ("failed to set porttype %d, result=%d\n",
1226  word, result);
1227  goto failed;
1228  }
1229  if ((msg->keepwepflags.status ==
1231  && (msg->keepwepflags.data !=
1233  /* Set the wepflags for no decryption */
1236  result =
1237  hfa384x_drvr_setconfig16(hw,
1239  word);
1240  }
1241 
1242  if (result) {
1243  pr_debug
1244  ("failed to set wepflags=0x%04x, result=%d\n",
1245  word, result);
1246  goto failed;
1247  }
1248  }
1249 
1250  /* Do we want to strip the FCS in monitor mode? */
1252  && (msg->stripfcs.data == P80211ENUM_truth_true)) {
1253  hw->sniff_fcs = 0;
1254  } else {
1255  hw->sniff_fcs = 1;
1256  }
1257 
1258  /* Do we want to truncate the packets? */
1259  if (msg->packet_trunc.status ==
1261  hw->sniff_truncate = msg->packet_trunc.data;
1262  } else {
1263  hw->sniff_truncate = 0;
1264  }
1265 
1266  /* Enable the port */
1267  result = hfa384x_drvr_enable(hw, 0);
1268  if (result) {
1269  pr_debug
1270  ("failed to enable port for sniffing, result=%d\n",
1271  result);
1272  goto failed;
1273  }
1274  /* Enable monitor mode */
1276  if (result) {
1277  pr_debug("failed to enable monitor mode, result=%d\n",
1278  result);
1279  goto failed;
1280  }
1281 
1282  if (wlandev->netdev->type == ARPHRD_ETHER)
1283  printk(KERN_INFO "monitor mode enabled\n");
1284 
1285  /* Set the driver state */
1286  /* Do we want the prism2 header? */
1287  if ((msg->prismheader.status ==
1289  && (msg->prismheader.data == P80211ENUM_truth_true)) {
1290  hw->sniffhdr = 0;
1291  wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1292  } else
1293  if ((msg->wlanheader.status ==
1295  && (msg->wlanheader.data == P80211ENUM_truth_true)) {
1296  hw->sniffhdr = 1;
1297  wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
1298  } else {
1299  wlandev->netdev->type = ARPHRD_IEEE80211;
1300  }
1301 
1303  result = 0;
1304  goto exit;
1305  break;
1306  default:
1308  result = 0;
1309  goto exit;
1310  break;
1311  }
1312 
1313 failed:
1315  result = 0;
1316 exit:
1317  return result;
1318 }