PageRenderTime 865ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/staging/wlan-ng/prism2mgmt.c

https://github.com/Mengqi/linux-2.6
C | 1317 lines | 803 code | 141 blank | 373 comment | 151 complexity | 45d9d6d4f9dad040a0bdd765211b55b6 MD5 | raw 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.
  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. * 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. #include <linux/if_arp.h>
  60. #include <linux/module.h>
  61. #include <linux/kernel.h>
  62. #include <linux/wait.h>
  63. #include <linux/sched.h>
  64. #include <linux/types.h>
  65. #include <linux/wireless.h>
  66. #include <linux/netdevice.h>
  67. #include <linux/delay.h>
  68. #include <linux/io.h>
  69. #include <asm/byteorder.h>
  70. #include <linux/random.h>
  71. #include <linux/usb.h>
  72. #include <linux/bitops.h>
  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 "p80211metadef.h"
  80. #include "p80211metastruct.h"
  81. #include "hfa384x.h"
  82. #include "prism2mgmt.h"
  83. /* Converts 802.11 format rate specifications to prism2 */
  84. #define p80211rate_to_p2bit(n) ((((n)&~BIT(7)) == 2) ? BIT(0) : \
  85. (((n)&~BIT(7)) == 4) ? BIT(1) : \
  86. (((n)&~BIT(7)) == 11) ? BIT(2) : \
  87. (((n)&~BIT(7)) == 22) ? BIT(3) : 0)
  88. /*----------------------------------------------------------------
  89. * prism2mgmt_scan
  90. *
  91. * Initiate a scan for BSSs.
  92. *
  93. * This function corresponds to MLME-scan.request and part of
  94. * MLME-scan.confirm. As far as I can tell in the standard, there
  95. * are no restrictions on when a scan.request may be issued. We have
  96. * to handle in whatever state the driver/MAC happen to be.
  97. *
  98. * Arguments:
  99. * wlandev wlan device structure
  100. * msgp ptr to msg buffer
  101. *
  102. * Returns:
  103. * 0 success and done
  104. * <0 success, but we're waiting for something to finish.
  105. * >0 an error occurred while handling the message.
  106. * Side effects:
  107. *
  108. * Call context:
  109. * process thread (usually)
  110. * interrupt
  111. ----------------------------------------------------------------*/
  112. int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp)
  113. {
  114. int result = 0;
  115. hfa384x_t *hw = wlandev->priv;
  116. struct p80211msg_dot11req_scan *msg = msgp;
  117. u16 roamingmode, word;
  118. int i, timeout;
  119. int istmpenable = 0;
  120. hfa384x_HostScanRequest_data_t scanreq;
  121. /* gatekeeper check */
  122. if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
  123. hw->ident_sta_fw.minor,
  124. hw->ident_sta_fw.variant) <
  125. HFA384x_FIRMWARE_VERSION(1, 3, 2)) {
  126. printk(KERN_ERR
  127. "HostScan not supported with current firmware (<1.3.2).\n");
  128. result = 1;
  129. msg->resultcode.data = P80211ENUM_resultcode_not_supported;
  130. goto exit;
  131. }
  132. memset(&scanreq, 0, sizeof(scanreq));
  133. /* save current roaming mode */
  134. result = hfa384x_drvr_getconfig16(hw,
  135. HFA384x_RID_CNFROAMINGMODE,
  136. &roamingmode);
  137. if (result) {
  138. printk(KERN_ERR "getconfig(ROAMMODE) failed. result=%d\n",
  139. result);
  140. msg->resultcode.data =
  141. P80211ENUM_resultcode_implementation_failure;
  142. goto exit;
  143. }
  144. /* drop into mode 3 for the scan */
  145. result = hfa384x_drvr_setconfig16(hw,
  146. HFA384x_RID_CNFROAMINGMODE,
  147. HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
  148. if (result) {
  149. printk(KERN_ERR "setconfig(ROAMINGMODE) failed. result=%d\n",
  150. result);
  151. msg->resultcode.data =
  152. P80211ENUM_resultcode_implementation_failure;
  153. goto exit;
  154. }
  155. /* active or passive? */
  156. if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
  157. hw->ident_sta_fw.minor,
  158. hw->ident_sta_fw.variant) >
  159. HFA384x_FIRMWARE_VERSION(1, 5, 0)) {
  160. if (msg->scantype.data != P80211ENUM_scantype_active)
  161. word = cpu_to_le16(msg->maxchanneltime.data);
  162. else
  163. word = 0;
  164. result =
  165. hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL,
  166. word);
  167. if (result) {
  168. printk(KERN_WARNING "Passive scan not supported with "
  169. "current firmware. (<1.5.1)\n");
  170. }
  171. }
  172. /* set up the txrate to be 2MBPS. Should be fastest basicrate... */
  173. word = HFA384x_RATEBIT_2;
  174. scanreq.txRate = cpu_to_le16(word);
  175. /* set up the channel list */
  176. word = 0;
  177. for (i = 0; i < msg->channellist.data.len; i++) {
  178. u8 channel = msg->channellist.data.data[i];
  179. if (channel > 14)
  180. continue;
  181. /* channel 1 is BIT 0 ... channel 14 is BIT 13 */
  182. word |= (1 << (channel - 1));
  183. }
  184. scanreq.channelList = cpu_to_le16(word);
  185. /* set up the ssid, if present. */
  186. scanreq.ssid.len = cpu_to_le16(msg->ssid.data.len);
  187. memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);
  188. /* Enable the MAC port if it's not already enabled */
  189. result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
  190. if (result) {
  191. printk(KERN_ERR "getconfig(PORTSTATUS) failed. "
  192. "result=%d\n", result);
  193. msg->resultcode.data =
  194. P80211ENUM_resultcode_implementation_failure;
  195. goto exit;
  196. }
  197. if (word == HFA384x_PORTSTATUS_DISABLED) {
  198. u16 wordbuf[17];
  199. result = hfa384x_drvr_setconfig16(hw,
  200. HFA384x_RID_CNFROAMINGMODE,
  201. HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
  202. if (result) {
  203. printk(KERN_ERR
  204. "setconfig(ROAMINGMODE) failed. result=%d\n",
  205. result);
  206. msg->resultcode.data =
  207. P80211ENUM_resultcode_implementation_failure;
  208. goto exit;
  209. }
  210. /* Construct a bogus SSID and assign it to OwnSSID and
  211. * DesiredSSID
  212. */
  213. wordbuf[0] = cpu_to_le16(WLAN_SSID_MAXLEN);
  214. get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
  215. result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
  216. wordbuf,
  217. HFA384x_RID_CNFOWNSSID_LEN);
  218. if (result) {
  219. printk(KERN_ERR "Failed to set OwnSSID.\n");
  220. msg->resultcode.data =
  221. P80211ENUM_resultcode_implementation_failure;
  222. goto exit;
  223. }
  224. result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
  225. wordbuf,
  226. HFA384x_RID_CNFDESIREDSSID_LEN);
  227. if (result) {
  228. printk(KERN_ERR "Failed to set DesiredSSID.\n");
  229. msg->resultcode.data =
  230. P80211ENUM_resultcode_implementation_failure;
  231. goto exit;
  232. }
  233. /* bsstype */
  234. result = hfa384x_drvr_setconfig16(hw,
  235. HFA384x_RID_CNFPORTTYPE,
  236. HFA384x_PORTTYPE_IBSS);
  237. if (result) {
  238. printk(KERN_ERR "Failed to set CNFPORTTYPE.\n");
  239. msg->resultcode.data =
  240. P80211ENUM_resultcode_implementation_failure;
  241. goto exit;
  242. }
  243. /* ibss options */
  244. result = hfa384x_drvr_setconfig16(hw,
  245. HFA384x_RID_CREATEIBSS,
  246. HFA384x_CREATEIBSS_JOINCREATEIBSS);
  247. if (result) {
  248. printk(KERN_ERR "Failed to set CREATEIBSS.\n");
  249. msg->resultcode.data =
  250. P80211ENUM_resultcode_implementation_failure;
  251. goto exit;
  252. }
  253. result = hfa384x_drvr_enable(hw, 0);
  254. if (result) {
  255. printk(KERN_ERR "drvr_enable(0) failed. "
  256. "result=%d\n", result);
  257. msg->resultcode.data =
  258. P80211ENUM_resultcode_implementation_failure;
  259. goto exit;
  260. }
  261. istmpenable = 1;
  262. }
  263. /* Figure out our timeout first Kus, then HZ */
  264. timeout = msg->channellist.data.len * msg->maxchanneltime.data;
  265. timeout = (timeout * HZ) / 1000;
  266. /* Issue the scan request */
  267. hw->scanflag = 0;
  268. result = hfa384x_drvr_setconfig(hw,
  269. HFA384x_RID_HOSTSCAN, &scanreq,
  270. sizeof(hfa384x_HostScanRequest_data_t));
  271. if (result) {
  272. printk(KERN_ERR "setconfig(SCANREQUEST) failed. result=%d\n",
  273. result);
  274. msg->resultcode.data =
  275. P80211ENUM_resultcode_implementation_failure;
  276. goto exit;
  277. }
  278. /* sleep until info frame arrives */
  279. wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);
  280. msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
  281. if (hw->scanflag == -1)
  282. hw->scanflag = 0;
  283. msg->numbss.data = hw->scanflag;
  284. hw->scanflag = 0;
  285. /* Disable port if we temporarily enabled it. */
  286. if (istmpenable) {
  287. result = hfa384x_drvr_disable(hw, 0);
  288. if (result) {
  289. printk(KERN_ERR "drvr_disable(0) failed. "
  290. "result=%d\n", result);
  291. msg->resultcode.data =
  292. P80211ENUM_resultcode_implementation_failure;
  293. goto exit;
  294. }
  295. }
  296. /* restore original roaming mode */
  297. result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
  298. roamingmode);
  299. if (result) {
  300. printk(KERN_ERR "setconfig(ROAMMODE) failed. result=%d\n",
  301. result);
  302. msg->resultcode.data =
  303. P80211ENUM_resultcode_implementation_failure;
  304. goto exit;
  305. }
  306. result = 0;
  307. msg->resultcode.data = P80211ENUM_resultcode_success;
  308. exit:
  309. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  310. return result;
  311. }
  312. /*----------------------------------------------------------------
  313. * prism2mgmt_scan_results
  314. *
  315. * Retrieve the BSS description for one of the BSSs identified in
  316. * a scan.
  317. *
  318. * Arguments:
  319. * wlandev wlan device structure
  320. * msgp ptr to msg buffer
  321. *
  322. * Returns:
  323. * 0 success and done
  324. * <0 success, but we're waiting for something to finish.
  325. * >0 an error occurred while handling the message.
  326. * Side effects:
  327. *
  328. * Call context:
  329. * process thread (usually)
  330. * interrupt
  331. ----------------------------------------------------------------*/
  332. int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp)
  333. {
  334. int result = 0;
  335. struct p80211msg_dot11req_scan_results *req;
  336. hfa384x_t *hw = wlandev->priv;
  337. hfa384x_HScanResultSub_t *item = NULL;
  338. int count;
  339. req = (struct p80211msg_dot11req_scan_results *) msgp;
  340. req->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  341. if (!hw->scanresults) {
  342. printk(KERN_ERR
  343. "dot11req_scan_results can only be used after a successful dot11req_scan.\n");
  344. result = 2;
  345. req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
  346. goto exit;
  347. }
  348. count = (hw->scanresults->framelen - 3) / 32;
  349. if (count > 32)
  350. count = 32;
  351. if (req->bssindex.data >= count) {
  352. pr_debug("requested index (%d) out of range (%d)\n",
  353. req->bssindex.data, count);
  354. result = 2;
  355. req->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
  356. goto exit;
  357. }
  358. item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]);
  359. /* signal and noise */
  360. req->signal.status = P80211ENUM_msgitem_status_data_ok;
  361. req->noise.status = P80211ENUM_msgitem_status_data_ok;
  362. req->signal.data = le16_to_cpu(item->sl);
  363. req->noise.data = le16_to_cpu(item->anl);
  364. /* BSSID */
  365. req->bssid.status = P80211ENUM_msgitem_status_data_ok;
  366. req->bssid.data.len = WLAN_BSSID_LEN;
  367. memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN);
  368. /* SSID */
  369. req->ssid.status = P80211ENUM_msgitem_status_data_ok;
  370. req->ssid.data.len = le16_to_cpu(item->ssid.len);
  371. memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
  372. /* supported rates */
  373. for (count = 0; count < 10; count++)
  374. if (item->supprates[count] == 0)
  375. break;
  376. #define REQBASICRATE(N) \
  377. if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \
  378. req->basicrate ## N .data = item->supprates[(N)-1]; \
  379. req->basicrate ## N .status = \
  380. P80211ENUM_msgitem_status_data_ok; \
  381. }
  382. REQBASICRATE(1);
  383. REQBASICRATE(2);
  384. REQBASICRATE(3);
  385. REQBASICRATE(4);
  386. REQBASICRATE(5);
  387. REQBASICRATE(6);
  388. REQBASICRATE(7);
  389. REQBASICRATE(8);
  390. #define REQSUPPRATE(N) \
  391. if (count >= N) { \
  392. req->supprate ## N .data = item->supprates[(N)-1]; \
  393. req->supprate ## N .status = \
  394. P80211ENUM_msgitem_status_data_ok; \
  395. }
  396. REQSUPPRATE(1);
  397. REQSUPPRATE(2);
  398. REQSUPPRATE(3);
  399. REQSUPPRATE(4);
  400. REQSUPPRATE(5);
  401. REQSUPPRATE(6);
  402. REQSUPPRATE(7);
  403. REQSUPPRATE(8);
  404. /* beacon period */
  405. req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok;
  406. req->beaconperiod.data = le16_to_cpu(item->bcnint);
  407. /* timestamps */
  408. req->timestamp.status = P80211ENUM_msgitem_status_data_ok;
  409. req->timestamp.data = jiffies;
  410. req->localtime.status = P80211ENUM_msgitem_status_data_ok;
  411. req->localtime.data = jiffies;
  412. /* atim window */
  413. req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok;
  414. req->ibssatimwindow.data = le16_to_cpu(item->atim);
  415. /* Channel */
  416. req->dschannel.status = P80211ENUM_msgitem_status_data_ok;
  417. req->dschannel.data = le16_to_cpu(item->chid);
  418. /* capinfo bits */
  419. count = le16_to_cpu(item->capinfo);
  420. req->capinfo.status = P80211ENUM_msgitem_status_data_ok;
  421. req->capinfo.data = count;
  422. /* privacy flag */
  423. req->privacy.status = P80211ENUM_msgitem_status_data_ok;
  424. req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count);
  425. /* cfpollable */
  426. req->cfpollable.status = P80211ENUM_msgitem_status_data_ok;
  427. req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count);
  428. /* cfpollreq */
  429. req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok;
  430. req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count);
  431. /* bsstype */
  432. req->bsstype.status = P80211ENUM_msgitem_status_data_ok;
  433. req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ?
  434. P80211ENUM_bsstype_infrastructure : P80211ENUM_bsstype_independent;
  435. result = 0;
  436. req->resultcode.data = P80211ENUM_resultcode_success;
  437. exit:
  438. return result;
  439. }
  440. /*----------------------------------------------------------------
  441. * prism2mgmt_start
  442. *
  443. * Start a BSS. Any station can do this for IBSS, only AP for ESS.
  444. *
  445. * Arguments:
  446. * wlandev wlan device structure
  447. * msgp ptr to msg buffer
  448. *
  449. * Returns:
  450. * 0 success and done
  451. * <0 success, but we're waiting for something to finish.
  452. * >0 an error occurred while handling the message.
  453. * Side effects:
  454. *
  455. * Call context:
  456. * process thread (usually)
  457. * interrupt
  458. ----------------------------------------------------------------*/
  459. int prism2mgmt_start(wlandevice_t *wlandev, void *msgp)
  460. {
  461. int result = 0;
  462. hfa384x_t *hw = wlandev->priv;
  463. struct p80211msg_dot11req_start *msg = msgp;
  464. p80211pstrd_t *pstr;
  465. u8 bytebuf[80];
  466. hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf;
  467. u16 word;
  468. wlandev->macmode = WLAN_MACMODE_NONE;
  469. /* Set the SSID */
  470. memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
  471. /*** ADHOC IBSS ***/
  472. /* see if current f/w is less than 8c3 */
  473. if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
  474. hw->ident_sta_fw.minor,
  475. hw->ident_sta_fw.variant) <
  476. HFA384x_FIRMWARE_VERSION(0, 8, 3)) {
  477. /* Ad-Hoc not quite supported on Prism2 */
  478. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  479. msg->resultcode.data = P80211ENUM_resultcode_not_supported;
  480. goto done;
  481. }
  482. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  483. /*** STATION ***/
  484. /* Set the REQUIRED config items */
  485. /* SSID */
  486. pstr = (p80211pstrd_t *) &(msg->ssid.data);
  487. prism2mgmt_pstr2bytestr(p2bytestr, pstr);
  488. result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
  489. bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
  490. if (result) {
  491. printk(KERN_ERR "Failed to set CnfOwnSSID\n");
  492. goto failed;
  493. }
  494. result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
  495. bytebuf,
  496. HFA384x_RID_CNFDESIREDSSID_LEN);
  497. if (result) {
  498. printk(KERN_ERR "Failed to set CnfDesiredSSID\n");
  499. goto failed;
  500. }
  501. /* bsstype - we use the default in the ap firmware */
  502. /* IBSS port */
  503. hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0);
  504. /* beacon period */
  505. word = msg->beaconperiod.data;
  506. result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNint, word);
  507. if (result) {
  508. printk(KERN_ERR "Failed to set beacon period=%d.\n", word);
  509. goto failed;
  510. }
  511. /* dschannel */
  512. word = msg->dschannel.data;
  513. result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word);
  514. if (result) {
  515. printk(KERN_ERR "Failed to set channel=%d.\n", word);
  516. goto failed;
  517. }
  518. /* Basic rates */
  519. word = p80211rate_to_p2bit(msg->basicrate1.data);
  520. if (msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok)
  521. word |= p80211rate_to_p2bit(msg->basicrate2.data);
  522. if (msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok)
  523. word |= p80211rate_to_p2bit(msg->basicrate3.data);
  524. if (msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok)
  525. word |= p80211rate_to_p2bit(msg->basicrate4.data);
  526. if (msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok)
  527. word |= p80211rate_to_p2bit(msg->basicrate5.data);
  528. if (msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok)
  529. word |= p80211rate_to_p2bit(msg->basicrate6.data);
  530. if (msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok)
  531. word |= p80211rate_to_p2bit(msg->basicrate7.data);
  532. if (msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok)
  533. word |= p80211rate_to_p2bit(msg->basicrate8.data);
  534. result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word);
  535. if (result) {
  536. printk(KERN_ERR "Failed to set basicrates=%d.\n", word);
  537. goto failed;
  538. }
  539. /* Operational rates (supprates and txratecontrol) */
  540. word = p80211rate_to_p2bit(msg->operationalrate1.data);
  541. if (msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok)
  542. word |= p80211rate_to_p2bit(msg->operationalrate2.data);
  543. if (msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok)
  544. word |= p80211rate_to_p2bit(msg->operationalrate3.data);
  545. if (msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok)
  546. word |= p80211rate_to_p2bit(msg->operationalrate4.data);
  547. if (msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok)
  548. word |= p80211rate_to_p2bit(msg->operationalrate5.data);
  549. if (msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok)
  550. word |= p80211rate_to_p2bit(msg->operationalrate6.data);
  551. if (msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok)
  552. word |= p80211rate_to_p2bit(msg->operationalrate7.data);
  553. if (msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok)
  554. word |= p80211rate_to_p2bit(msg->operationalrate8.data);
  555. result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word);
  556. if (result) {
  557. printk(KERN_ERR "Failed to set supprates=%d.\n", word);
  558. goto failed;
  559. }
  560. result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word);
  561. if (result) {
  562. printk(KERN_ERR "Failed to set txrates=%d.\n", word);
  563. goto failed;
  564. }
  565. /* Set the macmode so the frame setup code knows what to do */
  566. if (msg->bsstype.data == P80211ENUM_bsstype_independent) {
  567. wlandev->macmode = WLAN_MACMODE_IBSS_STA;
  568. /* lets extend the data length a bit */
  569. hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304);
  570. }
  571. /* Enable the Port */
  572. result = hfa384x_drvr_enable(hw, 0);
  573. if (result) {
  574. printk(KERN_ERR "Enable macport failed, result=%d.\n", result);
  575. goto failed;
  576. }
  577. msg->resultcode.data = P80211ENUM_resultcode_success;
  578. goto done;
  579. failed:
  580. pr_debug("Failed to set a config option, result=%d\n", result);
  581. msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
  582. done:
  583. result = 0;
  584. return result;
  585. }
  586. /*----------------------------------------------------------------
  587. * prism2mgmt_readpda
  588. *
  589. * Collect the PDA data and put it in the message.
  590. *
  591. * Arguments:
  592. * wlandev wlan device structure
  593. * msgp ptr to msg buffer
  594. *
  595. * Returns:
  596. * 0 success and done
  597. * <0 success, but we're waiting for something to finish.
  598. * >0 an error occurred while handling the message.
  599. * Side effects:
  600. *
  601. * Call context:
  602. * process thread (usually)
  603. ----------------------------------------------------------------*/
  604. int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp)
  605. {
  606. hfa384x_t *hw = wlandev->priv;
  607. struct p80211msg_p2req_readpda *msg = msgp;
  608. int result;
  609. /* We only support collecting the PDA when in the FWLOAD
  610. * state.
  611. */
  612. if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
  613. printk(KERN_ERR
  614. "PDA may only be read " "in the fwload state.\n");
  615. msg->resultcode.data =
  616. P80211ENUM_resultcode_implementation_failure;
  617. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  618. } else {
  619. /* Call drvr_readpda(), it handles the auxport enable
  620. * and validating the returned PDA.
  621. */
  622. result = hfa384x_drvr_readpda(hw,
  623. msg->pda.data,
  624. HFA384x_PDA_LEN_MAX);
  625. if (result) {
  626. printk(KERN_ERR
  627. "hfa384x_drvr_readpda() failed, "
  628. "result=%d\n", result);
  629. msg->resultcode.data =
  630. P80211ENUM_resultcode_implementation_failure;
  631. msg->resultcode.status =
  632. P80211ENUM_msgitem_status_data_ok;
  633. return 0;
  634. }
  635. msg->pda.status = P80211ENUM_msgitem_status_data_ok;
  636. msg->resultcode.data = P80211ENUM_resultcode_success;
  637. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  638. }
  639. return 0;
  640. }
  641. /*----------------------------------------------------------------
  642. * prism2mgmt_ramdl_state
  643. *
  644. * Establishes the beginning/end of a card RAM download session.
  645. *
  646. * It is expected that the ramdl_write() function will be called
  647. * one or more times between the 'enable' and 'disable' calls to
  648. * this function.
  649. *
  650. * Note: This function should not be called when a mac comm port
  651. * is active.
  652. *
  653. * Arguments:
  654. * wlandev wlan device structure
  655. * msgp ptr to msg buffer
  656. *
  657. * Returns:
  658. * 0 success and done
  659. * <0 success, but we're waiting for something to finish.
  660. * >0 an error occurred while handling the message.
  661. * Side effects:
  662. *
  663. * Call context:
  664. * process thread (usually)
  665. ----------------------------------------------------------------*/
  666. int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp)
  667. {
  668. hfa384x_t *hw = wlandev->priv;
  669. struct p80211msg_p2req_ramdl_state *msg = msgp;
  670. if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
  671. printk(KERN_ERR
  672. "ramdl_state(): may only be called "
  673. "in the fwload state.\n");
  674. msg->resultcode.data =
  675. P80211ENUM_resultcode_implementation_failure;
  676. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  677. return 0;
  678. }
  679. /*
  680. ** Note: Interrupts are locked out if this is an AP and are NOT
  681. ** locked out if this is a station.
  682. */
  683. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  684. if (msg->enable.data == P80211ENUM_truth_true) {
  685. if (hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data)) {
  686. msg->resultcode.data =
  687. P80211ENUM_resultcode_implementation_failure;
  688. } else {
  689. msg->resultcode.data = P80211ENUM_resultcode_success;
  690. }
  691. } else {
  692. hfa384x_drvr_ramdl_disable(hw);
  693. msg->resultcode.data = P80211ENUM_resultcode_success;
  694. }
  695. return 0;
  696. }
  697. /*----------------------------------------------------------------
  698. * prism2mgmt_ramdl_write
  699. *
  700. * Writes a buffer to the card RAM using the download state. This
  701. * is for writing code to card RAM. To just read or write raw data
  702. * use the aux functions.
  703. *
  704. * Arguments:
  705. * wlandev wlan device structure
  706. * msgp ptr to msg buffer
  707. *
  708. * Returns:
  709. * 0 success and done
  710. * <0 success, but we're waiting for something to finish.
  711. * >0 an error occurred while handling the message.
  712. * Side effects:
  713. *
  714. * Call context:
  715. * process thread (usually)
  716. ----------------------------------------------------------------*/
  717. int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp)
  718. {
  719. hfa384x_t *hw = wlandev->priv;
  720. struct p80211msg_p2req_ramdl_write *msg = msgp;
  721. u32 addr;
  722. u32 len;
  723. u8 *buf;
  724. if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
  725. printk(KERN_ERR
  726. "ramdl_write(): may only be called "
  727. "in the fwload state.\n");
  728. msg->resultcode.data =
  729. P80211ENUM_resultcode_implementation_failure;
  730. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  731. return 0;
  732. }
  733. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  734. /* first validate the length */
  735. if (msg->len.data > sizeof(msg->data.data)) {
  736. msg->resultcode.status =
  737. P80211ENUM_resultcode_invalid_parameters;
  738. return 0;
  739. }
  740. /* call the hfa384x function to do the write */
  741. addr = msg->addr.data;
  742. len = msg->len.data;
  743. buf = msg->data.data;
  744. if (hfa384x_drvr_ramdl_write(hw, addr, buf, len))
  745. msg->resultcode.data = P80211ENUM_resultcode_refused;
  746. msg->resultcode.data = P80211ENUM_resultcode_success;
  747. return 0;
  748. }
  749. /*----------------------------------------------------------------
  750. * prism2mgmt_flashdl_state
  751. *
  752. * Establishes the beginning/end of a card Flash download session.
  753. *
  754. * It is expected that the flashdl_write() function will be called
  755. * one or more times between the 'enable' and 'disable' calls to
  756. * this function.
  757. *
  758. * Note: This function should not be called when a mac comm port
  759. * is active.
  760. *
  761. * Arguments:
  762. * wlandev wlan device structure
  763. * msgp ptr to msg buffer
  764. *
  765. * Returns:
  766. * 0 success and done
  767. * <0 success, but we're waiting for something to finish.
  768. * >0 an error occurred while handling the message.
  769. * Side effects:
  770. *
  771. * Call context:
  772. * process thread (usually)
  773. ----------------------------------------------------------------*/
  774. int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp)
  775. {
  776. int result = 0;
  777. hfa384x_t *hw = wlandev->priv;
  778. struct p80211msg_p2req_flashdl_state *msg = msgp;
  779. if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
  780. printk(KERN_ERR
  781. "flashdl_state(): may only be called "
  782. "in the fwload state.\n");
  783. msg->resultcode.data =
  784. P80211ENUM_resultcode_implementation_failure;
  785. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  786. return 0;
  787. }
  788. /*
  789. ** Note: Interrupts are locked out if this is an AP and are NOT
  790. ** locked out if this is a station.
  791. */
  792. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  793. if (msg->enable.data == P80211ENUM_truth_true) {
  794. if (hfa384x_drvr_flashdl_enable(hw)) {
  795. msg->resultcode.data =
  796. P80211ENUM_resultcode_implementation_failure;
  797. } else {
  798. msg->resultcode.data = P80211ENUM_resultcode_success;
  799. }
  800. } else {
  801. hfa384x_drvr_flashdl_disable(hw);
  802. msg->resultcode.data = P80211ENUM_resultcode_success;
  803. /* NOTE: At this point, the MAC is in the post-reset
  804. * state and the driver is in the fwload state.
  805. * We need to get the MAC back into the fwload
  806. * state. To do this, we set the nsdstate to HWPRESENT
  807. * and then call the ifstate function to redo everything
  808. * that got us into the fwload state.
  809. */
  810. wlandev->msdstate = WLAN_MSD_HWPRESENT;
  811. result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload);
  812. if (result != P80211ENUM_resultcode_success) {
  813. printk(KERN_ERR "prism2sta_ifstate(fwload) failed,"
  814. "P80211ENUM_resultcode=%d\n", result);
  815. msg->resultcode.data =
  816. P80211ENUM_resultcode_implementation_failure;
  817. result = -1;
  818. }
  819. }
  820. return 0;
  821. }
  822. /*----------------------------------------------------------------
  823. * prism2mgmt_flashdl_write
  824. *
  825. *
  826. *
  827. * Arguments:
  828. * wlandev wlan device structure
  829. * msgp ptr to msg buffer
  830. *
  831. * Returns:
  832. * 0 success and done
  833. * <0 success, but we're waiting for something to finish.
  834. * >0 an error occurred while handling the message.
  835. * Side effects:
  836. *
  837. * Call context:
  838. * process thread (usually)
  839. ----------------------------------------------------------------*/
  840. int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp)
  841. {
  842. hfa384x_t *hw = wlandev->priv;
  843. struct p80211msg_p2req_flashdl_write *msg = msgp;
  844. u32 addr;
  845. u32 len;
  846. u8 *buf;
  847. if (wlandev->msdstate != WLAN_MSD_FWLOAD) {
  848. printk(KERN_ERR
  849. "flashdl_write(): may only be called "
  850. "in the fwload state.\n");
  851. msg->resultcode.data =
  852. P80211ENUM_resultcode_implementation_failure;
  853. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  854. return 0;
  855. }
  856. /*
  857. ** Note: Interrupts are locked out if this is an AP and are NOT
  858. ** locked out if this is a station.
  859. */
  860. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  861. /* first validate the length */
  862. if (msg->len.data > sizeof(msg->data.data)) {
  863. msg->resultcode.status =
  864. P80211ENUM_resultcode_invalid_parameters;
  865. return 0;
  866. }
  867. /* call the hfa384x function to do the write */
  868. addr = msg->addr.data;
  869. len = msg->len.data;
  870. buf = msg->data.data;
  871. if (hfa384x_drvr_flashdl_write(hw, addr, buf, len))
  872. msg->resultcode.data = P80211ENUM_resultcode_refused;
  873. msg->resultcode.data = P80211ENUM_resultcode_success;
  874. return 0;
  875. }
  876. /*----------------------------------------------------------------
  877. * prism2mgmt_autojoin
  878. *
  879. * Associate with an ESS.
  880. *
  881. * Arguments:
  882. * wlandev wlan device structure
  883. * msgp ptr to msg buffer
  884. *
  885. * Returns:
  886. * 0 success and done
  887. * <0 success, but we're waiting for something to finish.
  888. * >0 an error occurred while handling the message.
  889. * Side effects:
  890. *
  891. * Call context:
  892. * process thread (usually)
  893. * interrupt
  894. ----------------------------------------------------------------*/
  895. int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
  896. {
  897. hfa384x_t *hw = wlandev->priv;
  898. int result = 0;
  899. u16 reg;
  900. u16 port_type;
  901. struct p80211msg_lnxreq_autojoin *msg = msgp;
  902. p80211pstrd_t *pstr;
  903. u8 bytebuf[256];
  904. hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf;
  905. wlandev->macmode = WLAN_MACMODE_NONE;
  906. /* Set the SSID */
  907. memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data));
  908. /* Disable the Port */
  909. hfa384x_drvr_disable(hw, 0);
  910. /*** STATION ***/
  911. /* Set the TxRates */
  912. hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f);
  913. /* Set the auth type */
  914. if (msg->authtype.data == P80211ENUM_authalg_sharedkey)
  915. reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY;
  916. else
  917. reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM;
  918. hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg);
  919. /* Set the ssid */
  920. memset(bytebuf, 0, 256);
  921. pstr = (p80211pstrd_t *) &(msg->ssid.data);
  922. prism2mgmt_pstr2bytestr(p2bytestr, pstr);
  923. result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
  924. bytebuf,
  925. HFA384x_RID_CNFDESIREDSSID_LEN);
  926. port_type = HFA384x_PORTTYPE_BSS;
  927. /* Set the PortType */
  928. hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type);
  929. /* Enable the Port */
  930. hfa384x_drvr_enable(hw, 0);
  931. /* Set the resultcode */
  932. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  933. msg->resultcode.data = P80211ENUM_resultcode_success;
  934. return result;
  935. }
  936. /*----------------------------------------------------------------
  937. * prism2mgmt_wlansniff
  938. *
  939. * Start or stop sniffing.
  940. *
  941. * Arguments:
  942. * wlandev wlan device structure
  943. * msgp ptr to msg buffer
  944. *
  945. * Returns:
  946. * 0 success and done
  947. * <0 success, but we're waiting for something to finish.
  948. * >0 an error occurred while handling the message.
  949. * Side effects:
  950. *
  951. * Call context:
  952. * process thread (usually)
  953. * interrupt
  954. ----------------------------------------------------------------*/
  955. int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
  956. {
  957. int result = 0;
  958. struct p80211msg_lnxreq_wlansniff *msg = msgp;
  959. hfa384x_t *hw = wlandev->priv;
  960. u16 word;
  961. msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;
  962. switch (msg->enable.data) {
  963. case P80211ENUM_truth_false:
  964. /* Confirm that we're in monitor mode */
  965. if (wlandev->netdev->type == ARPHRD_ETHER) {
  966. msg->resultcode.data =
  967. P80211ENUM_resultcode_invalid_parameters;
  968. result = 0;
  969. goto exit;
  970. }
  971. /* Disable monitor mode */
  972. result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE);
  973. if (result) {
  974. pr_debug("failed to disable monitor mode, result=%d\n",
  975. result);
  976. goto failed;
  977. }
  978. /* Disable port 0 */
  979. result = hfa384x_drvr_disable(hw, 0);
  980. if (result) {
  981. pr_debug
  982. ("failed to disable port 0 after sniffing, result=%d\n",
  983. result);
  984. goto failed;
  985. }
  986. /* Clear the driver state */
  987. wlandev->netdev->type = ARPHRD_ETHER;
  988. /* Restore the wepflags */
  989. result = hfa384x_drvr_setconfig16(hw,
  990. HFA384x_RID_CNFWEPFLAGS,
  991. hw->presniff_wepflags);
  992. if (result) {
  993. pr_debug
  994. ("failed to restore wepflags=0x%04x, result=%d\n",
  995. hw->presniff_wepflags, result);
  996. goto failed;
  997. }
  998. /* Set the port to its prior type and enable (if necessary) */
  999. if (hw->presniff_port_type != 0) {
  1000. word = hw->presniff_port_type;
  1001. result = hfa384x_drvr_setconfig16(hw,
  1002. HFA384x_RID_CNFPORTTYPE,
  1003. word);
  1004. if (result) {
  1005. pr_debug
  1006. ("failed to restore porttype, result=%d\n",
  1007. result);
  1008. goto failed;
  1009. }
  1010. /* Enable the port */
  1011. result = hfa384x_drvr_enable(hw, 0);
  1012. if (result) {
  1013. pr_debug
  1014. ("failed to enable port to presniff setting, result=%d\n",
  1015. result);
  1016. goto failed;
  1017. }
  1018. } else {
  1019. result = hfa384x_drvr_disable(hw, 0);
  1020. }
  1021. printk(KERN_INFO "monitor mode disabled\n");
  1022. msg->resultcode.data = P80211ENUM_resultcode_success;
  1023. result = 0;
  1024. goto exit;
  1025. break;
  1026. case P80211ENUM_truth_true:
  1027. /* Disable the port (if enabled), only check Port 0 */
  1028. if (hw->port_enabled[0]) {
  1029. if (wlandev->netdev->type == ARPHRD_ETHER) {
  1030. /* Save macport 0 state */
  1031. result = hfa384x_drvr_getconfig16(hw,
  1032. HFA384x_RID_CNFPORTTYPE,
  1033. &(hw->presniff_port_type));
  1034. if (result) {
  1035. pr_debug
  1036. ("failed to read porttype, result=%d\n",
  1037. result);
  1038. goto failed;
  1039. }
  1040. /* Save the wepflags state */
  1041. result = hfa384x_drvr_getconfig16(hw,
  1042. HFA384x_RID_CNFWEPFLAGS,
  1043. &(hw->presniff_wepflags));
  1044. if (result) {
  1045. pr_debug
  1046. ("failed to read wepflags, result=%d\n",
  1047. result);
  1048. goto failed;
  1049. }
  1050. hfa384x_drvr_stop(hw);
  1051. result = hfa384x_drvr_start(hw);
  1052. if (result) {
  1053. pr_debug
  1054. ("failed to restart the card for sniffing, result=%d\n",
  1055. result);
  1056. goto failed;
  1057. }
  1058. } else {
  1059. /* Disable the port */
  1060. result = hfa384x_drvr_disable(hw, 0);
  1061. if (result) {
  1062. pr_debug
  1063. ("failed to enable port for sniffing, result=%d\n",
  1064. result);
  1065. goto failed;
  1066. }
  1067. }
  1068. } else {
  1069. hw->presniff_port_type = 0;
  1070. }
  1071. /* Set the channel we wish to sniff */
  1072. word = msg->channel.data;
  1073. result = hfa384x_drvr_setconfig16(hw,
  1074. HFA384x_RID_CNFOWNCHANNEL,
  1075. word);
  1076. hw->sniff_channel = word;
  1077. if (result) {
  1078. pr_debug("failed to set channel %d, result=%d\n",
  1079. word, result);
  1080. goto failed;
  1081. }
  1082. /* Now if we're already sniffing, we can skip the rest */
  1083. if (wlandev->netdev->type != ARPHRD_ETHER) {
  1084. /* Set the port type to pIbss */
  1085. word = HFA384x_PORTTYPE_PSUEDOIBSS;
  1086. result = hfa384x_drvr_setconfig16(hw,
  1087. HFA384x_RID_CNFPORTTYPE,
  1088. word);
  1089. if (result) {
  1090. pr_debug
  1091. ("failed to set porttype %d, result=%d\n",
  1092. word, result);
  1093. goto failed;
  1094. }
  1095. if ((msg->keepwepflags.status ==
  1096. P80211ENUM_msgitem_status_data_ok)
  1097. && (msg->keepwepflags.data !=
  1098. P80211ENUM_truth_true)) {
  1099. /* Set the wepflags for no decryption */
  1100. word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT |
  1101. HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
  1102. result =
  1103. hfa384x_drvr_setconfig16(hw,
  1104. HFA384x_RID_CNFWEPFLAGS,
  1105. word);
  1106. }
  1107. if (result) {
  1108. pr_debug
  1109. ("failed to set wepflags=0x%04x, result=%d\n",
  1110. word, result);
  1111. goto failed;
  1112. }
  1113. }
  1114. /* Do we want to strip the FCS in monitor mode? */
  1115. if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok)
  1116. && (msg->stripfcs.data == P80211ENUM_truth_true)) {
  1117. hw->sniff_fcs = 0;
  1118. } else {
  1119. hw->sniff_fcs = 1;
  1120. }
  1121. /* Do we want to truncate the packets? */
  1122. if (msg->packet_trunc.status ==
  1123. P80211ENUM_msgitem_status_data_ok) {
  1124. hw->sniff_truncate = msg->packet_trunc.data;
  1125. } else {
  1126. hw->sniff_truncate = 0;
  1127. }
  1128. /* Enable the port */
  1129. result = hfa384x_drvr_enable(hw, 0);
  1130. if (result) {
  1131. pr_debug
  1132. ("failed to enable port for sniffing, result=%d\n",
  1133. result);
  1134. goto failed;
  1135. }
  1136. /* Enable monitor mode */
  1137. result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE);
  1138. if (result) {
  1139. pr_debug("failed to enable monitor mode, result=%d\n",
  1140. result);
  1141. goto failed;
  1142. }
  1143. if (wlandev->netdev->type == ARPHRD_ETHER)
  1144. printk(KERN_INFO "monitor mode enabled\n");
  1145. /* Set the driver state */
  1146. /* Do we want the prism2 header? */
  1147. if ((msg->prismheader.status ==
  1148. P80211ENUM_msgitem_status_data_ok)
  1149. && (msg->prismheader.data == P80211ENUM_truth_true)) {
  1150. hw->sniffhdr = 0;
  1151. wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
  1152. } else
  1153. if ((msg->wlanheader.status ==
  1154. P80211ENUM_msgitem_status_data_ok)
  1155. && (msg->wlanheader.data == P80211ENUM_truth_true)) {
  1156. hw->sniffhdr = 1;
  1157. wlandev->netdev->type = ARPHRD_IEEE80211_PRISM;
  1158. } else {
  1159. wlandev->netdev->type = ARPHRD_IEEE80211;
  1160. }
  1161. msg->resultcode.data = P80211ENUM_resultcode_success;
  1162. result = 0;
  1163. goto exit;
  1164. break;
  1165. default:
  1166. msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters;
  1167. result = 0;
  1168. goto exit;
  1169. break;
  1170. }
  1171. failed:
  1172. msg->resultcode.data = P80211ENUM_resultcode_refused;
  1173. result = 0;
  1174. exit:
  1175. return result;
  1176. }