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