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 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----------------------------------------------------------------*/ 116int 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 125 hfa384x_HostScanRequest_data_t scanreq; 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)) { 132 printk(KERN_ERR 133 "HostScan not supported with current firmware (<1.3.2).\n"); 134 result = 1; 135 msg->resultcode.data = P80211ENUM_resultcode_not_supported; 136 goto exit; 137 } 138 139 memset(&scanreq, 0, sizeof(scanreq)); 140 141 /* save current roaming mode */ 142 result = hfa384x_drvr_getconfig16(hw, 143 HFA384x_RID_CNFROAMINGMODE, 144 &roamingmode); 145 if (result) { 146 printk(KERN_ERR "getconfig(ROAMMODE) failed. result=%d\n", 147 result); 148 msg->resultcode.data = 149 P80211ENUM_resultcode_implementation_failure; 150 goto exit; 151 } 152 153 /* drop into mode 3 for the scan */ 154 result = hfa384x_drvr_setconfig16(hw, 155 HFA384x_RID_CNFROAMINGMODE, 156 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM); 157 if (result) { 158 printk(KERN_ERR "setconfig(ROAMINGMODE) failed. result=%d\n", 159 result); 160 msg->resultcode.data = 161 P80211ENUM_resultcode_implementation_failure; 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)) { 170 if (msg->scantype.data != P80211ENUM_scantype_active) 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 = 209 P80211ENUM_resultcode_implementation_failure; 210 goto exit; 211 } 212 if (word == HFA384x_PORTSTATUS_DISABLED) { 213 u16 wordbuf[17]; 214 215 result = hfa384x_drvr_setconfig16(hw, 216 HFA384x_RID_CNFROAMINGMODE, 217 HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM); 218 if (result) { 219 printk(KERN_ERR 220 "setconfig(ROAMINGMODE) failed. result=%d\n", 221 result); 222 msg->resultcode.data = 223 P80211ENUM_resultcode_implementation_failure; 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); 231 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID, 232 wordbuf, 233 HFA384x_RID_CNFOWNSSID_LEN); 234 if (result) { 235 printk(KERN_ERR "Failed to set OwnSSID.\n"); 236 msg->resultcode.data = 237 P80211ENUM_resultcode_implementation_failure; 238 goto exit; 239 } 240 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, 241 wordbuf, 242 HFA384x_RID_CNFDESIREDSSID_LEN); 243 if (result) { 244 printk(KERN_ERR "Failed to set DesiredSSID.\n"); 245 msg->resultcode.data = 246 P80211ENUM_resultcode_implementation_failure; 247 goto exit; 248 } 249 /* bsstype */ 250 result = hfa384x_drvr_setconfig16(hw, 251 HFA384x_RID_CNFPORTTYPE, 252 HFA384x_PORTTYPE_IBSS); 253 if (result) { 254 printk(KERN_ERR "Failed to set CNFPORTTYPE.\n"); 255 msg->resultcode.data = 256 P80211ENUM_resultcode_implementation_failure; 257 goto exit; 258 } 259 /* ibss options */ 260 result = hfa384x_drvr_setconfig16(hw, 261 HFA384x_RID_CREATEIBSS, 262 HFA384x_CREATEIBSS_JOINCREATEIBSS); 263 if (result) { 264 printk(KERN_ERR "Failed to set CREATEIBSS.\n"); 265 msg->resultcode.data = 266 P80211ENUM_resultcode_implementation_failure; 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 = 274 P80211ENUM_resultcode_implementation_failure; 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, 289 sizeof(hfa384x_HostScanRequest_data_t)); 290 if (result) { 291 printk(KERN_ERR "setconfig(SCANREQUEST) failed. result=%d\n", 292 result); 293 msg->resultcode.data = 294 P80211ENUM_resultcode_implementation_failure; 295 goto exit; 296 } 297 298 /* sleep until info frame arrives */ 299 wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout); 300 301 msg->numbss.status = P80211ENUM_msgitem_status_data_ok; 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 = 316 P80211ENUM_resultcode_implementation_failure; 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 = 328 P80211ENUM_resultcode_implementation_failure; 329 goto exit; 330 } 331 332 result = 0; 333 msg->resultcode.data = P80211ENUM_resultcode_success; 334 335exit: 336 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 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----------------------------------------------------------------*/ 361int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) 362{ 363 int result = 0; 364 struct p80211msg_dot11req_scan_results *req; 365 hfa384x_t *hw = wlandev->priv; 366 hfa384x_HScanResultSub_t *item = NULL; 367 368 int count; 369 370 req = (struct p80211msg_dot11req_scan_results *) msgp; 371 372 req->resultcode.status = P80211ENUM_msgitem_status_data_ok; 373 374 if (!hw->scanresults) { 375 printk(KERN_ERR 376 "dot11req_scan_results can only be used after a successful dot11req_scan.\n"); 377 result = 2; 378 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters; 379 goto exit; 380 } 381 382 count = (hw->scanresults->framelen - 3) / 32; 383 if (count > 32) 384 count = 32; 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; 390 req->resultcode.data = P80211ENUM_resultcode_invalid_parameters; 391 goto exit; 392 } 393 394 item = &(hw->scanresults->info.hscanresult.result[req->bssindex.data]); 395 /* signal and noise */ 396 req->signal.status = P80211ENUM_msgitem_status_data_ok; 397 req->noise.status = P80211ENUM_msgitem_status_data_ok; 398 req->signal.data = le16_to_cpu(item->sl); 399 req->noise.data = le16_to_cpu(item->anl); 400 401 /* BSSID */ 402 req->bssid.status = P80211ENUM_msgitem_status_data_ok; 403 req->bssid.data.len = WLAN_BSSID_LEN; 404 memcpy(req->bssid.data.data, item->bssid, WLAN_BSSID_LEN); 405 406 /* SSID */ 407 req->ssid.status = P80211ENUM_msgitem_status_data_ok; 408 req->ssid.data.len = le16_to_cpu(item->ssid.len); 409 memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); 410 411 /* supported rates */ 412 for (count = 0; count < 10; count++) 413 if (item->supprates[count] == 0) 414 break; 415 416#define REQBASICRATE(N) \ 417 if ((count >= N) && DOT11_RATE5_ISBASIC_GET(item->supprates[(N)-1])) { \ 418 req->basicrate ## N .data = item->supprates[(N)-1]; \ 419 req->basicrate ## N .status = P80211ENUM_msgitem_status_data_ok; \ 420 } 421 422 REQBASICRATE(1); 423 REQBASICRATE(2); 424 REQBASICRATE(3); 425 REQBASICRATE(4); 426 REQBASICRATE(5); 427 REQBASICRATE(6); 428 REQBASICRATE(7); 429 REQBASICRATE(8); 430 431#define REQSUPPRATE(N) \ 432 if (count >= N) { \ 433 req->supprate ## N .data = item->supprates[(N)-1]; \ 434 req->supprate ## N .status = P80211ENUM_msgitem_status_data_ok; \ 435 } 436 437 REQSUPPRATE(1); 438 REQSUPPRATE(2); 439 REQSUPPRATE(3); 440 REQSUPPRATE(4); 441 REQSUPPRATE(5); 442 REQSUPPRATE(6); 443 REQSUPPRATE(7); 444 REQSUPPRATE(8); 445 446 /* beacon period */ 447 req->beaconperiod.status = P80211ENUM_msgitem_status_data_ok; 448 req->beaconperiod.data = le16_to_cpu(item->bcnint); 449 450 /* timestamps */ 451 req->timestamp.status = P80211ENUM_msgitem_status_data_ok; 452 req->timestamp.data = jiffies; 453 req->localtime.status = P80211ENUM_msgitem_status_data_ok; 454 req->localtime.data = jiffies; 455 456 /* atim window */ 457 req->ibssatimwindow.status = P80211ENUM_msgitem_status_data_ok; 458 req->ibssatimwindow.data = le16_to_cpu(item->atim); 459 460 /* Channel */ 461 req->dschannel.status = P80211ENUM_msgitem_status_data_ok; 462 req->dschannel.data = le16_to_cpu(item->chid); 463 464 /* capinfo bits */ 465 count = le16_to_cpu(item->capinfo); 466 req->capinfo.status = P80211ENUM_msgitem_status_data_ok; 467 req->capinfo.data = count; 468 469 /* privacy flag */ 470 req->privacy.status = P80211ENUM_msgitem_status_data_ok; 471 req->privacy.data = WLAN_GET_MGMT_CAP_INFO_PRIVACY(count); 472 473 /* cfpollable */ 474 req->cfpollable.status = P80211ENUM_msgitem_status_data_ok; 475 req->cfpollable.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLABLE(count); 476 477 /* cfpollreq */ 478 req->cfpollreq.status = P80211ENUM_msgitem_status_data_ok; 479 req->cfpollreq.data = WLAN_GET_MGMT_CAP_INFO_CFPOLLREQ(count); 480 481 /* bsstype */ 482 req->bsstype.status = P80211ENUM_msgitem_status_data_ok; 483 req->bsstype.data = (WLAN_GET_MGMT_CAP_INFO_ESS(count)) ? 484 P80211ENUM_bsstype_infrastructure : P80211ENUM_bsstype_independent; 485 486 result = 0; 487 req->resultcode.data = P80211ENUM_resultcode_success; 488 489exit: 490 return result; 491} 492 493/*---------------------------------------------------------------- 494* prism2mgmt_start 495* 496* Start a BSS. Any station can do this for IBSS, only AP for ESS. 497* 498* Arguments: 499* wlandev wlan device structure 500* msgp ptr to msg buffer 501* 502* Returns: 503* 0 success and done 504* <0 success, but we're waiting for something to finish. 505* >0 an error occurred while handling the message. 506* Side effects: 507* 508* Call context: 509* process thread (usually) 510* interrupt 511----------------------------------------------------------------*/ 512int prism2mgmt_start(wlandevice_t *wlandev, void *msgp) 513{ 514 int result = 0; 515 hfa384x_t *hw = wlandev->priv; 516 struct p80211msg_dot11req_start *msg = msgp; 517 518 p80211pstrd_t *pstr; 519 u8 bytebuf[80]; 520 hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf; 521 u16 word; 522 523 wlandev->macmode = WLAN_MACMODE_NONE; 524 525 /* Set the SSID */ 526 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data)); 527 528 /*** ADHOC IBSS ***/ 529 /* see if current f/w is less than 8c3 */ 530 if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major, 531 hw->ident_sta_fw.minor, 532 hw->ident_sta_fw.variant) < 533 HFA384x_FIRMWARE_VERSION(0, 8, 3)) { 534 /* Ad-Hoc not quite supported on Prism2 */ 535 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 536 msg->resultcode.data = P80211ENUM_resultcode_not_supported; 537 goto done; 538 } 539 540 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 541 542 /*** STATION ***/ 543 /* Set the REQUIRED config items */ 544 /* SSID */ 545 pstr = (p80211pstrd_t *) &(msg->ssid.data); 546 prism2mgmt_pstr2bytestr(p2bytestr, pstr); 547 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID, 548 bytebuf, HFA384x_RID_CNFOWNSSID_LEN); 549 if (result) { 550 printk(KERN_ERR "Failed to set CnfOwnSSID\n"); 551 goto failed; 552 } 553 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, 554 bytebuf, 555 HFA384x_RID_CNFDESIREDSSID_LEN); 556 if (result) { 557 printk(KERN_ERR "Failed to set CnfDesiredSSID\n"); 558 goto failed; 559 } 560 561 /* bsstype - we use the default in the ap firmware */ 562 /* IBSS port */ 563 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, 0); 564 565 /* beacon period */ 566 word = msg->beaconperiod.data; 567 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAPBCNint, word); 568 if (result) { 569 printk(KERN_ERR "Failed to set beacon period=%d.\n", word); 570 goto failed; 571 } 572 573 /* dschannel */ 574 word = msg->dschannel.data; 575 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFOWNCHANNEL, word); 576 if (result) { 577 printk(KERN_ERR "Failed to set channel=%d.\n", word); 578 goto failed; 579 } 580 /* Basic rates */ 581 word = p80211rate_to_p2bit(msg->basicrate1.data); 582 if (msg->basicrate2.status == P80211ENUM_msgitem_status_data_ok) 583 word |= p80211rate_to_p2bit(msg->basicrate2.data); 584 585 if (msg->basicrate3.status == P80211ENUM_msgitem_status_data_ok) 586 word |= p80211rate_to_p2bit(msg->basicrate3.data); 587 588 if (msg->basicrate4.status == P80211ENUM_msgitem_status_data_ok) 589 word |= p80211rate_to_p2bit(msg->basicrate4.data); 590 591 if (msg->basicrate5.status == P80211ENUM_msgitem_status_data_ok) 592 word |= p80211rate_to_p2bit(msg->basicrate5.data); 593 594 if (msg->basicrate6.status == P80211ENUM_msgitem_status_data_ok) 595 word |= p80211rate_to_p2bit(msg->basicrate6.data); 596 597 if (msg->basicrate7.status == P80211ENUM_msgitem_status_data_ok) 598 word |= p80211rate_to_p2bit(msg->basicrate7.data); 599 600 if (msg->basicrate8.status == P80211ENUM_msgitem_status_data_ok) 601 word |= p80211rate_to_p2bit(msg->basicrate8.data); 602 603 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFBASICRATES, word); 604 if (result) { 605 printk(KERN_ERR "Failed to set basicrates=%d.\n", word); 606 goto failed; 607 } 608 609 /* Operational rates (supprates and txratecontrol) */ 610 word = p80211rate_to_p2bit(msg->operationalrate1.data); 611 if (msg->operationalrate2.status == P80211ENUM_msgitem_status_data_ok) 612 word |= p80211rate_to_p2bit(msg->operationalrate2.data); 613 614 if (msg->operationalrate3.status == P80211ENUM_msgitem_status_data_ok) 615 word |= p80211rate_to_p2bit(msg->operationalrate3.data); 616 617 if (msg->operationalrate4.status == P80211ENUM_msgitem_status_data_ok) 618 word |= p80211rate_to_p2bit(msg->operationalrate4.data); 619 620 if (msg->operationalrate5.status == P80211ENUM_msgitem_status_data_ok) 621 word |= p80211rate_to_p2bit(msg->operationalrate5.data); 622 623 if (msg->operationalrate6.status == P80211ENUM_msgitem_status_data_ok) 624 word |= p80211rate_to_p2bit(msg->operationalrate6.data); 625 626 if (msg->operationalrate7.status == P80211ENUM_msgitem_status_data_ok) 627 word |= p80211rate_to_p2bit(msg->operationalrate7.data); 628 629 if (msg->operationalrate8.status == P80211ENUM_msgitem_status_data_ok) 630 word |= p80211rate_to_p2bit(msg->operationalrate8.data); 631 632 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFSUPPRATES, word); 633 if (result) { 634 printk(KERN_ERR "Failed to set supprates=%d.\n", word); 635 goto failed; 636 } 637 638 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, word); 639 if (result) { 640 printk(KERN_ERR "Failed to set txrates=%d.\n", word); 641 goto failed; 642 } 643 644 /* Set the macmode so the frame setup code knows what to do */ 645 if (msg->bsstype.data == P80211ENUM_bsstype_independent) { 646 wlandev->macmode = WLAN_MACMODE_IBSS_STA; 647 /* lets extend the data length a bit */ 648 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, 2304); 649 } 650 651 /* Enable the Port */ 652 result = hfa384x_drvr_enable(hw, 0); 653 if (result) { 654 printk(KERN_ERR "Enable macport failed, result=%d.\n", result); 655 goto failed; 656 } 657 658 msg->resultcode.data = P80211ENUM_resultcode_success; 659 660 goto done; 661failed: 662 pr_debug("Failed to set a config option, result=%d\n", result); 663 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; 664 665done: 666 result = 0; 667 668 return result; 669} 670 671/*---------------------------------------------------------------- 672* prism2mgmt_readpda 673* 674* Collect the PDA data and put it in the message. 675* 676* Arguments: 677* wlandev wlan device structure 678* msgp ptr to msg buffer 679* 680* Returns: 681* 0 success and done 682* <0 success, but we're waiting for something to finish. 683* >0 an error occurred while handling the message. 684* Side effects: 685* 686* Call context: 687* process thread (usually) 688----------------------------------------------------------------*/ 689int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp) 690{ 691 hfa384x_t *hw = wlandev->priv; 692 struct p80211msg_p2req_readpda *msg = msgp; 693 int result; 694 695 /* We only support collecting the PDA when in the FWLOAD 696 * state. 697 */ 698 if (wlandev->msdstate != WLAN_MSD_FWLOAD) { 699 printk(KERN_ERR 700 "PDA may only be read " "in the fwload state.\n"); 701 msg->resultcode.data = 702 P80211ENUM_resultcode_implementation_failure; 703 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 704 } else { 705 /* Call drvr_readpda(), it handles the auxport enable 706 * and validating the returned PDA. 707 */ 708 result = hfa384x_drvr_readpda(hw, 709 msg->pda.data, 710 HFA384x_PDA_LEN_MAX); 711 if (result) { 712 printk(KERN_ERR 713 "hfa384x_drvr_readpda() failed, " 714 "result=%d\n", result); 715 716 msg->resultcode.data = 717 P80211ENUM_resultcode_implementation_failure; 718 msg->resultcode.status = 719 P80211ENUM_msgitem_status_data_ok; 720 return 0; 721 } 722 msg->pda.status = P80211ENUM_msgitem_status_data_ok; 723 msg->resultcode.data = P80211ENUM_resultcode_success; 724 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 725 } 726 727 return 0; 728} 729 730/*---------------------------------------------------------------- 731* prism2mgmt_ramdl_state 732* 733* Establishes the beginning/end of a card RAM download session. 734* 735* It is expected that the ramdl_write() function will be called 736* one or more times between the 'enable' and 'disable' calls to 737* this function. 738* 739* Note: This function should not be called when a mac comm port 740* is active. 741* 742* Arguments: 743* wlandev wlan device structure 744* msgp ptr to msg buffer 745* 746* Returns: 747* 0 success and done 748* <0 success, but we're waiting for something to finish. 749* >0 an error occurred while handling the message. 750* Side effects: 751* 752* Call context: 753* process thread (usually) 754----------------------------------------------------------------*/ 755int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp) 756{ 757 hfa384x_t *hw = wlandev->priv; 758 struct p80211msg_p2req_ramdl_state *msg = msgp; 759 760 if (wlandev->msdstate != WLAN_MSD_FWLOAD) { 761 printk(KERN_ERR 762 "ramdl_state(): may only be called " 763 "in the fwload state.\n"); 764 msg->resultcode.data = 765 P80211ENUM_resultcode_implementation_failure; 766 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 767 return 0; 768 } 769 770 /* 771 ** Note: Interrupts are locked out if this is an AP and are NOT 772 ** locked out if this is a station. 773 */ 774 775 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 776 if (msg->enable.data == P80211ENUM_truth_true) { 777 if (hfa384x_drvr_ramdl_enable(hw, msg->exeaddr.data)) { 778 msg->resultcode.data = 779 P80211ENUM_resultcode_implementation_failure; 780 } else { 781 msg->resultcode.data = P80211ENUM_resultcode_success; 782 } 783 } else { 784 hfa384x_drvr_ramdl_disable(hw); 785 msg->resultcode.data = P80211ENUM_resultcode_success; 786 } 787 788 return 0; 789} 790 791/*---------------------------------------------------------------- 792* prism2mgmt_ramdl_write 793* 794* Writes a buffer to the card RAM using the download state. This 795* is for writing code to card RAM. To just read or write raw data 796* use the aux functions. 797* 798* Arguments: 799* wlandev wlan device structure 800* msgp ptr to msg buffer 801* 802* Returns: 803* 0 success and done 804* <0 success, but we're waiting for something to finish. 805* >0 an error occurred while handling the message. 806* Side effects: 807* 808* Call context: 809* process thread (usually) 810----------------------------------------------------------------*/ 811int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp) 812{ 813 hfa384x_t *hw = wlandev->priv; 814 struct p80211msg_p2req_ramdl_write *msg = msgp; 815 u32 addr; 816 u32 len; 817 u8 *buf; 818 819 if (wlandev->msdstate != WLAN_MSD_FWLOAD) { 820 printk(KERN_ERR 821 "ramdl_write(): may only be called " 822 "in the fwload state.\n"); 823 msg->resultcode.data = 824 P80211ENUM_resultcode_implementation_failure; 825 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 826 return 0; 827 } 828 829 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 830 /* first validate the length */ 831 if (msg->len.data > sizeof(msg->data.data)) { 832 msg->resultcode.status = 833 P80211ENUM_resultcode_invalid_parameters; 834 return 0; 835 } 836 /* call the hfa384x function to do the write */ 837 addr = msg->addr.data; 838 len = msg->len.data; 839 buf = msg->data.data; 840 if (hfa384x_drvr_ramdl_write(hw, addr, buf, len)) 841 msg->resultcode.data = P80211ENUM_resultcode_refused; 842 843 msg->resultcode.data = P80211ENUM_resultcode_success; 844 845 return 0; 846} 847 848/*---------------------------------------------------------------- 849* prism2mgmt_flashdl_state 850* 851* Establishes the beginning/end of a card Flash download session. 852* 853* It is expected that the flashdl_write() function will be called 854* one or more times between the 'enable' and 'disable' calls to 855* this function. 856* 857* Note: This function should not be called when a mac comm port 858* is active. 859* 860* Arguments: 861* wlandev wlan device structure 862* msgp ptr to msg buffer 863* 864* Returns: 865* 0 success and done 866* <0 success, but we're waiting for something to finish. 867* >0 an error occurred while handling the message. 868* Side effects: 869* 870* Call context: 871* process thread (usually) 872----------------------------------------------------------------*/ 873int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp) 874{ 875 int result = 0; 876 hfa384x_t *hw = wlandev->priv; 877 struct p80211msg_p2req_flashdl_state *msg = msgp; 878 879 if (wlandev->msdstate != WLAN_MSD_FWLOAD) { 880 printk(KERN_ERR 881 "flashdl_state(): may only be called " 882 "in the fwload state.\n"); 883 msg->resultcode.data = 884 P80211ENUM_resultcode_implementation_failure; 885 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 886 return 0; 887 } 888 889 /* 890 ** Note: Interrupts are locked out if this is an AP and are NOT 891 ** locked out if this is a station. 892 */ 893 894 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 895 if (msg->enable.data == P80211ENUM_truth_true) { 896 if (hfa384x_drvr_flashdl_enable(hw)) { 897 msg->resultcode.data = 898 P80211ENUM_resultcode_implementation_failure; 899 } else { 900 msg->resultcode.data = P80211ENUM_resultcode_success; 901 } 902 } else { 903 hfa384x_drvr_flashdl_disable(hw); 904 msg->resultcode.data = P80211ENUM_resultcode_success; 905 /* NOTE: At this point, the MAC is in the post-reset 906 * state and the driver is in the fwload state. 907 * We need to get the MAC back into the fwload 908 * state. To do this, we set the nsdstate to HWPRESENT 909 * and then call the ifstate function to redo everything 910 * that got us into the fwload state. 911 */ 912 wlandev->msdstate = WLAN_MSD_HWPRESENT; 913 result = prism2sta_ifstate(wlandev, P80211ENUM_ifstate_fwload); 914 if (result != P80211ENUM_resultcode_success) { 915 printk(KERN_ERR "prism2sta_ifstate(fwload) failed," 916 "P80211ENUM_resultcode=%d\n", result); 917 msg->resultcode.data = 918 P80211ENUM_resultcode_implementation_failure; 919 result = -1; 920 } 921 } 922 923 return 0; 924} 925 926/*---------------------------------------------------------------- 927* prism2mgmt_flashdl_write 928* 929* 930* 931* Arguments: 932* wlandev wlan device structure 933* msgp ptr to msg buffer 934* 935* Returns: 936* 0 success and done 937* <0 success, but we're waiting for something to finish. 938* >0 an error occurred while handling the message. 939* Side effects: 940* 941* Call context: 942* process thread (usually) 943----------------------------------------------------------------*/ 944int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp) 945{ 946 hfa384x_t *hw = wlandev->priv; 947 struct p80211msg_p2req_flashdl_write *msg = msgp; 948 u32 addr; 949 u32 len; 950 u8 *buf; 951 952 if (wlandev->msdstate != WLAN_MSD_FWLOAD) { 953 printk(KERN_ERR 954 "flashdl_write(): may only be called " 955 "in the fwload state.\n"); 956 msg->resultcode.data = 957 P80211ENUM_resultcode_implementation_failure; 958 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 959 return 0; 960 } 961 962 /* 963 ** Note: Interrupts are locked out if this is an AP and are NOT 964 ** locked out if this is a station. 965 */ 966 967 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 968 /* first validate the length */ 969 if (msg->len.data > sizeof(msg->data.data)) { 970 msg->resultcode.status = 971 P80211ENUM_resultcode_invalid_parameters; 972 return 0; 973 } 974 /* call the hfa384x function to do the write */ 975 addr = msg->addr.data; 976 len = msg->len.data; 977 buf = msg->data.data; 978 if (hfa384x_drvr_flashdl_write(hw, addr, buf, len)) 979 msg->resultcode.data = P80211ENUM_resultcode_refused; 980 981 msg->resultcode.data = P80211ENUM_resultcode_success; 982 983 return 0; 984} 985 986/*---------------------------------------------------------------- 987* prism2mgmt_autojoin 988* 989* Associate with an ESS. 990* 991* Arguments: 992* wlandev wlan device structure 993* msgp ptr to msg buffer 994* 995* Returns: 996* 0 success and done 997* <0 success, but we're waiting for something to finish. 998* >0 an error occurred while handling the message. 999* Side effects: 1000* 1001* Call context: 1002* process thread (usually) 1003* interrupt 1004----------------------------------------------------------------*/ 1005int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp) 1006{ 1007 hfa384x_t *hw = wlandev->priv; 1008 int result = 0; 1009 u16 reg; 1010 u16 port_type; 1011 struct p80211msg_lnxreq_autojoin *msg = msgp; 1012 p80211pstrd_t *pstr; 1013 u8 bytebuf[256]; 1014 hfa384x_bytestr_t *p2bytestr = (hfa384x_bytestr_t *) bytebuf; 1015 1016 wlandev->macmode = WLAN_MACMODE_NONE; 1017 1018 /* Set the SSID */ 1019 memcpy(&wlandev->ssid, &msg->ssid.data, sizeof(msg->ssid.data)); 1020 1021 /* Disable the Port */ 1022 hfa384x_drvr_disable(hw, 0); 1023 1024 /*** STATION ***/ 1025 /* Set the TxRates */ 1026 hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, 0x000f); 1027 1028 /* Set the auth type */ 1029 if (msg->authtype.data == P80211ENUM_authalg_sharedkey) 1030 reg = HFA384x_CNFAUTHENTICATION_SHAREDKEY; 1031 else 1032 reg = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; 1033 1034 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, reg); 1035 1036 /* Set the ssid */ 1037 memset(bytebuf, 0, 256); 1038 pstr = (p80211pstrd_t *) &(msg->ssid.data); 1039 prism2mgmt_pstr2bytestr(p2bytestr, pstr); 1040 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, 1041 bytebuf, 1042 HFA384x_RID_CNFDESIREDSSID_LEN); 1043 port_type = HFA384x_PORTTYPE_BSS; 1044 /* Set the PortType */ 1045 hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, port_type); 1046 1047 /* Enable the Port */ 1048 hfa384x_drvr_enable(hw, 0); 1049 1050 /* Set the resultcode */ 1051 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 1052 msg->resultcode.data = P80211ENUM_resultcode_success; 1053 1054 return result; 1055} 1056 1057/*---------------------------------------------------------------- 1058* prism2mgmt_wlansniff 1059* 1060* Start or stop sniffing. 1061* 1062* Arguments: 1063* wlandev wlan device structure 1064* msgp ptr to msg buffer 1065* 1066* Returns: 1067* 0 success and done 1068* <0 success, but we're waiting for something to finish. 1069* >0 an error occurred while handling the message. 1070* Side effects: 1071* 1072* Call context: 1073* process thread (usually) 1074* interrupt 1075----------------------------------------------------------------*/ 1076int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp) 1077{ 1078 int result = 0; 1079 struct p80211msg_lnxreq_wlansniff *msg = msgp; 1080 1081 hfa384x_t *hw = wlandev->priv; 1082 u16 word; 1083 1084 msg->resultcode.status = P80211ENUM_msgitem_status_data_ok; 1085 switch (msg->enable.data) { 1086 case P80211ENUM_truth_false: 1087 /* Confirm that we're in monitor mode */ 1088 if (wlandev->netdev->type == ARPHRD_ETHER) { 1089 msg->resultcode.data = 1090 P80211ENUM_resultcode_invalid_parameters; 1091 result = 0; 1092 goto exit; 1093 } 1094 /* Disable monitor mode */ 1095 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_DISABLE); 1096 if (result) { 1097 pr_debug("failed to disable monitor mode, result=%d\n", 1098 result); 1099 goto failed; 1100 } 1101 /* Disable port 0 */ 1102 result = hfa384x_drvr_disable(hw, 0); 1103 if (result) { 1104 pr_debug 1105 ("failed to disable port 0 after sniffing, result=%d\n", 1106 result); 1107 goto failed; 1108 } 1109 /* Clear the driver state */ 1110 wlandev->netdev->type = ARPHRD_ETHER; 1111 1112 /* Restore the wepflags */ 1113 result = hfa384x_drvr_setconfig16(hw, 1114 HFA384x_RID_CNFWEPFLAGS, 1115 hw->presniff_wepflags); 1116 if (result) { 1117 pr_debug 1118 ("failed to restore wepflags=0x%04x, result=%d\n", 1119 hw->presniff_wepflags, result); 1120 goto failed; 1121 } 1122 1123 /* Set the port to its prior type and enable (if necessary) */ 1124 if (hw->presniff_port_type != 0) { 1125 word = hw->presniff_port_type; 1126 result = hfa384x_drvr_setconfig16(hw, 1127 HFA384x_RID_CNFPORTTYPE, 1128 word); 1129 if (result) { 1130 pr_debug 1131 ("failed to restore porttype, result=%d\n", 1132 result); 1133 goto failed; 1134 } 1135 1136 /* Enable the port */ 1137 result = hfa384x_drvr_enable(hw, 0); 1138 if (result) { 1139 pr_debug 1140 ("failed to enable port to presniff setting, result=%d\n", 1141 result); 1142 goto failed; 1143 } 1144 } else { 1145 result = hfa384x_drvr_disable(hw, 0); 1146 1147 } 1148 1149 printk(KERN_INFO "monitor mode disabled\n"); 1150 msg->resultcode.data = P80211ENUM_resultcode_success; 1151 result = 0; 1152 goto exit; 1153 break; 1154 case P80211ENUM_truth_true: 1155 /* Disable the port (if enabled), only check Port 0 */ 1156 if (hw->port_enabled[0]) { 1157 if (wlandev->netdev->type == ARPHRD_ETHER) { 1158 /* Save macport 0 state */ 1159 result = hfa384x_drvr_getconfig16(hw, 1160 HFA384x_RID_CNFPORTTYPE, 1161 &(hw->presniff_port_type)); 1162 if (result) { 1163 pr_debug 1164 ("failed to read porttype, result=%d\n", 1165 result); 1166 goto failed; 1167 } 1168 /* Save the wepflags state */ 1169 result = hfa384x_drvr_getconfig16(hw, 1170 HFA384x_RID_CNFWEPFLAGS, 1171 &(hw->presniff_wepflags)); 1172 if (result) { 1173 pr_debug 1174 ("failed to read wepflags, result=%d\n", 1175 result); 1176 goto failed; 1177 } 1178 hfa384x_drvr_stop(hw); 1179 result = hfa384x_drvr_start(hw); 1180 if (result) { 1181 pr_debug 1182 ("failed to restart the card for sniffing, result=%d\n", 1183 result); 1184 goto failed; 1185 } 1186 } else { 1187 /* Disable the port */ 1188 result = hfa384x_drvr_disable(hw, 0); 1189 if (result) { 1190 pr_debug 1191 ("failed to enable port for sniffing, result=%d\n", 1192 result); 1193 goto failed; 1194 } 1195 } 1196 } else { 1197 hw->presniff_port_type = 0; 1198 } 1199 1200 /* Set the channel we wish to sniff */ 1201 word = msg->channel.data; 1202 result = hfa384x_drvr_setconfig16(hw, 1203 HFA384x_RID_CNFOWNCHANNEL, 1204 word); 1205 hw->sniff_channel = word; 1206 1207 if (result) { 1208 pr_debug("failed to set channel %d, result=%d\n", 1209 word, result); 1210 goto failed; 1211 } 1212 1213 /* Now if we're already sniffing, we can skip the rest */ 1214 if (wlandev->netdev->type != ARPHRD_ETHER) { 1215 /* Set the port type to pIbss */ 1216 word = HFA384x_PORTTYPE_PSUEDOIBSS; 1217 result = hfa384x_drvr_setconfig16(hw, 1218 HFA384x_RID_CNFPORTTYPE, 1219 word); 1220 if (result) { 1221 pr_debug 1222 ("failed to set porttype %d, result=%d\n", 1223 word, result); 1224 goto failed; 1225 } 1226 if ((msg->keepwepflags.status == 1227 P80211ENUM_msgitem_status_data_ok) 1228 && (msg->keepwepflags.data != 1229 P80211ENUM_truth_true)) { 1230 /* Set the wepflags for no decryption */ 1231 word = HFA384x_WEPFLAGS_DISABLE_TXCRYPT | 1232 HFA384x_WEPFLAGS_DISABLE_RXCRYPT; 1233 result = 1234 hfa384x_drvr_setconfig16(hw, 1235 HFA384x_RID_CNFWEPFLAGS, 1236 word); 1237 } 1238 1239 if (result) { 1240 pr_debug 1241 ("failed to set wepflags=0x%04x, result=%d\n", 1242 word, result); 1243 goto failed; 1244 } 1245 } 1246 1247 /* Do we want to strip the FCS in monitor mode? */ 1248 if ((msg->stripfcs.status == P80211ENUM_msgitem_status_data_ok) 1249 && (msg->stripfcs.data == P80211ENUM_truth_true)) { 1250 hw->sniff_fcs = 0; 1251 } else { 1252 hw->sniff_fcs = 1; 1253 } 1254 1255 /* Do we want to truncate the packets? */ 1256 if (msg->packet_trunc.status == 1257 P80211ENUM_msgitem_status_data_ok) { 1258 hw->sniff_truncate = msg->packet_trunc.data; 1259 } else { 1260 hw->sniff_truncate = 0; 1261 } 1262 1263 /* Enable the port */ 1264 result = hfa384x_drvr_enable(hw, 0); 1265 if (result) { 1266 pr_debug 1267 ("failed to enable port for sniffing, result=%d\n", 1268 result); 1269 goto failed; 1270 } 1271 /* Enable monitor mode */ 1272 result = hfa384x_cmd_monitor(hw, HFA384x_MONITOR_ENABLE); 1273 if (result) { 1274 pr_debug("failed to enable monitor mode, result=%d\n", 1275 result); 1276 goto failed; 1277 } 1278 1279 if (wlandev->netdev->type == ARPHRD_ETHER) 1280 printk(KERN_INFO "monitor mode enabled\n"); 1281 1282 /* Set the driver state */ 1283 /* Do we want the prism2 header? */ 1284 if ((msg->prismheader.status == 1285 P80211ENUM_msgitem_status_data_ok) 1286 && (msg->prismheader.data == P80211ENUM_truth_true)) { 1287 hw->sniffhdr = 0; 1288 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM; 1289 } else 1290 if ((msg->wlanheader.status == 1291 P80211ENUM_msgitem_status_data_ok) 1292 && (msg->wlanheader.data == P80211ENUM_truth_true)) { 1293 hw->sniffhdr = 1; 1294 wlandev->netdev->type = ARPHRD_IEEE80211_PRISM; 1295 } else { 1296 wlandev->netdev->type = ARPHRD_IEEE80211; 1297 } 1298 1299 msg->resultcode.data = P80211ENUM_resultcode_success; 1300 result = 0; 1301 goto exit; 1302 break; 1303 default: 1304 msg->resultcode.data = P80211ENUM_resultcode_invalid_parameters; 1305 result = 0; 1306 goto exit; 1307 break; 1308 } 1309 1310failed: 1311 msg->resultcode.data = P80211ENUM_resultcode_refused; 1312 result = 0; 1313exit: 1314 return result; 1315} 1316