1 /* $NetBSD: if_malo_pcmcia.c,v 1.6 2014/04/21 22:40:00 pgoyette Exp $ */ 2 /* $OpenBSD: if_malo.c,v 1.65 2009/03/29 21:53:53 sthen Exp $ */ 3 4 /* 5 * Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/cdefs.h> 21 __KERNEL_RCSID(0, "$NetBSD: if_malo_pcmcia.c,v 1.6 2014/04/21 22:40:00 pgoyette Exp $"); 22 23 #ifdef _MODULE 24 #include <sys/module.h> 25 #endif 26 27 #include <sys/param.h> 28 #include <sys/bus.h> 29 #include <sys/condvar.h> 30 #include <sys/device.h> 31 #include <sys/intr.h> 32 #include <sys/kernel.h> 33 #include <sys/malloc.h> 34 #include <sys/mbuf.h> 35 #include <sys/mutex.h> 36 #include <sys/pmf.h> 37 #include <sys/proc.h> 38 #include <sys/socket.h> 39 #include <sys/sockio.h> 40 #include <sys/systm.h> 41 42 #include <net/bpf.h> 43 #include <net/if.h> 44 #include <net/if_dl.h> 45 #include <net/if_ether.h> 46 #include <net/if_media.h> 47 #include <net/if_llc.h> 48 49 #include <net80211/ieee80211_var.h> 50 #include <net80211/ieee80211_radiotap.h> 51 52 #include <dev/firmload.h> 53 54 #include <dev/pcmcia/pcmciareg.h> 55 #include <dev/pcmcia/pcmciavar.h> 56 #include <dev/pcmcia/pcmciadevs.h> 57 58 #include <dev/pcmcia/if_malo_pcmciavar.h> 59 #include <dev/pcmcia/if_malo_pcmciareg.h> 60 61 /* 62 * Driver for the Marvell 88W8385 chip (Compact Flash). 63 */ 64 65 #ifdef CMALO_DEBUG 66 int cmalo_d = 1; 67 #define DPRINTF(l, x...) do { if ((l) <= cmalo_d) printf(x); } while (0) 68 #else 69 #define DPRINTF(l, x...) do {} while (0) 70 #endif 71 72 static int malo_pcmcia_match(device_t, cfdata_t, void *); 73 static void malo_pcmcia_attach(device_t, device_t, void *); 74 static int malo_pcmcia_detach(device_t, int); 75 static int malo_pcmcia_activate(device_t, devact_t); 76 77 static int malo_pcmcia_validate_config(struct pcmcia_config_entry *); 78 79 static int malo_pcmcia_enable(struct malo_softc *); 80 static void malo_pcmcia_disable(struct malo_softc *); 81 82 static void cmalo_attach(void *); 83 static void cmalo_detach(void *); 84 static int cmalo_intr(void *); 85 86 static void cmalo_start(struct ifnet *); 87 static int cmalo_ioctl(struct ifnet *, u_long, void *); 88 static int cmalo_init(struct ifnet *); 89 static void cmalo_watchdog(struct ifnet *); 90 static int cmalo_media_change(struct ifnet *); 91 static int cmalo_newstate(struct ieee80211com *, enum ieee80211_state, 92 int); 93 94 static int firmware_load(const char *, const char *, uint8_t **, size_t *); 95 static int cmalo_fw_alloc(struct malo_softc *); 96 static void cmalo_fw_free(struct malo_softc *); 97 static int cmalo_fw_load_helper(struct malo_softc *); 98 static int cmalo_fw_load_main(struct malo_softc *); 99 100 static void cmalo_stop(struct malo_softc *); 101 static void cmalo_intr_mask(struct malo_softc *, int); 102 static void cmalo_rx(struct malo_softc *); 103 static int cmalo_tx(struct malo_softc *, struct mbuf *); 104 static void cmalo_tx_done(struct malo_softc *); 105 static void cmalo_event(struct malo_softc *); 106 static void cmalo_select_network(struct malo_softc *); 107 static void cmalo_reflect_network(struct malo_softc *); 108 static int cmalo_wep(struct malo_softc *); 109 static int cmalo_rate2bitmap(int); 110 111 static void cmalo_hexdump(void *, int); 112 static int cmalo_cmd_get_hwspec(struct malo_softc *); 113 static int cmalo_cmd_rsp_hwspec(struct malo_softc *); 114 static int cmalo_cmd_set_reset(struct malo_softc *); 115 static int cmalo_cmd_set_scan(struct malo_softc *); 116 static int cmalo_cmd_rsp_scan(struct malo_softc *); 117 static int cmalo_parse_elements(struct malo_softc *, uint8_t *, int, int); 118 static int cmalo_cmd_set_auth(struct malo_softc *); 119 static int cmalo_cmd_set_wep(struct malo_softc *, uint16_t, 120 struct ieee80211_key *); 121 static int cmalo_cmd_set_snmp(struct malo_softc *, uint16_t); 122 static int cmalo_cmd_set_radio(struct malo_softc *, uint16_t); 123 static int cmalo_cmd_set_channel(struct malo_softc *, uint16_t); 124 static int cmalo_cmd_set_txpower(struct malo_softc *, int16_t); 125 static int cmalo_cmd_set_antenna(struct malo_softc *, uint16_t); 126 static int cmalo_cmd_set_macctrl(struct malo_softc *); 127 static int cmalo_cmd_set_macaddr(struct malo_softc *, uint8_t *); 128 static int cmalo_cmd_set_assoc(struct malo_softc *); 129 static int cmalo_cmd_rsp_assoc(struct malo_softc *); 130 static int cmalo_cmd_set_rate(struct malo_softc *, int); 131 static int cmalo_cmd_request(struct malo_softc *, uint16_t, int); 132 static int cmalo_cmd_response(struct malo_softc *); 133 134 /* 135 * PCMCIA bus. 136 */ 137 struct malo_pcmcia_softc { 138 struct malo_softc sc_malo; 139 140 struct pcmcia_function *sc_pf; 141 struct pcmcia_io_handle sc_pcioh; 142 int sc_io_window; 143 void *sc_ih; 144 }; 145 146 CFATTACH_DECL_NEW(malo_pcmcia, sizeof(struct malo_pcmcia_softc), 147 malo_pcmcia_match, malo_pcmcia_attach, malo_pcmcia_detach, 148 malo_pcmcia_activate); 149 150 151 static int 152 malo_pcmcia_match(device_t parent, cfdata_t match, void *aux) 153 { 154 struct pcmcia_attach_args *pa = aux; 155 156 if (pa->manufacturer == PCMCIA_VENDOR_AMBICOM && 157 pa->product == PCMCIA_PRODUCT_AMBICOM_WL54CF) 158 return 1; 159 160 return 0; 161 } 162 163 static void 164 malo_pcmcia_attach(device_t parent, device_t self, void *aux) 165 { 166 struct malo_pcmcia_softc *psc = device_private(self); 167 struct malo_softc *sc = &psc->sc_malo; 168 struct pcmcia_attach_args *pa = aux; 169 struct pcmcia_config_entry *cfe; 170 int error; 171 172 sc->sc_dev = self; 173 psc->sc_pf = pa->pf; 174 175 error = pcmcia_function_configure(pa->pf, malo_pcmcia_validate_config); 176 if (error) { 177 aprint_error_dev(self, "configure failed, error=%d\n", error); 178 return; 179 } 180 181 malo_pcmcia_enable(sc); 182 183 cfe = pa->pf->cfe; 184 sc->sc_iot = cfe->iospace[0].handle.iot; 185 sc->sc_ioh = cfe->iospace[0].handle.ioh; 186 187 cmalo_attach(sc); 188 if (!(sc->sc_flags & MALO_DEVICE_ATTACHED)) 189 goto fail; 190 191 if (pmf_device_register(self, NULL, NULL)) 192 pmf_class_network_register(self, &sc->sc_if); 193 else 194 aprint_error_dev(self, "couldn't establish power handler\n"); 195 196 fail: 197 malo_pcmcia_disable(sc); 198 199 if (sc->sc_flags & MALO_DEVICE_ATTACHED) 200 return; 201 202 pcmcia_function_unconfigure(pa->pf); 203 return; 204 } 205 206 static int 207 malo_pcmcia_detach(device_t dev, int flags) 208 { 209 struct malo_pcmcia_softc *psc = device_private(dev); 210 struct malo_softc *sc = &psc->sc_malo; 211 212 cmalo_detach(sc); 213 malo_pcmcia_disable(sc); 214 pcmcia_function_unconfigure(psc->sc_pf); 215 216 return 0; 217 } 218 219 static int 220 malo_pcmcia_activate(device_t dev, devact_t act) 221 { 222 struct malo_pcmcia_softc *psc = device_private(dev); 223 struct malo_softc *sc = &psc->sc_malo; 224 struct ifnet *ifp = &sc->sc_if; 225 int s; 226 227 s = splnet(); 228 switch (act) { 229 case DVACT_DEACTIVATE: 230 if_deactivate(ifp); 231 break; 232 default: 233 return EOPNOTSUPP; 234 } 235 splx(s); 236 237 return 0; 238 } 239 240 241 int 242 malo_pcmcia_validate_config(struct pcmcia_config_entry *cfe) 243 { 244 245 if (cfe->iftype != PCMCIA_IFTYPE_IO || cfe->num_iospace != 1) 246 return EINVAL; 247 /* Some cards have a memory space, but we don't use it. */ 248 cfe->num_memspace = 0; 249 return 0; 250 } 251 252 253 static int 254 malo_pcmcia_enable(struct malo_softc *sc) 255 { 256 struct malo_pcmcia_softc *psc = (struct malo_pcmcia_softc *)sc; 257 258 /* establish interrupt */ 259 psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, cmalo_intr, sc); 260 if (psc->sc_ih == NULL) { 261 aprint_error(": can't establish interrupt\n"); 262 return -1; 263 } 264 265 if (pcmcia_function_enable(psc->sc_pf)) { 266 aprint_error(": can't enable function\n"); 267 pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih); 268 return -1; 269 } 270 sc->sc_flags |= MALO_DEVICE_ENABLED; 271 272 return 0; 273 } 274 275 static void 276 malo_pcmcia_disable(struct malo_softc *sc) 277 { 278 struct malo_pcmcia_softc *psc = (struct malo_pcmcia_softc *)sc; 279 280 pcmcia_function_disable(psc->sc_pf); 281 if (psc->sc_ih) 282 pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih); 283 psc->sc_ih = NULL; 284 sc->sc_flags &= ~MALO_DEVICE_ENABLED; 285 } 286 287 288 /* 289 * Driver. 290 */ 291 static void 292 cmalo_attach(void *arg) 293 { 294 struct malo_softc *sc = arg; 295 struct ieee80211com *ic = &sc->sc_ic; 296 struct ifnet *ifp = &sc->sc_if; 297 int i; 298 299 /* disable interrupts */ 300 cmalo_intr_mask(sc, 0); 301 302 /* load firmware */ 303 if (cmalo_fw_alloc(sc) != 0 || 304 cmalo_fw_load_helper(sc) != 0 || 305 cmalo_fw_load_main(sc) != 0) { 306 /* free firmware */ 307 cmalo_fw_free(sc); 308 return; 309 } 310 sc->sc_flags |= MALO_FW_LOADED; 311 312 /* allocate command buffer */ 313 sc->sc_cmd = malloc(MALO_CMD_BUFFER_SIZE, M_DEVBUF, M_NOWAIT); 314 315 /* allocate data buffer */ 316 sc->sc_data = malloc(MALO_DATA_BUFFER_SIZE, M_DEVBUF, M_NOWAIT); 317 318 /* enable interrupts */ 319 cmalo_intr_mask(sc, 1); 320 321 /* we are context save here for FW commands */ 322 sc->sc_cmd_ctxsave = 1; 323 324 mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_VM); 325 cv_init(&sc->sc_cv, "malo"); 326 327 /* get hardware specs */ 328 cmalo_cmd_get_hwspec(sc); 329 330 /* setup interface */ 331 ifp->if_softc = sc; 332 ifp->if_start = cmalo_start; 333 ifp->if_ioctl = cmalo_ioctl; 334 ifp->if_init = cmalo_init; 335 ifp->if_watchdog = cmalo_watchdog; 336 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; 337 strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 338 IFQ_SET_READY(&ifp->if_snd); 339 340 ic->ic_ifp = ifp; 341 ic->ic_phytype = IEEE80211_T_OFDM; 342 ic->ic_opmode = IEEE80211_M_STA; 343 ic->ic_state = IEEE80211_S_INIT; 344 ic->ic_caps = IEEE80211_C_MONITOR | IEEE80211_C_WEP; 345 346 ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b; 347 ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g; 348 349 for (i = 0; i <= 14; i++) { 350 ic->ic_channels[i].ic_freq = 351 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 352 ic->ic_channels[i].ic_flags = 353 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | 354 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; 355 } 356 357 /* attach interface */ 358 if_attach(ifp); 359 ieee80211_ifattach(ic); 360 361 sc->sc_newstate = ic->ic_newstate; 362 ic->ic_newstate = cmalo_newstate; 363 ieee80211_media_init(ic, cmalo_media_change, ieee80211_media_status); 364 365 /* second attach line */ 366 aprint_normal_dev(sc->sc_dev, "address %s\n", 367 ether_sprintf(ic->ic_myaddr)); 368 369 ieee80211_announce(ic); 370 371 /* device attached */ 372 sc->sc_flags |= MALO_DEVICE_ATTACHED; 373 } 374 375 static void 376 cmalo_detach(void *arg) 377 { 378 struct malo_softc *sc = arg; 379 struct ieee80211com *ic = &sc->sc_ic; 380 struct ifnet *ifp = &sc->sc_if; 381 382 if (!(sc->sc_flags & MALO_DEVICE_ATTACHED)) { 383 /* free firmware */ 384 cmalo_fw_free(sc); 385 386 /* device was not properly attached */ 387 return; 388 } 389 390 if (ifp->if_flags & IFF_RUNNING) 391 cmalo_stop(sc); 392 393 /* free command buffer */ 394 if (sc->sc_cmd != NULL) 395 free(sc->sc_cmd, M_DEVBUF); 396 397 /* free data buffer */ 398 if (sc->sc_data != NULL) 399 free(sc->sc_data, M_DEVBUF); 400 401 /* free firmware */ 402 cmalo_fw_free(sc); 403 404 /* detach inferface */ 405 ieee80211_ifdetach(ic); 406 if_detach(ifp); 407 408 mutex_destroy(&sc->sc_mtx); 409 cv_destroy(&sc->sc_cv); 410 } 411 412 static int 413 cmalo_intr(void *arg) 414 { 415 struct malo_softc *sc = arg; 416 uint16_t intr = 0; 417 418 /* read interrupt reason */ 419 intr = MALO_READ_2(sc, MALO_REG_HOST_INTR_CAUSE); 420 if (intr == 0) 421 /* interrupt not for us */ 422 return 0; 423 if (intr == 0xffff) 424 /* card has been detached */ 425 return 0; 426 427 /* disable interrupts */ 428 cmalo_intr_mask(sc, 0); 429 430 /* acknowledge interrupt */ 431 MALO_WRITE_2(sc, MALO_REG_HOST_INTR_CAUSE, 432 intr & MALO_VAL_HOST_INTR_MASK_ON); 433 434 /* enable interrupts */ 435 cmalo_intr_mask(sc, 1); 436 437 DPRINTF(2, "%s: interrupt handler called (intr = 0x%04x)\n", 438 device_xname(sc->sc_dev), intr); 439 440 if (intr & MALO_VAL_HOST_INTR_TX) 441 /* TX frame sent */ 442 cmalo_tx_done(sc); 443 if (intr & MALO_VAL_HOST_INTR_RX) 444 /* RX frame received */ 445 cmalo_rx(sc); 446 if (intr & MALO_VAL_HOST_INTR_CMD) { 447 /* command response */ 448 mutex_enter(&sc->sc_mtx); 449 cv_signal(&sc->sc_cv); 450 mutex_exit(&sc->sc_mtx); 451 if (!sc->sc_cmd_ctxsave) 452 cmalo_cmd_response(sc); 453 } 454 if (intr & MALO_VAL_HOST_INTR_EVENT) 455 /* event */ 456 cmalo_event(sc); 457 458 return 1; 459 } 460 461 462 /* 463 * Network functions 464 */ 465 static void 466 cmalo_start(struct ifnet *ifp) 467 { 468 struct malo_softc *sc = ifp->if_softc; 469 struct mbuf *m; 470 471 /* don't transmit packets if interface is busy or down */ 472 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 473 return; 474 475 IFQ_POLL(&ifp->if_snd, m); 476 if (m == NULL) 477 return; 478 479 IFQ_DEQUEUE(&ifp->if_snd, m); 480 481 if (ifp->if_bpf) 482 bpf_ops->bpf_mtap(ifp->if_bpf, m); 483 484 if (cmalo_tx(sc, m) != 0) 485 ifp->if_oerrors++; 486 } 487 488 static int 489 cmalo_ioctl(struct ifnet *ifp, u_long cmd, void *data) 490 { 491 struct malo_softc *sc = ifp->if_softc; 492 struct ieee80211com *ic = &sc->sc_ic; 493 int s, error = 0; 494 495 s = splnet(); 496 497 switch (cmd) { 498 case SIOCSIFFLAGS: 499 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 500 break; 501 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { 502 case IFF_RUNNING: 503 cmalo_stop(sc); 504 break; 505 506 case IFF_UP: 507 cmalo_init(ifp); 508 break; 509 510 default: 511 break; 512 } 513 error = 0; 514 break; 515 516 case SIOCADDMULTI: 517 case SIOCDELMULTI: 518 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) 519 /* setup multicast filter, etc */ 520 error = 0; 521 break; 522 523 default: 524 error = ieee80211_ioctl(ic, cmd, data); 525 break; 526 } 527 528 if (error == ENETRESET) { 529 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 530 (IFF_UP | IFF_RUNNING)) 531 cmalo_init(ifp); 532 error = 0; 533 } 534 535 splx(s); 536 537 return error; 538 } 539 540 static int 541 cmalo_init(struct ifnet *ifp) 542 { 543 struct malo_softc *sc = ifp->if_softc; 544 struct ieee80211com *ic = &sc->sc_ic; 545 546 if (!(sc->sc_flags & MALO_DEVICE_ENABLED)) 547 malo_pcmcia_enable(sc); 548 549 /* reload the firmware if necessary */ 550 if (!(sc->sc_flags & MALO_FW_LOADED)) { 551 /* disable interrupts */ 552 cmalo_intr_mask(sc, 0); 553 554 /* load firmware */ 555 if (cmalo_fw_load_helper(sc) != 0) 556 return EIO; 557 if (cmalo_fw_load_main(sc) != 0) 558 return EIO; 559 sc->sc_flags |= MALO_FW_LOADED; 560 561 /* enable interrupts */ 562 cmalo_intr_mask(sc, 1); 563 } 564 565 if (ifp->if_flags & IFF_RUNNING) 566 cmalo_stop(sc); 567 568 /* reset association state flag */ 569 sc->sc_flags &= ~MALO_ASSOC_FAILED; 570 571 /* get current channel */ 572 ic->ic_curchan = ic->ic_ibss_chan; 573 sc->sc_curchan = ieee80211_chan2ieee(ic, ic->ic_curchan); 574 DPRINTF(1, "%s: current channel is %d\n", 575 device_xname(sc->sc_dev), sc->sc_curchan); 576 577 /* setup device */ 578 if (cmalo_cmd_set_macctrl(sc) != 0) 579 return EIO; 580 if (cmalo_cmd_set_txpower(sc, 15) != 0) 581 return EIO; 582 if (cmalo_cmd_set_antenna(sc, 1) != 0) 583 return EIO; 584 if (cmalo_cmd_set_antenna(sc, 2) != 0) 585 return EIO; 586 if (cmalo_cmd_set_radio(sc, 1) != 0) 587 return EIO; 588 if (cmalo_cmd_set_channel(sc, sc->sc_curchan) != 0) 589 return EIO; 590 if (cmalo_cmd_set_rate(sc, ic->ic_fixed_rate) != 0) 591 return EIO; 592 if (cmalo_cmd_set_snmp(sc, MALO_OID_RTSTRESH) != 0) 593 return EIO; 594 if (cmalo_cmd_set_snmp(sc, MALO_OID_SHORTRETRY) != 0) 595 return EIO; 596 if (cmalo_cmd_set_snmp(sc, MALO_OID_FRAGTRESH) != 0) 597 return EIO; 598 IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl)); 599 if (cmalo_cmd_set_macaddr(sc, ic->ic_myaddr) != 0) 600 return EIO; 601 if (ic->ic_flags & IEEE80211_F_PRIVACY) 602 if (cmalo_wep(sc) != 0) 603 return EIO; 604 605 /* device up */ 606 ifp->if_flags |= IFF_RUNNING; 607 ifp->if_flags &= ~IFF_OACTIVE; 608 609 /* start network */ 610 if (ic->ic_opmode != IEEE80211_M_MONITOR) 611 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 612 if (sc->sc_flags & MALO_ASSOC_FAILED) 613 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 614 else 615 ieee80211_new_state(ic, IEEE80211_S_RUN, -1); 616 617 /* we are not context save anymore for FW commands */ 618 sc->sc_cmd_ctxsave = 0; 619 620 return 0; 621 } 622 623 static void 624 cmalo_watchdog(struct ifnet *ifp) 625 { 626 DPRINTF(2, "watchdog timeout\n"); 627 628 /* accept TX packets again */ 629 ifp->if_flags &= ~IFF_OACTIVE; 630 } 631 632 static int 633 cmalo_media_change(struct ifnet *ifp) 634 { 635 int error; 636 637 if ((error = ieee80211_media_change(ifp) != ENETRESET)) 638 return error; 639 640 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) 641 cmalo_init(ifp); 642 643 return 0; 644 } 645 646 static int 647 cmalo_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 648 { 649 struct malo_softc *sc = ic->ic_ifp->if_softc; 650 enum ieee80211_state ostate; 651 652 ostate = ic->ic_state; 653 654 if (ostate == nstate) 655 goto out; 656 657 switch (nstate) { 658 case IEEE80211_S_INIT: 659 DPRINTF(1, "%s: newstate is IEEE80211_S_INIT\n", 660 device_xname(sc->sc_dev)); 661 break; 662 case IEEE80211_S_SCAN: 663 DPRINTF(1, "%s: newstate is IEEE80211_S_SCAN\n", 664 device_xname(sc->sc_dev)); 665 cmalo_cmd_set_scan(sc); 666 if (!sc->sc_net_num) { 667 /* no networks found */ 668 DPRINTF(1, "%s: no networks found\n", 669 device_xname(sc->sc_dev)); 670 break; 671 } 672 cmalo_select_network(sc); 673 cmalo_cmd_set_auth(sc); 674 cmalo_cmd_set_assoc(sc); 675 break; 676 case IEEE80211_S_AUTH: 677 DPRINTF(1, "%s: newstate is IEEE80211_S_AUTH\n", 678 device_xname(sc->sc_dev)); 679 break; 680 case IEEE80211_S_ASSOC: 681 DPRINTF(1, "%s: newstate is IEEE80211_S_ASSOC\n", 682 device_xname(sc->sc_dev)); 683 break; 684 case IEEE80211_S_RUN: 685 DPRINTF(1, "%s: newstate is IEEE80211_S_RUN\n", 686 device_xname(sc->sc_dev)); 687 cmalo_reflect_network(sc); 688 break; 689 default: 690 break; 691 } 692 693 out: 694 return sc->sc_newstate(ic, nstate, arg); 695 } 696 697 698 static int 699 firmware_load(const char *dname, const char *iname, uint8_t **ucodep, 700 size_t *sizep) 701 { 702 firmware_handle_t fh; 703 int error; 704 705 if ((error = firmware_open(dname, iname, &fh)) != 0) 706 return error; 707 *sizep = firmware_get_size(fh); 708 if ((*ucodep = firmware_malloc(*sizep)) == NULL) { 709 firmware_close(fh); 710 return ENOMEM; 711 } 712 if ((error = firmware_read(fh, 0, *ucodep, *sizep)) != 0) 713 firmware_free(*ucodep, *sizep); 714 firmware_close(fh); 715 716 return error; 717 } 718 719 static int 720 cmalo_fw_alloc(struct malo_softc *sc) 721 { 722 const char *name_h = "malo8385-h"; 723 const char *name_m = "malo8385-m"; 724 int error; 725 726 if (sc->sc_fw_h == NULL) { 727 /* read helper firmware image */ 728 error = firmware_load("malo", name_h, &sc->sc_fw_h, 729 &sc->sc_fw_h_size); 730 if (error != 0) { 731 aprint_error_dev(sc->sc_dev, 732 "error %d, could not read firmware %s\n", 733 error, name_h); 734 return EIO; 735 } 736 } 737 738 if (sc->sc_fw_m == NULL) { 739 /* read main firmware image */ 740 error = firmware_load("malo", name_m, &sc->sc_fw_m, 741 &sc->sc_fw_m_size); 742 if (error != 0) { 743 aprint_error_dev(sc->sc_dev, 744 "error %d, could not read firmware %s\n", 745 error, name_m); 746 return EIO; 747 } 748 } 749 750 return 0; 751 } 752 753 static void 754 cmalo_fw_free(struct malo_softc *sc) 755 { 756 757 if (sc->sc_fw_h != NULL) { 758 firmware_free(sc->sc_fw_h, sc->sc_fw_h_size); 759 sc->sc_fw_h = NULL; 760 } 761 762 if (sc->sc_fw_m != NULL) { 763 firmware_free(sc->sc_fw_m, sc->sc_fw_m_size); 764 sc->sc_fw_m = NULL; 765 } 766 } 767 768 static int 769 cmalo_fw_load_helper(struct malo_softc *sc) 770 { 771 uint8_t val8; 772 uint16_t bsize, *uc; 773 int offset, i; 774 775 /* verify if the card is ready for firmware download */ 776 val8 = MALO_READ_1(sc, MALO_REG_SCRATCH); 777 if (val8 == MALO_VAL_SCRATCH_FW_LOADED) 778 /* firmware already loaded */ 779 return 0; 780 if (val8 != MALO_VAL_SCRATCH_READY) { 781 /* bad register value */ 782 aprint_error_dev(sc->sc_dev, 783 "device not ready for FW download\n"); 784 return EIO; 785 } 786 787 /* download the helper firmware */ 788 for (offset = 0; offset < sc->sc_fw_h_size; offset += bsize) { 789 if (sc->sc_fw_h_size - offset >= MALO_FW_HELPER_BSIZE) 790 bsize = MALO_FW_HELPER_BSIZE; 791 else 792 bsize = sc->sc_fw_h_size - offset; 793 794 /* send a block in words and confirm it */ 795 DPRINTF(3, "%s: download helper FW block (%d bytes, %d off)\n", 796 device_xname(sc->sc_dev), bsize, offset); 797 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, bsize); 798 uc = (uint16_t *)(sc->sc_fw_h + offset); 799 for (i = 0; i < bsize / 2; i++) 800 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i])); 801 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER); 802 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, 803 MALO_VAL_CMD_DL_OVER); 804 805 /* poll for an acknowledgement */ 806 for (i = 0; i < 50; i++) { 807 if (MALO_READ_1(sc, MALO_REG_CARD_STATUS) == 808 MALO_VAL_CMD_DL_OVER) 809 break; 810 delay(1000); 811 } 812 if (i == 50) { 813 aprint_error_dev(sc->sc_dev, 814 "timeout while helper FW block download\n"); 815 return EIO; 816 } 817 } 818 819 /* helper firmware download done */ 820 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, 0); 821 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER); 822 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_CMD_DL_OVER); 823 DPRINTF(1, "%s: helper FW downloaded\n", device_xname(sc->sc_dev)); 824 825 return 0; 826 } 827 828 static int 829 cmalo_fw_load_main(struct malo_softc *sc) 830 { 831 uint16_t val16, bsize = 0, *uc; 832 int offset, i, retry = 0; 833 834 /* verify if the helper firmware has been loaded correctly */ 835 for (i = 0; i < 10; i++) { 836 if (MALO_READ_1(sc, MALO_REG_RBAL) == MALO_FW_HELPER_LOADED) 837 break; 838 delay(1000); 839 } 840 if (i == 10) { 841 aprint_error_dev(sc->sc_dev, "helper FW not loaded\n"); 842 return EIO; 843 } 844 DPRINTF(1, "%s: helper FW loaded successfully\n", 845 device_xname(sc->sc_dev)); 846 847 /* download the main firmware */ 848 for (offset = 0; offset < sc->sc_fw_m_size; offset += bsize) { 849 val16 = MALO_READ_2(sc, MALO_REG_RBAL); 850 /* 851 * If the helper firmware serves us an odd integer then 852 * something went wrong and we retry to download the last 853 * block until we receive a good integer again, or give up. 854 */ 855 if (val16 & 0x0001) { 856 if (retry > MALO_FW_MAIN_MAXRETRY) { 857 aprint_error_dev(sc->sc_dev, 858 "main FW download failed\n"); 859 return EIO; 860 } 861 retry++; 862 offset -= bsize; 863 } else { 864 retry = 0; 865 bsize = val16; 866 } 867 868 /* send a block in words and confirm it */ 869 DPRINTF(3, "%s: download main FW block (%d bytes, %d off)\n", 870 device_xname(sc->sc_dev), bsize, offset); 871 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, bsize); 872 uc = (uint16_t *)(sc->sc_fw_m + offset); 873 for (i = 0; i < bsize / 2; i++) 874 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i])); 875 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER); 876 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, 877 MALO_VAL_CMD_DL_OVER); 878 879 /* poll for an acknowledgement */ 880 for (i = 0; i < 5000; i++) { 881 if (MALO_READ_1(sc, MALO_REG_CARD_STATUS) == 882 MALO_VAL_CMD_DL_OVER) 883 break; 884 } 885 if (i == 5000) { 886 aprint_error_dev(sc->sc_dev, 887 "timeout while main FW block download\n"); 888 return EIO; 889 } 890 } 891 892 DPRINTF(1, "%s: main FW downloaded\n", device_xname(sc->sc_dev)); 893 894 /* verify if the main firmware has been loaded correctly */ 895 for (i = 0; i < 500; i++) { 896 if (MALO_READ_1(sc, MALO_REG_SCRATCH) == 897 MALO_VAL_SCRATCH_FW_LOADED) 898 break; 899 delay(1000); 900 } 901 if (i == 500) { 902 aprint_error_dev(sc->sc_dev, "main FW not loaded\n"); 903 return EIO; 904 } 905 906 DPRINTF(1, "%s: main FW loaded successfully\n", 907 device_xname(sc->sc_dev)); 908 909 return 0; 910 } 911 912 static void 913 cmalo_stop(struct malo_softc *sc) 914 { 915 struct ieee80211com *ic = &sc->sc_ic; 916 struct ifnet *ifp = &sc->sc_if; 917 918 /* device down */ 919 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 920 921 /* change device back to initial state */ 922 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 923 924 /* reset device */ 925 cmalo_cmd_set_reset(sc); 926 sc->sc_flags &= ~MALO_FW_LOADED; 927 928 if (sc->sc_flags & MALO_DEVICE_ENABLED) 929 malo_pcmcia_disable(sc); 930 931 DPRINTF(1, "%s: device down\n", device_xname(sc->sc_dev)); 932 } 933 934 static void 935 cmalo_intr_mask(struct malo_softc *sc, int enable) 936 { 937 uint16_t val16; 938 939 val16 = MALO_READ_2(sc, MALO_REG_HOST_INTR_MASK); 940 941 DPRINTF(3, "%s: intr mask changed from 0x%04x ", 942 device_xname(sc->sc_dev), val16); 943 944 if (enable) 945 MALO_WRITE_2(sc, MALO_REG_HOST_INTR_MASK, 946 val16 & ~MALO_VAL_HOST_INTR_MASK_ON); 947 else 948 MALO_WRITE_2(sc, MALO_REG_HOST_INTR_MASK, 949 val16 | MALO_VAL_HOST_INTR_MASK_ON); 950 951 val16 = MALO_READ_2(sc, MALO_REG_HOST_INTR_MASK); 952 953 DPRINTF(3, "to 0x%04x\n", val16); 954 } 955 956 static void 957 cmalo_rx(struct malo_softc *sc) 958 { 959 struct ieee80211com *ic = &sc->sc_ic; 960 struct ifnet *ifp = &sc->sc_if; 961 struct malo_rx_desc *rxdesc; 962 struct mbuf *m; 963 uint8_t *data; 964 uint16_t psize; 965 int i; 966 967 /* read the whole RX packet which is always 802.3 */ 968 psize = MALO_READ_2(sc, MALO_REG_DATA_READ_LEN); 969 if (psize > MALO_DATA_BUFFER_SIZE) { 970 aprint_error_dev(sc->sc_dev, 971 "received data too large: %dbyte\n", psize); 972 return; 973 } 974 975 MALO_READ_MULTI_2(sc, MALO_REG_DATA_READ, 976 (uint16_t *)sc->sc_data, psize / sizeof(uint16_t)); 977 if (psize & 0x0001) 978 sc->sc_data[psize - 1] = MALO_READ_1(sc, MALO_REG_DATA_READ); 979 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_RX_DL_OVER); 980 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_RX_DL_OVER); 981 982 /* access RX packet descriptor */ 983 rxdesc = (struct malo_rx_desc *)sc->sc_data; 984 rxdesc->status = le16toh(rxdesc->status); 985 rxdesc->pkglen = le16toh(rxdesc->pkglen); 986 rxdesc->pkgoffset = le32toh(rxdesc->pkgoffset); 987 988 DPRINTF(2, "RX status=%d, pkglen=%d, pkgoffset=%d\n", 989 rxdesc->status, rxdesc->pkglen, rxdesc->pkgoffset); 990 991 if (rxdesc->status != MALO_RX_STATUS_OK) 992 /* RX packet is not OK */ 993 return; 994 995 /* remove the LLC / SNAP header */ 996 data = sc->sc_data + rxdesc->pkgoffset; 997 i = (ETHER_ADDR_LEN * 2) + sizeof(struct llc); 998 memcpy(data + (ETHER_ADDR_LEN * 2), data + i, rxdesc->pkglen - i); 999 rxdesc->pkglen -= sizeof(struct llc); 1000 1001 #define ETHER_ALIGN 2 /* XXX */ 1002 /* prepare mbuf */ 1003 m = m_devget(sc->sc_data + rxdesc->pkgoffset, 1004 rxdesc->pkglen, ETHER_ALIGN, ifp, NULL); 1005 if (m == NULL) { 1006 DPRINTF(1, "RX m_devget failed\n"); 1007 ifp->if_ierrors++; 1008 return; 1009 } 1010 1011 if (ifp->if_bpf) 1012 bpf_ops->bpf_mtap(ifp->if_bpf, m); 1013 1014 /* push the frame up to the network stack if not in monitor mode */ 1015 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 1016 (*ifp->if_input)(ifp, m); 1017 ifp->if_ipackets++; 1018 } 1019 } 1020 1021 static int 1022 cmalo_tx(struct malo_softc *sc, struct mbuf *m) 1023 { 1024 struct ifnet *ifp = &sc->sc_if; 1025 struct malo_tx_desc *txdesc = (struct malo_tx_desc *)sc->sc_data; 1026 uint8_t *data; 1027 uint16_t psize; 1028 1029 memset(sc->sc_data, 0, sizeof(*txdesc)); 1030 psize = sizeof(*txdesc) + m->m_pkthdr.len; 1031 data = mtod(m, uint8_t *); 1032 1033 /* prepare TX descriptor */ 1034 txdesc->pkgoffset = htole32(sizeof(*txdesc)); 1035 txdesc->pkglen = htole16(m->m_pkthdr.len); 1036 memcpy(txdesc->dstaddrhigh, data, ETHER_ADDR_LEN); 1037 1038 /* copy mbuf data to the buffer */ 1039 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_data + sizeof(*txdesc)); 1040 m_freem(m); 1041 1042 /* send TX packet to the device */ 1043 MALO_WRITE_2(sc, MALO_REG_DATA_WRITE_LEN, psize); 1044 MALO_WRITE_MULTI_2(sc, MALO_REG_DATA_WRITE, 1045 (uint16_t *)sc->sc_data, psize / sizeof(uint16_t)); 1046 if (psize & 0x0001) { 1047 data = sc->sc_data; 1048 MALO_WRITE_1(sc, MALO_REG_DATA_WRITE, data[psize - 1]); 1049 } 1050 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_TX_DL_OVER); 1051 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_TX_DL_OVER); 1052 1053 ifp->if_flags |= IFF_OACTIVE; 1054 ifp->if_timer = 5; 1055 1056 DPRINTF(2, "%s: TX status=%d, pkglen=%d, pkgoffset=%zd\n", 1057 device_xname(sc->sc_dev), txdesc->status, le16toh(txdesc->pkglen), 1058 sizeof(*txdesc)); 1059 1060 return 0; 1061 } 1062 1063 static void 1064 cmalo_tx_done(struct malo_softc *sc) 1065 { 1066 struct ifnet *ifp = &sc->sc_if; 1067 1068 DPRINTF(2, "%s: TX done\n", device_xname(sc->sc_dev)); 1069 1070 ifp->if_opackets++; 1071 ifp->if_flags &= ~IFF_OACTIVE; 1072 ifp->if_timer = 0; 1073 cmalo_start(ifp); 1074 } 1075 1076 static void 1077 cmalo_event(struct malo_softc *sc) 1078 { 1079 uint16_t event; 1080 1081 /* read event reason */ 1082 event = MALO_READ_2(sc, MALO_REG_CARD_STATUS); 1083 event &= MALO_VAL_CARD_STATUS_MASK; 1084 event = event >> 8; 1085 1086 switch (event) { 1087 case MALO_EVENT_DEAUTH: 1088 DPRINTF(1, "%s: got deauthentication event (0x%04x)\n", 1089 device_xname(sc->sc_dev), event); 1090 /* try to associate again */ 1091 cmalo_cmd_set_assoc(sc); 1092 break; 1093 case MALO_EVENT_DISASSOC: 1094 DPRINTF(1, "%s: got disassociation event (0x%04x)\n", 1095 device_xname(sc->sc_dev), event); 1096 /* try to associate again */ 1097 cmalo_cmd_set_assoc(sc); 1098 break; 1099 default: 1100 DPRINTF(1, "%s: got unknown event (0x%04x)\n", 1101 device_xname(sc->sc_dev), event); 1102 break; 1103 } 1104 1105 /* acknowledge event */ 1106 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_HOST_INTR_EVENT); 1107 } 1108 1109 static void 1110 cmalo_select_network(struct malo_softc *sc) 1111 { 1112 struct ieee80211com *ic = &sc->sc_ic; 1113 int i, best_rssi; 1114 1115 /* reset last selected network */ 1116 sc->sc_net_cur = 0; 1117 1118 /* get desired network */ 1119 if (ic->ic_des_esslen) { 1120 for (i = 0; i < sc->sc_net_num; i++) { 1121 if (!strcmp(ic->ic_des_essid, sc->sc_net[i].ssid)) { 1122 sc->sc_net_cur = i; 1123 DPRINTF(1, "%s: desired network found (%s)\n", 1124 device_xname(sc->sc_dev), 1125 ic->ic_des_essid); 1126 return; 1127 } 1128 } 1129 DPRINTF(1, "%s: desired network not found in scan results " 1130 "(%s)\n", 1131 device_xname(sc->sc_dev), ic->ic_des_essid); 1132 } 1133 1134 /* get network with best signal strength */ 1135 best_rssi = sc->sc_net[0].rssi; 1136 for (i = 0; i < sc->sc_net_num; i++) { 1137 if (best_rssi < sc->sc_net[i].rssi) { 1138 best_rssi = sc->sc_net[i].rssi; 1139 sc->sc_net_cur = i; 1140 } 1141 } 1142 DPRINTF(1, "%s: best network found (%s)\n", 1143 device_xname(sc->sc_dev), sc->sc_net[sc->sc_net_cur].ssid); 1144 } 1145 1146 static void 1147 cmalo_reflect_network(struct malo_softc *sc) 1148 { 1149 struct ieee80211com *ic = &sc->sc_ic; 1150 uint8_t chan; 1151 1152 /* reflect active network to our 80211 stack */ 1153 1154 /* BSSID */ 1155 IEEE80211_ADDR_COPY(ic->ic_bss->ni_bssid, 1156 sc->sc_net[sc->sc_net_cur].bssid); 1157 1158 /* SSID */ 1159 ic->ic_bss->ni_esslen = strlen(sc->sc_net[sc->sc_net_cur].ssid); 1160 memcpy(ic->ic_bss->ni_essid, sc->sc_net[sc->sc_net_cur].ssid, 1161 ic->ic_bss->ni_esslen); 1162 1163 /* channel */ 1164 chan = sc->sc_net[sc->sc_net_cur].channel; 1165 ic->ic_curchan = &ic->ic_channels[chan]; 1166 } 1167 1168 static int 1169 cmalo_wep(struct malo_softc *sc) 1170 { 1171 struct ieee80211com *ic = &sc->sc_ic; 1172 int i; 1173 1174 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1175 struct ieee80211_key *key = &ic->ic_crypto.cs_nw_keys[i]; 1176 1177 if (!key->wk_keylen) 1178 continue; 1179 1180 DPRINTF(1, "%s: setting wep key for index %d\n", 1181 device_xname(sc->sc_dev), i); 1182 1183 cmalo_cmd_set_wep(sc, i, key); 1184 } 1185 1186 return 0; 1187 } 1188 1189 static int 1190 cmalo_rate2bitmap(int rate) 1191 { 1192 switch (rate) { 1193 /* CCK rates */ 1194 case 0: return MALO_RATE_BITMAP_DS1; 1195 case 1: return MALO_RATE_BITMAP_DS2; 1196 case 2: return MALO_RATE_BITMAP_DS5; 1197 case 3: return MALO_RATE_BITMAP_DS11; 1198 1199 /* OFDM rates */ 1200 case 4: return MALO_RATE_BITMAP_OFDM6; 1201 case 5: return MALO_RATE_BITMAP_OFDM9; 1202 case 6: return MALO_RATE_BITMAP_OFDM12; 1203 case 7: return MALO_RATE_BITMAP_OFDM18; 1204 case 8: return MALO_RATE_BITMAP_OFDM24; 1205 case 9: return MALO_RATE_BITMAP_OFDM36; 1206 case 10: return MALO_RATE_BITMAP_OFDM48; 1207 case 11: return MALO_RATE_BITMAP_OFDM54; 1208 1209 /* unknown rate: should not happen */ 1210 default: return 0; 1211 } 1212 } 1213 1214 static void 1215 cmalo_hexdump(void *buf, int len) 1216 { 1217 #ifdef CMALO_DEBUG 1218 int i; 1219 1220 if (cmalo_d >= 2) { 1221 for (i = 0; i < len; i++) { 1222 if (i % 16 == 0) 1223 printf("%s%5i:", i ? "\n" : "", i); 1224 if (i % 4 == 0) 1225 printf(" "); 1226 printf("%02x", (int)*((u_char *)buf + i)); 1227 } 1228 printf("\n"); 1229 } 1230 #endif 1231 } 1232 1233 static int 1234 cmalo_cmd_get_hwspec(struct malo_softc *sc) 1235 { 1236 struct malo_cmd_header *hdr; 1237 struct malo_cmd_body_spec *body; 1238 const uint16_t psize = sizeof(*hdr) + sizeof(*body); 1239 1240 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1241 hdr->cmd = htole16(MALO_CMD_HWSPEC); 1242 hdr->size = htole16(sizeof(*body)); 1243 hdr->seqnum = htole16(1); 1244 hdr->result = 0; 1245 1246 body = (struct malo_cmd_body_spec *)(hdr + 1); 1247 memset(body, 0, sizeof(*body)); 1248 /* set all bits for MAC address, otherwise we won't get one back */ 1249 memset(body->macaddr, 0xff, ETHER_ADDR_LEN); 1250 1251 /* process command request */ 1252 if (cmalo_cmd_request(sc, psize, 0) != 0) 1253 return EIO; 1254 1255 /* process command repsonse */ 1256 cmalo_cmd_response(sc); 1257 1258 return 0; 1259 } 1260 1261 static int 1262 cmalo_cmd_rsp_hwspec(struct malo_softc *sc) 1263 { 1264 struct ieee80211com *ic = &sc->sc_ic; 1265 struct malo_cmd_header *hdr = (struct malo_cmd_header *)sc->sc_cmd; 1266 struct malo_cmd_body_spec *body; 1267 int i; 1268 1269 body = (struct malo_cmd_body_spec *)(hdr + 1); 1270 1271 /* get our MAC address */ 1272 for (i = 0; i < ETHER_ADDR_LEN; i++) 1273 ic->ic_myaddr[i] = body->macaddr[i]; 1274 1275 return 0; 1276 } 1277 1278 static int 1279 cmalo_cmd_set_reset(struct malo_softc *sc) 1280 { 1281 struct malo_cmd_header *hdr = (struct malo_cmd_header *)sc->sc_cmd; 1282 const uint16_t psize = sizeof(*hdr); 1283 1284 hdr->cmd = htole16(MALO_CMD_RESET); 1285 hdr->size = 0; 1286 hdr->seqnum = htole16(1); 1287 hdr->result = 0; 1288 1289 /* process command request */ 1290 if (cmalo_cmd_request(sc, psize, 1) != 0) 1291 return EIO; 1292 1293 /* give the device some time to finish the reset */ 1294 delay(100); 1295 1296 return 0; 1297 } 1298 1299 static int 1300 cmalo_cmd_set_scan(struct malo_softc *sc) 1301 { 1302 struct ieee80211com *ic = &sc->sc_ic; 1303 struct malo_cmd_header *hdr; 1304 struct malo_cmd_body_scan *body; 1305 struct malo_cmd_tlv_ssid *body_ssid; 1306 struct malo_cmd_tlv_chanlist *body_chanlist; 1307 struct malo_cmd_tlv_rates *body_rates; 1308 uint16_t psize; 1309 int i; 1310 1311 psize = sizeof(*hdr) + sizeof(*body) + 1312 sizeof(*body_ssid) + sizeof(*body_chanlist) + sizeof(*body_rates); 1313 1314 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1315 hdr->cmd = htole16(MALO_CMD_SCAN); 1316 hdr->seqnum = htole16(1); 1317 hdr->result = 0; 1318 1319 body = (struct malo_cmd_body_scan *)(hdr + 1); 1320 body->bsstype = 0x03; /* any BSS */ 1321 memset(body->bssid, 0xff, ETHER_ADDR_LEN); 1322 1323 body_ssid = (struct malo_cmd_tlv_ssid *)(body + 1); 1324 body_ssid->type = htole16(MALO_TLV_TYPE_SSID); 1325 body_ssid->size = htole16(0); 1326 1327 body_chanlist = (struct malo_cmd_tlv_chanlist *)(body_ssid + 1); 1328 body_chanlist->type = htole16(MALO_TLV_TYPE_CHANLIST); 1329 body_chanlist->size = htole16(sizeof(body_chanlist->data)); 1330 for (i = 0; i < CHANNELS; i++) { 1331 body_chanlist->data[i].radiotype = 0x00; 1332 body_chanlist->data[i].channumber = (i + 1); 1333 body_chanlist->data[i].scantype = 0x00; /* active */ 1334 body_chanlist->data[i].minscantime = htole16(0); 1335 body_chanlist->data[i].maxscantime = htole16(100); 1336 } 1337 1338 body_rates = (struct malo_cmd_tlv_rates *)(body_chanlist + 1); 1339 body_rates->type = htole16(MALO_TLV_TYPE_RATES); 1340 body_rates->size = 1341 htole16(ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates); 1342 memcpy(body_rates->data, ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates, 1343 ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates); 1344 psize += le16toh(body_rates->size); 1345 1346 memset((char *)(body_rates + 1) + le16toh(body_rates->size), 0, 1347 sizeof(struct malo_cmd_tlv_numprobes)); 1348 1349 hdr->size = htole16(psize - sizeof(*hdr)); 1350 1351 /* process command request */ 1352 if (cmalo_cmd_request(sc, psize, 0) != 0) 1353 return EIO; 1354 1355 /* process command repsonse */ 1356 cmalo_cmd_response(sc); 1357 1358 return 0; 1359 } 1360 1361 static int 1362 cmalo_cmd_rsp_scan(struct malo_softc *sc) 1363 { 1364 struct malo_cmd_header *hdr = (struct malo_cmd_header *)sc->sc_cmd; 1365 struct malo_cmd_body_rsp_scan *body; 1366 struct malo_cmd_body_rsp_scan_set *set; 1367 int i; 1368 1369 memset(sc->sc_net, 0, sizeof(sc->sc_net)); 1370 1371 body = (struct malo_cmd_body_rsp_scan *)(hdr + 1); 1372 body->bufsize = le16toh(body->bufsize); 1373 1374 DPRINTF(1, "bufsize=%d, APs=%d\n", body->bufsize, body->numofset); 1375 sc->sc_net_num = body->numofset; 1376 1377 set = (struct malo_cmd_body_rsp_scan_set *)(body + 1); 1378 1379 /* cycle through found networks */ 1380 for (i = 0; i < body->numofset; i++) { 1381 set->size = le16toh(set->size); 1382 set->beaconintvl = le16toh(set->beaconintvl); 1383 set->capinfo = le16toh(set->capinfo); 1384 1385 DPRINTF(1, "size=%d, bssid=%s, rssi=%d, beaconintvl=%d, " 1386 "capinfo=0x%04x\n", 1387 set->size, ether_sprintf(set->bssid), set->rssi, 1388 set->beaconintvl, set->capinfo); 1389 1390 /* save scan results */ 1391 memcpy(sc->sc_net[i].bssid, set->bssid, sizeof(set->bssid)); 1392 sc->sc_net[i].rssi = set->rssi; 1393 memcpy(sc->sc_net[i].timestamp, set->timestamp, 1394 sizeof(set->timestamp)); 1395 sc->sc_net[i].beaconintvl = set->beaconintvl; 1396 sc->sc_net[i].capinfo = set->capinfo; 1397 1398 cmalo_parse_elements(sc, set->data, 1399 set->size - (sizeof(*set) - sizeof(set->size)), i); 1400 1401 set = (struct malo_cmd_body_rsp_scan_set *) 1402 ((char *)set + sizeof(set->size) + set->size); 1403 } 1404 1405 return 0; 1406 } 1407 1408 static int 1409 cmalo_parse_elements(struct malo_softc *sc, uint8_t *buf, int size, int pos) 1410 { 1411 uint8_t eid, len; 1412 int i; 1413 1414 DPRINTF(2, "element_size=%d, element_pos=%d\n", size, pos); 1415 1416 for (i = 0; i < size; ) { 1417 eid = *(uint8_t *)(buf + i); 1418 i++; 1419 len = *(uint8_t *)(buf + i); 1420 i++; 1421 DPRINTF(2, "eid=%d, len=%d, ", eid, len); 1422 1423 switch (eid) { 1424 case IEEE80211_ELEMID_SSID: 1425 memcpy(sc->sc_net[pos].ssid, buf + i, len); 1426 DPRINTF(2, "ssid=%s\n", sc->sc_net[pos].ssid); 1427 break; 1428 case IEEE80211_ELEMID_RATES: 1429 memcpy(sc->sc_net[pos].rates, buf + i, len); 1430 DPRINTF(2, "rates\n"); 1431 break; 1432 case IEEE80211_ELEMID_DSPARMS: 1433 sc->sc_net[pos].channel = *(uint8_t *)(buf + i); 1434 DPRINTF(2, "chnl=%d\n", sc->sc_net[pos].channel); 1435 break; 1436 default: 1437 DPRINTF(2, "unknown\n"); 1438 break; 1439 } 1440 1441 i += len; 1442 } 1443 1444 return 0; 1445 } 1446 1447 static int 1448 cmalo_cmd_set_auth(struct malo_softc *sc) 1449 { 1450 struct malo_cmd_header *hdr; 1451 struct malo_cmd_body_auth *body; 1452 const uint16_t psize = sizeof(*hdr) + sizeof(*body); 1453 1454 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1455 hdr->cmd = htole16(MALO_CMD_AUTH); 1456 hdr->size = htole16(sizeof(*body)); 1457 hdr->seqnum = htole16(1); 1458 hdr->result = 0; 1459 1460 body = (struct malo_cmd_body_auth *)(hdr + 1); 1461 memcpy(body->peermac, sc->sc_net[sc->sc_net_cur].bssid, ETHER_ADDR_LEN); 1462 body->authtype = 0; 1463 1464 /* process command request */ 1465 if (cmalo_cmd_request(sc, psize, 0) != 0) 1466 return EIO; 1467 1468 /* process command repsonse */ 1469 cmalo_cmd_response(sc); 1470 1471 return 0; 1472 } 1473 1474 static int 1475 cmalo_cmd_set_wep(struct malo_softc *sc, uint16_t index, 1476 struct ieee80211_key *key) 1477 { 1478 struct malo_cmd_header *hdr; 1479 struct malo_cmd_body_wep *body; 1480 const uint16_t psize = sizeof(*hdr) + sizeof(*body); 1481 1482 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1483 hdr->cmd = htole16(MALO_CMD_WEP); 1484 hdr->size = htole16(sizeof(*body)); 1485 hdr->seqnum = htole16(1); 1486 hdr->result = 0; 1487 1488 body = (struct malo_cmd_body_wep *)(hdr + 1); 1489 memset(body, 0, sizeof(*body)); 1490 body->action = htole16(MALO_WEP_ACTION_TYPE_ADD); 1491 body->key_index = htole16(index); 1492 1493 if (body->key_index == 0) { 1494 if (key->wk_keylen > 5) 1495 body->key_type_1 = MALO_WEP_KEY_TYPE_104BIT; 1496 else 1497 body->key_type_1 = MALO_WEP_KEY_TYPE_40BIT; 1498 memcpy(body->key_value_1, key->wk_key, key->wk_keylen); 1499 } 1500 if (body->key_index == 1) { 1501 if (key->wk_keylen > 5) 1502 body->key_type_2 = MALO_WEP_KEY_TYPE_104BIT; 1503 else 1504 body->key_type_2 = MALO_WEP_KEY_TYPE_40BIT; 1505 memcpy(body->key_value_2, key->wk_key, key->wk_keylen); 1506 } 1507 if (body->key_index == 2) { 1508 if (key->wk_keylen > 5) 1509 body->key_type_3 = MALO_WEP_KEY_TYPE_104BIT; 1510 else 1511 body->key_type_3 = MALO_WEP_KEY_TYPE_40BIT; 1512 memcpy(body->key_value_3, key->wk_key, key->wk_keylen); 1513 } 1514 if (body->key_index == 3) { 1515 if (key->wk_keylen > 5) 1516 body->key_type_4 = MALO_WEP_KEY_TYPE_104BIT; 1517 else 1518 body->key_type_4 = MALO_WEP_KEY_TYPE_40BIT; 1519 memcpy(body->key_value_4, key->wk_key, key->wk_keylen); 1520 } 1521 1522 /* process command request */ 1523 if (cmalo_cmd_request(sc, psize, 0) != 0) 1524 return EIO; 1525 1526 /* process command repsonse */ 1527 cmalo_cmd_response(sc); 1528 1529 return 0; 1530 } 1531 1532 static int 1533 cmalo_cmd_set_snmp(struct malo_softc *sc, uint16_t oid) 1534 { 1535 struct malo_cmd_header *hdr; 1536 struct malo_cmd_body_snmp *body; 1537 const uint16_t psize = sizeof(*hdr) + sizeof(*body); 1538 1539 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1540 hdr->cmd = htole16(MALO_CMD_SNMP); 1541 hdr->size = htole16(sizeof(*body)); 1542 hdr->seqnum = htole16(1); 1543 hdr->result = 0; 1544 1545 body = (struct malo_cmd_body_snmp *)(hdr + 1); 1546 memset(body, 0, sizeof(*body)); 1547 body->action = htole16(1); 1548 1549 switch (oid) { 1550 case MALO_OID_RTSTRESH: 1551 body->oid = htole16(MALO_OID_RTSTRESH); 1552 body->size = htole16(2); 1553 *(uint16_t *)body->data = htole16(2347); 1554 break; 1555 case MALO_OID_SHORTRETRY: 1556 body->oid = htole16(MALO_OID_SHORTRETRY); 1557 body->size = htole16(2); 1558 *(uint16_t *)body->data = htole16(4); 1559 break; 1560 case MALO_OID_FRAGTRESH: 1561 body->oid = htole16(MALO_OID_FRAGTRESH); 1562 body->size = htole16(2); 1563 *(uint16_t *)body->data = htole16(2346); 1564 break; 1565 case MALO_OID_80211D: 1566 body->oid = htole16(MALO_OID_80211D); 1567 body->size = htole16(2); 1568 *(uint16_t *)body->data = htole16(1); 1569 break; 1570 default: 1571 break; 1572 } 1573 1574 /* process command request */ 1575 if (cmalo_cmd_request(sc, psize, 0) != 0) 1576 return EIO; 1577 1578 /* process command repsonse */ 1579 cmalo_cmd_response(sc); 1580 1581 return 0; 1582 } 1583 1584 static int 1585 cmalo_cmd_set_radio(struct malo_softc *sc, uint16_t control) 1586 { 1587 struct malo_cmd_header *hdr; 1588 struct malo_cmd_body_radio *body; 1589 const uint16_t psize = sizeof(*hdr) + sizeof(*body); 1590 1591 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1592 hdr->cmd = htole16(MALO_CMD_RADIO); 1593 hdr->size = htole16(sizeof(*body)); 1594 hdr->seqnum = htole16(1); 1595 hdr->result = 0; 1596 1597 body = (struct malo_cmd_body_radio *)(hdr + 1); 1598 body->action = htole16(1); 1599 if (control) 1600 body->control = 1601 htole16(MALO_CMD_RADIO_ON | MALO_CMD_RADIO_AUTO_P); 1602 else 1603 body->control = 0; 1604 1605 /* process command request */ 1606 if (cmalo_cmd_request(sc, psize, 0) != 0) 1607 return EIO; 1608 1609 /* process command repsonse */ 1610 cmalo_cmd_response(sc); 1611 1612 return 0; 1613 } 1614 1615 static int 1616 cmalo_cmd_set_channel(struct malo_softc *sc, uint16_t channel) 1617 { 1618 struct malo_cmd_header *hdr; 1619 struct malo_cmd_body_channel *body; 1620 const uint16_t psize = sizeof(*hdr) + sizeof(*body); 1621 1622 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1623 hdr->cmd = htole16(MALO_CMD_CHANNEL); 1624 hdr->size = htole16(sizeof(*body)); 1625 hdr->seqnum = htole16(1); 1626 hdr->result = 0; 1627 1628 body = (struct malo_cmd_body_channel *)(hdr + 1); 1629 memset(body, 0, sizeof(*body)); 1630 body->action = htole16(1); 1631 body->channel = htole16(channel); 1632 1633 /* process command request */ 1634 if (cmalo_cmd_request(sc, psize, 0) != 0) 1635 return EIO; 1636 1637 /* process command repsonse */ 1638 cmalo_cmd_response(sc); 1639 1640 return 0; 1641 } 1642 1643 1644 static int 1645 cmalo_cmd_set_txpower(struct malo_softc *sc, int16_t txpower) 1646 { 1647 struct malo_cmd_header *hdr; 1648 struct malo_cmd_body_txpower *body; 1649 const uint16_t psize = sizeof(*hdr) + sizeof(*body); 1650 1651 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1652 hdr->cmd = htole16(MALO_CMD_TXPOWER); 1653 hdr->size = htole16(sizeof(*body)); 1654 hdr->seqnum = htole16(1); 1655 hdr->result = 0; 1656 1657 body = (struct malo_cmd_body_txpower *)(hdr + 1); 1658 body->action = htole16(1); 1659 body->txpower = htole16(txpower); 1660 1661 /* process command request */ 1662 if (cmalo_cmd_request(sc, psize, 0) != 0) 1663 return EIO; 1664 1665 /* process command repsonse */ 1666 cmalo_cmd_response(sc); 1667 1668 return 0; 1669 } 1670 1671 static int 1672 cmalo_cmd_set_antenna(struct malo_softc *sc, uint16_t action) 1673 { 1674 struct malo_cmd_header *hdr; 1675 struct malo_cmd_body_antenna *body; 1676 const uint16_t psize = sizeof(*hdr) + sizeof(*body); 1677 1678 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1679 hdr->cmd = htole16(MALO_CMD_ANTENNA); 1680 hdr->size = htole16(sizeof(*body)); 1681 hdr->seqnum = htole16(1); 1682 hdr->result = 0; 1683 1684 body = (struct malo_cmd_body_antenna *)(hdr + 1); 1685 /* 1 = set RX, 2 = set TX */ 1686 body->action = htole16(action); 1687 1688 switch (action) { 1689 case 1: 1690 /* set RX antenna */ 1691 body->antenna_mode = htole16(0xffff); 1692 break; 1693 1694 case 2: 1695 /* set TX antenna */ 1696 body->antenna_mode = htole16(2); 1697 break; 1698 1699 default: 1700 body->antenna_mode = 0; 1701 break; 1702 } 1703 1704 /* process command request */ 1705 if (cmalo_cmd_request(sc, psize, 0) != 0) 1706 return EIO; 1707 1708 /* process command repsonse */ 1709 cmalo_cmd_response(sc); 1710 1711 return 0; 1712 } 1713 1714 static int 1715 cmalo_cmd_set_macctrl(struct malo_softc *sc) 1716 { 1717 struct ieee80211com *ic = &sc->sc_ic; 1718 struct malo_cmd_header *hdr; 1719 struct malo_cmd_body_macctrl *body; 1720 uint16_t psize; 1721 1722 psize = sizeof(*hdr) + sizeof(*body); 1723 1724 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1725 hdr->cmd = htole16(MALO_CMD_MACCTRL); 1726 hdr->size = htole16(sizeof(*body)); 1727 hdr->seqnum = htole16(1); 1728 hdr->result = 0; 1729 1730 body = (struct malo_cmd_body_macctrl *)(hdr + 1); 1731 memset(body, 0, sizeof(*body)); 1732 body->action = htole16(MALO_CMD_MACCTRL_RX_ON | MALO_CMD_MACCTRL_TX_ON); 1733 if (ic->ic_opmode == IEEE80211_M_MONITOR) 1734 body->action |= htole16(MALO_CMD_MACCTRL_PROMISC_ON); 1735 1736 /* process command request */ 1737 if (cmalo_cmd_request(sc, psize, 0) != 0) 1738 return EIO; 1739 1740 /* process command repsonse */ 1741 cmalo_cmd_response(sc); 1742 1743 return 0; 1744 } 1745 1746 static int 1747 cmalo_cmd_set_macaddr(struct malo_softc *sc, uint8_t *macaddr) 1748 { 1749 struct malo_cmd_header *hdr; 1750 struct malo_cmd_body_macaddr *body; 1751 const uint16_t psize = sizeof(*hdr) + sizeof(*body); 1752 1753 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1754 hdr->cmd = htole16(MALO_CMD_MACADDR); 1755 hdr->size = htole16(sizeof(*body)); 1756 hdr->seqnum = htole16(1); 1757 hdr->result = 0; 1758 1759 body = (struct malo_cmd_body_macaddr *)(hdr + 1); 1760 body->action = htole16(1); 1761 memcpy(body->macaddr, macaddr, ETHER_ADDR_LEN); 1762 1763 /* process command request */ 1764 if (cmalo_cmd_request(sc, psize, 0) != 0) 1765 return EIO; 1766 1767 /* process command repsonse */ 1768 cmalo_cmd_response(sc); 1769 1770 return 0; 1771 } 1772 1773 static int 1774 cmalo_cmd_set_assoc(struct malo_softc *sc) 1775 { 1776 struct malo_cmd_header *hdr; 1777 struct malo_cmd_body_assoc *body; 1778 struct malo_cmd_tlv_ssid *body_ssid; 1779 struct malo_cmd_tlv_phy *body_phy; 1780 struct malo_cmd_tlv_cf *body_cf; 1781 struct malo_cmd_tlv_rates *body_rates; 1782 struct malo_cmd_tlv_passeid *body_passeid; 1783 uint16_t psize; 1784 1785 psize = sizeof(*hdr) + sizeof(*body) + sizeof(*body_ssid) + 1786 sizeof(body_phy) + sizeof(*body_cf) + sizeof(*body_rates); 1787 1788 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1789 hdr->cmd = htole16(MALO_CMD_ASSOC); 1790 hdr->seqnum = htole16(1); 1791 hdr->result = 0; 1792 1793 body = (struct malo_cmd_body_assoc *)(hdr + 1); 1794 memset(body, 0, sizeof(*body)); 1795 memcpy(body->peermac, sc->sc_net[sc->sc_net_cur].bssid, ETHER_ADDR_LEN); 1796 body->capinfo = htole16(sc->sc_net[sc->sc_net_cur].capinfo); 1797 body->listenintrv = htole16(10); 1798 1799 body_ssid = (struct malo_cmd_tlv_ssid *)(body + 1); 1800 body_ssid->type = htole16(MALO_TLV_TYPE_SSID); 1801 body_ssid->size = htole16(strlen(sc->sc_net[sc->sc_net_cur].ssid)); 1802 memcpy(body_ssid->data, sc->sc_net[sc->sc_net_cur].ssid, 1803 le16toh(body_ssid->size)); 1804 psize += le16toh(body_ssid->size); 1805 1806 body_phy = (struct malo_cmd_tlv_phy *) 1807 ((char *)(body_ssid + 1) + le16toh(body_ssid->size)); 1808 body_phy->type = htole16(MALO_TLV_TYPE_PHY); 1809 body_phy->size = htole16(1); 1810 body_phy->data[0] = sc->sc_net[sc->sc_net_cur].channel; 1811 psize += le16toh(body_phy->size); 1812 1813 body_cf = (struct malo_cmd_tlv_cf *) 1814 ((char *)(body_phy + 1) + le16toh(body_phy->size)); 1815 body_cf->type = htole16(MALO_TLV_TYPE_CF); 1816 body_cf->size = htole16(0); 1817 1818 body_rates = (struct malo_cmd_tlv_rates *)(body_cf + 1); 1819 body_rates->type = htole16(MALO_TLV_TYPE_RATES); 1820 body_rates->size = htole16(strlen(sc->sc_net[sc->sc_net_cur].rates)); 1821 memcpy(body_rates->data, sc->sc_net[sc->sc_net_cur].rates, 1822 le16toh(body_rates->size)); 1823 psize += le16toh(body_rates->size); 1824 1825 /* hack to correct FW's wrong generated rates-element-id */ 1826 body_passeid = (struct malo_cmd_tlv_passeid *) 1827 ((char *)(body_rates + 1) + le16toh(body_rates->size)); 1828 body_passeid->type = htole16(MALO_TLV_TYPE_PASSEID); 1829 body_passeid->size = body_rates->size; 1830 memcpy(body_passeid->data, body_rates->data, le16toh(body_rates->size)); 1831 psize += le16toh(body_passeid->size); 1832 1833 hdr->size = htole16(psize - sizeof(*hdr)); 1834 1835 /* process command request */ 1836 if (!sc->sc_cmd_ctxsave) { 1837 if (cmalo_cmd_request(sc, psize, 1) != 0) 1838 return EIO; 1839 return 0; 1840 } 1841 if (cmalo_cmd_request(sc, psize, 0) != 0) 1842 return EIO; 1843 1844 /* process command repsonse */ 1845 cmalo_cmd_response(sc); 1846 1847 return 0; 1848 } 1849 1850 static int 1851 cmalo_cmd_rsp_assoc(struct malo_softc *sc) 1852 { 1853 struct malo_cmd_header *hdr = (struct malo_cmd_header *)sc->sc_cmd; 1854 struct malo_cmd_body_rsp_assoc *body; 1855 1856 body = (struct malo_cmd_body_rsp_assoc *)(hdr + 1); 1857 1858 if (body->status) { 1859 DPRINTF(1, "%s: association failed (status %d)\n", 1860 device_xname(sc->sc_dev), body->status); 1861 sc->sc_flags |= MALO_ASSOC_FAILED; 1862 } else 1863 DPRINTF(1, "%s: association successful\n", 1864 device_xname(sc->sc_dev)); 1865 1866 return 0; 1867 } 1868 1869 static int 1870 cmalo_cmd_set_rate(struct malo_softc *sc, int rate) 1871 { 1872 struct malo_cmd_header *hdr; 1873 struct malo_cmd_body_rate *body; 1874 const uint16_t psize = sizeof(*hdr) + sizeof(*body); 1875 1876 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1877 hdr->cmd = htole16(MALO_CMD_RATE); 1878 hdr->size = htole16(sizeof(*body)); 1879 hdr->seqnum = htole16(1); 1880 hdr->result = 0; 1881 1882 body = (struct malo_cmd_body_rate *)(hdr + 1); 1883 body->action = htole16(1); 1884 if (rate == IEEE80211_FIXED_RATE_NONE) { 1885 body->hwauto = htole16(1); 1886 body->ratebitmap = htole16(MALO_RATE_BITMAP_AUTO); 1887 } else { 1888 body->hwauto = 0; 1889 body->ratebitmap = htole16(cmalo_rate2bitmap(rate)); 1890 } 1891 1892 /* process command request */ 1893 if (cmalo_cmd_request(sc, psize, 0) != 0) 1894 return EIO; 1895 1896 /* process command repsonse */ 1897 cmalo_cmd_response(sc); 1898 1899 return 0; 1900 } 1901 1902 static int 1903 cmalo_cmd_request(struct malo_softc *sc, uint16_t psize, int no_response) 1904 { 1905 uint8_t *cmd; 1906 1907 mutex_enter(&sc->sc_mtx); 1908 1909 cmalo_hexdump(sc->sc_cmd, psize); 1910 1911 /* send command request */ 1912 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, psize); 1913 MALO_WRITE_MULTI_2(sc, MALO_REG_CMD_WRITE, 1914 (uint16_t *)sc->sc_cmd, psize / sizeof(uint16_t)); 1915 if (psize & 0x0001) { 1916 cmd = sc->sc_cmd; 1917 MALO_WRITE_1(sc, MALO_REG_CMD_WRITE, cmd[psize - 1]); 1918 } 1919 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER); 1920 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_CMD_DL_OVER); 1921 1922 if (no_response) { 1923 mutex_exit(&sc->sc_mtx); 1924 1925 /* we don't expect a response */ 1926 return 0; 1927 } 1928 1929 /* wait for the command response */ 1930 if (cv_timedwait_sig(&sc->sc_cv, &sc->sc_mtx, 500) == EWOULDBLOCK) { 1931 mutex_exit(&sc->sc_mtx); 1932 aprint_error_dev(sc->sc_dev, 1933 "timeout while waiting for cmd response\n"); 1934 return EIO; 1935 } 1936 mutex_exit(&sc->sc_mtx); 1937 1938 return 0; 1939 } 1940 1941 static int 1942 cmalo_cmd_response(struct malo_softc *sc) 1943 { 1944 struct malo_cmd_header *hdr = (struct malo_cmd_header *)sc->sc_cmd; 1945 uint16_t psize; 1946 int s; 1947 1948 s = splnet(); 1949 1950 #ifdef CMALO_DEBUG 1951 memset(sc->sc_cmd, 0, MALO_CMD_BUFFER_SIZE); 1952 #endif 1953 1954 /* read the whole command response */ 1955 psize = MALO_READ_2(sc, MALO_REG_CMD_READ_LEN); 1956 if (psize > MALO_CMD_BUFFER_SIZE) { 1957 aprint_error_dev(sc->sc_dev, 1958 "command response too large: %dbyte\n", psize); 1959 return EIO; 1960 } 1961 1962 MALO_READ_MULTI_2(sc, MALO_REG_CMD_READ, 1963 (uint16_t *)sc->sc_cmd, psize / sizeof(uint16_t)); 1964 if (psize & 0x0001) 1965 sc->sc_cmd[psize - 1] = MALO_READ_1(sc, MALO_REG_CMD_READ); 1966 1967 cmalo_hexdump(sc->sc_cmd, psize); 1968 1969 /* 1970 * We convert the header values into the machines correct endianess, 1971 * so we don't have to le16toh() all over the code. The body is 1972 * kept in the cards order, little endian. We need to take care 1973 * about the body endianess in the corresponding response routines. 1974 */ 1975 hdr->cmd = le16toh(hdr->cmd); 1976 hdr->size = le16toh(hdr->size); 1977 hdr->seqnum = le16toh(hdr->seqnum); 1978 hdr->result = le16toh(hdr->result); 1979 1980 /* check for a valid command response */ 1981 if (!(hdr->cmd & MALO_CMD_RESP)) { 1982 aprint_error_dev(sc->sc_dev, 1983 "got invalid command response (0x%04x)\n", hdr->cmd); 1984 splx(s); 1985 return EIO; 1986 } 1987 hdr->cmd &= ~MALO_CMD_RESP; 1988 1989 /* association cmd response is special */ 1990 if (hdr->cmd == 0x0012) 1991 hdr->cmd = MALO_CMD_ASSOC; 1992 1993 /* to which command does the response belong */ 1994 switch (hdr->cmd) { 1995 case MALO_CMD_HWSPEC: 1996 DPRINTF(1, "%s: got hwspec cmd response\n", 1997 device_xname(sc->sc_dev)); 1998 cmalo_cmd_rsp_hwspec(sc); 1999 break; 2000 case MALO_CMD_RESET: 2001 /* reset will not send back a response */ 2002 break; 2003 case MALO_CMD_SCAN: 2004 DPRINTF(1, "%s: got scan cmd response\n", 2005 device_xname(sc->sc_dev)); 2006 cmalo_cmd_rsp_scan(sc); 2007 break; 2008 case MALO_CMD_AUTH: 2009 /* do nothing */ 2010 DPRINTF(1, "%s: got auth cmd response\n", 2011 device_xname(sc->sc_dev)); 2012 break; 2013 case MALO_CMD_WEP: 2014 /* do nothing */ 2015 DPRINTF(1, "%s: got wep cmd response\n", 2016 device_xname(sc->sc_dev)); 2017 break; 2018 case MALO_CMD_SNMP: 2019 /* do nothing */ 2020 DPRINTF(1, "%s: got snmp cmd response\n", 2021 device_xname(sc->sc_dev)); 2022 break; 2023 case MALO_CMD_RADIO: 2024 /* do nothing */ 2025 DPRINTF(1, "%s: got radio cmd response\n", 2026 device_xname(sc->sc_dev)); 2027 break; 2028 case MALO_CMD_CHANNEL: 2029 /* do nothing */ 2030 DPRINTF(1, "%s: got channel cmd response\n", 2031 device_xname(sc->sc_dev)); 2032 break; 2033 case MALO_CMD_TXPOWER: 2034 /* do nothing */ 2035 DPRINTF(1, "%s: got txpower cmd response\n", 2036 device_xname(sc->sc_dev)); 2037 break; 2038 case MALO_CMD_ANTENNA: 2039 /* do nothing */ 2040 DPRINTF(1, "%s: got antenna cmd response\n", 2041 device_xname(sc->sc_dev)); 2042 break; 2043 case MALO_CMD_MACCTRL: 2044 /* do nothing */ 2045 DPRINTF(1, "%s: got macctrl cmd response\n", 2046 device_xname(sc->sc_dev)); 2047 break; 2048 case MALO_CMD_MACADDR: 2049 /* do nothing */ 2050 DPRINTF(1, "%s: got macaddr cmd response\n", 2051 device_xname(sc->sc_dev)); 2052 break; 2053 case MALO_CMD_ASSOC: 2054 /* do nothing */ 2055 DPRINTF(1, "%s: got assoc cmd response\n", 2056 device_xname(sc->sc_dev)); 2057 cmalo_cmd_rsp_assoc(sc); 2058 break; 2059 case MALO_CMD_80211D: 2060 /* do nothing */ 2061 DPRINTF(1, "%s: got 80211d cmd response\n", 2062 device_xname(sc->sc_dev)); 2063 break; 2064 case MALO_CMD_BGSCAN_CONFIG: 2065 /* do nothing */ 2066 DPRINTF(1, "%s: got bgscan config cmd response\n", 2067 device_xname(sc->sc_dev)); 2068 break; 2069 case MALO_CMD_BGSCAN_QUERY: 2070 /* do nothing */ 2071 DPRINTF(1, "%s: got bgscan query cmd response\n", 2072 device_xname(sc->sc_dev)); 2073 break; 2074 case MALO_CMD_RATE: 2075 /* do nothing */ 2076 DPRINTF(1, "%s: got rate cmd response\n", 2077 device_xname(sc->sc_dev)); 2078 break; 2079 default: 2080 aprint_error_dev(sc->sc_dev, 2081 "got unknown cmd response (0x%04x)\n", hdr->cmd); 2082 break; 2083 } 2084 2085 splx(s); 2086 2087 return 0; 2088 } 2089 2090 #ifdef _MODULE 2091 2092 MODULE(MODULE_CLASS_DRIVER, malo_pcmcia, NULL); 2093 2094 CFDRIVER_DECL(malo_pcmcia, DV_IFNET, NULL); 2095 extern struct cfattach malo_pcmcia_ca; 2096 static int malo_pcmcialoc[] = { -1 }; 2097 static struct cfparent pcmciaparent = { 2098 "pcmcia", NULL, DVUNIT_ANY 2099 }; 2100 static struct cfdata malo_pcmcia_cfdata[] = { 2101 { 2102 .cf_name = "malo_pcmcia", 2103 .cf_atname = "malo", 2104 .cf_unit = 0, 2105 .cf_fstate = FSTATE_STAR, 2106 .cf_loc = malo_pcmcialoc, 2107 .cf_flags = 0, 2108 .cf_pspec = &pcmciaparent, 2109 }, 2110 { NULL } 2111 }; 2112 2113 static int 2114 malo_pcmcia_modcmd(modcmd_t cmd, void *arg) 2115 { 2116 int err; 2117 2118 switch (cmd) { 2119 case MODULE_CMD_INIT: 2120 err = config_cfdriver_attach(&malo_pcmcia_cd); 2121 if (err) 2122 return err; 2123 err = config_cfattach_attach("malo_pcmcia", &malo_pcmcia_ca); 2124 if (err) { 2125 config_cfdriver_detach(&malo_pcmcia_cd); 2126 return err; 2127 } 2128 err = config_cfdata_attach(malo_pcmcia_cfdata, 1); 2129 if (err) { 2130 config_cfattach_detach("malo_pcmcia", &malo_pcmcia_ca); 2131 config_cfdriver_detach(&malo_pcmcia_cd); 2132 return err; 2133 } 2134 return 0; 2135 case MODULE_CMD_FINI: 2136 err = config_cfdata_detach(malo_pcmcia_cfdata); 2137 if (err) 2138 return err; 2139 config_cfattach_detach("malo_pcmcia", &malo_pcmcia_ca); 2140 config_cfdriver_detach(&malo_pcmcia_cd); 2141 return 0; 2142 default: 2143 return ENOTTY; 2144 } 2145 } 2146 #endif 2147