1 /* $NetBSD: if_malo_pcmcia.c,v 1.15 2017/10/23 09:24:34 msaitoh 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.15 2017/10/23 09:24:34 msaitoh 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_NOWAIT); 327 328 /* allocate data buffer */ 329 sc->sc_data = malloc(MALO_DATA_BUFFER_SIZE, M_DEVBUF, M_NOWAIT); 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 if (ifp->if_bpf) 526 bpf_ops->bpf_mtap(ifp->if_bpf, m); 527 528 if (cmalo_tx(sc, m) != 0) 529 ifp->if_oerrors++; 530 } 531 532 static int 533 cmalo_ioctl(struct ifnet *ifp, u_long cmd, void *data) 534 { 535 struct malo_softc *sc = ifp->if_softc; 536 struct ieee80211com *ic = &sc->sc_ic; 537 int s, error = 0; 538 539 s = splnet(); 540 541 switch (cmd) { 542 case SIOCSIFFLAGS: 543 if ((error = ifioctl_common(ifp, cmd, data)) != 0) 544 break; 545 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { 546 case IFF_RUNNING: 547 cmalo_stop(sc); 548 break; 549 550 case IFF_UP: 551 cmalo_init(ifp); 552 break; 553 554 default: 555 break; 556 } 557 error = 0; 558 break; 559 560 case SIOCADDMULTI: 561 case SIOCDELMULTI: 562 if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) 563 /* setup multicast filter, etc */ 564 error = 0; 565 break; 566 567 default: 568 error = ieee80211_ioctl(ic, cmd, data); 569 break; 570 } 571 572 if (error == ENETRESET) { 573 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 574 (IFF_UP | IFF_RUNNING)) 575 cmalo_init(ifp); 576 error = 0; 577 } 578 579 splx(s); 580 581 return error; 582 } 583 584 static int 585 cmalo_init(struct ifnet *ifp) 586 { 587 struct malo_softc *sc = ifp->if_softc; 588 struct ieee80211com *ic = &sc->sc_ic; 589 590 if (!(sc->sc_flags & MALO_DEVICE_ENABLED)) 591 malo_pcmcia_enable(sc); 592 593 /* reload the firmware if necessary */ 594 if (!(sc->sc_flags & MALO_FW_LOADED)) { 595 /* disable interrupts */ 596 cmalo_intr_mask(sc, 0); 597 598 /* load firmware */ 599 if (cmalo_fw_load_helper(sc) != 0) 600 return EIO; 601 if (cmalo_fw_load_main(sc) != 0) 602 return EIO; 603 sc->sc_flags |= MALO_FW_LOADED; 604 605 /* enable interrupts */ 606 cmalo_intr_mask(sc, 1); 607 } 608 609 if (ifp->if_flags & IFF_RUNNING) 610 cmalo_stop(sc); 611 612 /* reset association state flag */ 613 sc->sc_flags &= ~MALO_ASSOC_FAILED; 614 615 /* get current channel */ 616 ic->ic_curchan = ic->ic_ibss_chan; 617 sc->sc_curchan = ieee80211_chan2ieee(ic, ic->ic_curchan); 618 DPRINTF(1, "%s: current channel is %d\n", 619 device_xname(sc->sc_dev), sc->sc_curchan); 620 621 /* setup device */ 622 if (cmalo_cmd_set_macctrl(sc) != 0) 623 return EIO; 624 if (cmalo_cmd_set_txpower(sc, 15) != 0) 625 return EIO; 626 if (cmalo_cmd_set_antenna(sc, 1) != 0) 627 return EIO; 628 if (cmalo_cmd_set_antenna(sc, 2) != 0) 629 return EIO; 630 if (cmalo_cmd_set_radio(sc, 1) != 0) 631 return EIO; 632 if (cmalo_cmd_set_channel(sc, sc->sc_curchan) != 0) 633 return EIO; 634 if (cmalo_cmd_set_rate(sc, ic->ic_fixed_rate) != 0) 635 return EIO; 636 if (cmalo_cmd_set_snmp(sc, MALO_OID_RTSTRESH) != 0) 637 return EIO; 638 if (cmalo_cmd_set_snmp(sc, MALO_OID_SHORTRETRY) != 0) 639 return EIO; 640 if (cmalo_cmd_set_snmp(sc, MALO_OID_FRAGTRESH) != 0) 641 return EIO; 642 IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl)); 643 if (cmalo_cmd_set_macaddr(sc, ic->ic_myaddr) != 0) 644 return EIO; 645 if (ic->ic_flags & IEEE80211_F_PRIVACY) 646 if (cmalo_wep(sc) != 0) 647 return EIO; 648 649 /* device up */ 650 ifp->if_flags |= IFF_RUNNING; 651 ifp->if_flags &= ~IFF_OACTIVE; 652 653 /* start network */ 654 if (ic->ic_opmode != IEEE80211_M_MONITOR) 655 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 656 if (sc->sc_flags & MALO_ASSOC_FAILED) 657 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 658 else 659 ieee80211_new_state(ic, IEEE80211_S_RUN, -1); 660 661 /* we are not context save anymore for FW commands */ 662 sc->sc_cmd_ctxsave = 0; 663 664 return 0; 665 } 666 667 static void 668 cmalo_watchdog(struct ifnet *ifp) 669 { 670 DPRINTF(2, "watchdog timeout\n"); 671 672 /* accept TX packets again */ 673 ifp->if_flags &= ~IFF_OACTIVE; 674 } 675 676 static int 677 cmalo_media_change(struct ifnet *ifp) 678 { 679 int error; 680 681 if ((error = ieee80211_media_change(ifp)) != ENETRESET) 682 return error; 683 684 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) 685 cmalo_init(ifp); 686 687 return 0; 688 } 689 690 static int 691 cmalo_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 692 { 693 struct malo_softc *sc = ic->ic_ifp->if_softc; 694 enum ieee80211_state ostate; 695 696 ostate = ic->ic_state; 697 698 if (ostate == nstate) 699 goto out; 700 701 switch (nstate) { 702 case IEEE80211_S_INIT: 703 DPRINTF(1, "%s: newstate is IEEE80211_S_INIT\n", 704 device_xname(sc->sc_dev)); 705 break; 706 case IEEE80211_S_SCAN: 707 DPRINTF(1, "%s: newstate is IEEE80211_S_SCAN\n", 708 device_xname(sc->sc_dev)); 709 cmalo_cmd_set_scan(sc); 710 if (!sc->sc_net_num) { 711 /* no networks found */ 712 DPRINTF(1, "%s: no networks found\n", 713 device_xname(sc->sc_dev)); 714 break; 715 } 716 cmalo_select_network(sc); 717 cmalo_cmd_set_auth(sc); 718 cmalo_cmd_set_assoc(sc); 719 break; 720 case IEEE80211_S_AUTH: 721 DPRINTF(1, "%s: newstate is IEEE80211_S_AUTH\n", 722 device_xname(sc->sc_dev)); 723 break; 724 case IEEE80211_S_ASSOC: 725 DPRINTF(1, "%s: newstate is IEEE80211_S_ASSOC\n", 726 device_xname(sc->sc_dev)); 727 break; 728 case IEEE80211_S_RUN: 729 DPRINTF(1, "%s: newstate is IEEE80211_S_RUN\n", 730 device_xname(sc->sc_dev)); 731 cmalo_reflect_network(sc); 732 break; 733 default: 734 break; 735 } 736 737 out: 738 return sc->sc_newstate(ic, nstate, arg); 739 } 740 741 742 static int 743 firmware_load(const char *dname, const char *iname, uint8_t **ucodep, 744 size_t *sizep) 745 { 746 firmware_handle_t fh; 747 int error; 748 749 if ((error = firmware_open(dname, iname, &fh)) != 0) 750 return error; 751 *sizep = firmware_get_size(fh); 752 if ((*ucodep = firmware_malloc(*sizep)) == NULL) { 753 firmware_close(fh); 754 return ENOMEM; 755 } 756 if ((error = firmware_read(fh, 0, *ucodep, *sizep)) != 0) 757 firmware_free(*ucodep, *sizep); 758 firmware_close(fh); 759 760 return error; 761 } 762 763 static int 764 cmalo_fw_alloc(struct malo_softc *sc) 765 { 766 const char *name_h = "malo8385-h"; 767 const char *name_m = "malo8385-m"; 768 int error; 769 770 if (sc->sc_fw_h == NULL) { 771 /* read helper firmware image */ 772 error = firmware_load("malo", name_h, &sc->sc_fw_h, 773 &sc->sc_fw_h_size); 774 if (error != 0) { 775 aprint_error_dev(sc->sc_dev, 776 "error %d, could not read firmware %s\n", 777 error, name_h); 778 return EIO; 779 } 780 } 781 782 if (sc->sc_fw_m == NULL) { 783 /* read main firmware image */ 784 error = firmware_load("malo", name_m, &sc->sc_fw_m, 785 &sc->sc_fw_m_size); 786 if (error != 0) { 787 aprint_error_dev(sc->sc_dev, 788 "error %d, could not read firmware %s\n", 789 error, name_m); 790 return EIO; 791 } 792 } 793 794 return 0; 795 } 796 797 static void 798 cmalo_fw_free(struct malo_softc *sc) 799 { 800 801 if (sc->sc_fw_h != NULL) { 802 firmware_free(sc->sc_fw_h, sc->sc_fw_h_size); 803 sc->sc_fw_h = NULL; 804 } 805 806 if (sc->sc_fw_m != NULL) { 807 firmware_free(sc->sc_fw_m, sc->sc_fw_m_size); 808 sc->sc_fw_m = NULL; 809 } 810 } 811 812 static int 813 cmalo_fw_load_helper(struct malo_softc *sc) 814 { 815 uint8_t val8; 816 uint16_t bsize, *uc; 817 int offset, i; 818 819 /* verify if the card is ready for firmware download */ 820 val8 = MALO_READ_1(sc, MALO_REG_SCRATCH); 821 if (val8 == MALO_VAL_SCRATCH_FW_LOADED) 822 /* firmware already loaded */ 823 return 0; 824 if (val8 != MALO_VAL_SCRATCH_READY) { 825 /* bad register value */ 826 aprint_error_dev(sc->sc_dev, 827 "device not ready for FW download\n"); 828 return EIO; 829 } 830 831 /* download the helper firmware */ 832 for (offset = 0; offset < sc->sc_fw_h_size; offset += bsize) { 833 if (sc->sc_fw_h_size - offset >= MALO_FW_HELPER_BSIZE) 834 bsize = MALO_FW_HELPER_BSIZE; 835 else 836 bsize = sc->sc_fw_h_size - offset; 837 838 /* send a block in words and confirm it */ 839 DPRINTF(3, "%s: download helper FW block (%d bytes, %d off)\n", 840 device_xname(sc->sc_dev), bsize, offset); 841 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, bsize); 842 uc = (uint16_t *)(sc->sc_fw_h + offset); 843 for (i = 0; i < bsize / 2; i++) 844 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i])); 845 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER); 846 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, 847 MALO_VAL_CMD_DL_OVER); 848 849 /* poll for an acknowledgement */ 850 for (i = 0; i < 50; i++) { 851 if (MALO_READ_1(sc, MALO_REG_CARD_STATUS) == 852 MALO_VAL_CMD_DL_OVER) 853 break; 854 delay(1000); 855 } 856 if (i == 50) { 857 aprint_error_dev(sc->sc_dev, 858 "timeout while helper FW block download\n"); 859 return EIO; 860 } 861 } 862 863 /* helper firmware download done */ 864 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, 0); 865 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER); 866 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_CMD_DL_OVER); 867 DPRINTF(1, "%s: helper FW downloaded\n", device_xname(sc->sc_dev)); 868 869 return 0; 870 } 871 872 static int 873 cmalo_fw_load_main(struct malo_softc *sc) 874 { 875 uint16_t val16, bsize = 0, *uc; 876 int offset, i, retry = 0; 877 878 /* verify if the helper firmware has been loaded correctly */ 879 for (i = 0; i < 10; i++) { 880 if (MALO_READ_1(sc, MALO_REG_RBAL) == MALO_FW_HELPER_LOADED) 881 break; 882 delay(1000); 883 } 884 if (i == 10) { 885 aprint_error_dev(sc->sc_dev, "helper FW not loaded\n"); 886 return EIO; 887 } 888 DPRINTF(1, "%s: helper FW loaded successfully\n", 889 device_xname(sc->sc_dev)); 890 891 /* download the main firmware */ 892 for (offset = 0; offset < sc->sc_fw_m_size; offset += bsize) { 893 val16 = MALO_READ_2(sc, MALO_REG_RBAL); 894 /* 895 * If the helper firmware serves us an odd integer then 896 * something went wrong and we retry to download the last 897 * block until we receive a good integer again, or give up. 898 */ 899 if (val16 & 0x0001) { 900 if (retry > MALO_FW_MAIN_MAXRETRY) { 901 aprint_error_dev(sc->sc_dev, 902 "main FW download failed\n"); 903 return EIO; 904 } 905 retry++; 906 offset -= bsize; 907 } else { 908 retry = 0; 909 bsize = val16; 910 } 911 912 /* send a block in words and confirm it */ 913 DPRINTF(3, "%s: download main FW block (%d bytes, %d off)\n", 914 device_xname(sc->sc_dev), bsize, offset); 915 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, bsize); 916 uc = (uint16_t *)(sc->sc_fw_m + offset); 917 for (i = 0; i < bsize / 2; i++) 918 MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i])); 919 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER); 920 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, 921 MALO_VAL_CMD_DL_OVER); 922 923 /* poll for an acknowledgement */ 924 for (i = 0; i < 5000; i++) { 925 if (MALO_READ_1(sc, MALO_REG_CARD_STATUS) == 926 MALO_VAL_CMD_DL_OVER) 927 break; 928 } 929 if (i == 5000) { 930 aprint_error_dev(sc->sc_dev, 931 "timeout while main FW block download\n"); 932 return EIO; 933 } 934 } 935 936 DPRINTF(1, "%s: main FW downloaded\n", device_xname(sc->sc_dev)); 937 938 /* verify if the main firmware has been loaded correctly */ 939 for (i = 0; i < 500; i++) { 940 if (MALO_READ_1(sc, MALO_REG_SCRATCH) == 941 MALO_VAL_SCRATCH_FW_LOADED) 942 break; 943 delay(1000); 944 } 945 if (i == 500) { 946 aprint_error_dev(sc->sc_dev, "main FW not loaded\n"); 947 return EIO; 948 } 949 950 DPRINTF(1, "%s: main FW loaded successfully\n", 951 device_xname(sc->sc_dev)); 952 953 return 0; 954 } 955 956 static void 957 cmalo_stop(struct malo_softc *sc) 958 { 959 struct ieee80211com *ic = &sc->sc_ic; 960 struct ifnet *ifp = &sc->sc_if; 961 962 /* device down */ 963 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 964 965 /* change device back to initial state */ 966 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 967 968 /* reset device */ 969 cmalo_cmd_set_reset(sc); 970 sc->sc_flags &= ~MALO_FW_LOADED; 971 972 if (sc->sc_flags & MALO_DEVICE_ENABLED) 973 malo_pcmcia_disable(sc); 974 975 DPRINTF(1, "%s: device down\n", device_xname(sc->sc_dev)); 976 } 977 978 static void 979 cmalo_intr_mask(struct malo_softc *sc, int enable) 980 { 981 uint16_t val16; 982 983 val16 = MALO_READ_2(sc, MALO_REG_HOST_INTR_MASK); 984 985 DPRINTF(3, "%s: intr mask changed from 0x%04x ", 986 device_xname(sc->sc_dev), val16); 987 988 if (enable) 989 MALO_WRITE_2(sc, MALO_REG_HOST_INTR_MASK, 990 val16 & ~MALO_VAL_HOST_INTR_MASK_ON); 991 else 992 MALO_WRITE_2(sc, MALO_REG_HOST_INTR_MASK, 993 val16 | MALO_VAL_HOST_INTR_MASK_ON); 994 995 val16 = MALO_READ_2(sc, MALO_REG_HOST_INTR_MASK); 996 997 DPRINTF(3, "to 0x%04x\n", val16); 998 } 999 1000 static void 1001 cmalo_rx(struct malo_softc *sc) 1002 { 1003 struct ieee80211com *ic = &sc->sc_ic; 1004 struct ifnet *ifp = &sc->sc_if; 1005 struct malo_rx_desc *rxdesc; 1006 struct mbuf *m; 1007 uint8_t *data; 1008 uint16_t psize; 1009 int i; 1010 1011 /* read the whole RX packet which is always 802.3 */ 1012 psize = MALO_READ_2(sc, MALO_REG_DATA_READ_LEN); 1013 if (psize > MALO_DATA_BUFFER_SIZE) { 1014 aprint_error_dev(sc->sc_dev, 1015 "received data too large: %dbyte\n", psize); 1016 return; 1017 } 1018 1019 MALO_READ_MULTI_2(sc, MALO_REG_DATA_READ, 1020 (uint16_t *)sc->sc_data, psize / sizeof(uint16_t)); 1021 if (psize & 0x0001) 1022 sc->sc_data[psize - 1] = MALO_READ_1(sc, MALO_REG_DATA_READ); 1023 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_RX_DL_OVER); 1024 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_RX_DL_OVER); 1025 1026 /* access RX packet descriptor */ 1027 rxdesc = (struct malo_rx_desc *)sc->sc_data; 1028 rxdesc->status = le16toh(rxdesc->status); 1029 rxdesc->pkglen = le16toh(rxdesc->pkglen); 1030 rxdesc->pkgoffset = le32toh(rxdesc->pkgoffset); 1031 1032 DPRINTF(2, "RX status=%d, pkglen=%d, pkgoffset=%d\n", 1033 rxdesc->status, rxdesc->pkglen, rxdesc->pkgoffset); 1034 1035 if (rxdesc->status != MALO_RX_STATUS_OK) 1036 /* RX packet is not OK */ 1037 return; 1038 1039 /* remove the LLC / SNAP header */ 1040 data = sc->sc_data + rxdesc->pkgoffset; 1041 i = (ETHER_ADDR_LEN * 2) + sizeof(struct llc); 1042 memcpy(data + (ETHER_ADDR_LEN * 2), data + i, rxdesc->pkglen - i); 1043 rxdesc->pkglen -= sizeof(struct llc); 1044 1045 #define ETHER_ALIGN 2 /* XXX */ 1046 /* prepare mbuf */ 1047 m = m_devget(sc->sc_data + rxdesc->pkgoffset, 1048 rxdesc->pkglen, ETHER_ALIGN, ifp, NULL); 1049 if (m == NULL) { 1050 DPRINTF(1, "RX m_devget failed\n"); 1051 ifp->if_ierrors++; 1052 return; 1053 } 1054 1055 /* push the frame up to the network stack if not in monitor mode */ 1056 if (ic->ic_opmode != IEEE80211_M_MONITOR) 1057 if_percpuq_enqueue(ifp->if_percpuq, m); 1058 } 1059 1060 static int 1061 cmalo_tx(struct malo_softc *sc, struct mbuf *m) 1062 { 1063 struct ifnet *ifp = &sc->sc_if; 1064 struct malo_tx_desc *txdesc = (struct malo_tx_desc *)sc->sc_data; 1065 uint8_t *data; 1066 uint16_t psize; 1067 1068 memset(sc->sc_data, 0, sizeof(*txdesc)); 1069 psize = sizeof(*txdesc) + m->m_pkthdr.len; 1070 data = mtod(m, uint8_t *); 1071 1072 /* prepare TX descriptor */ 1073 txdesc->pkgoffset = htole32(sizeof(*txdesc)); 1074 txdesc->pkglen = htole16(m->m_pkthdr.len); 1075 memcpy(txdesc->dstaddr, data, ETHER_ADDR_LEN); 1076 1077 /* copy mbuf data to the buffer */ 1078 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_data + sizeof(*txdesc)); 1079 m_freem(m); 1080 1081 /* send TX packet to the device */ 1082 MALO_WRITE_2(sc, MALO_REG_DATA_WRITE_LEN, psize); 1083 MALO_WRITE_MULTI_2(sc, MALO_REG_DATA_WRITE, 1084 (uint16_t *)sc->sc_data, psize / sizeof(uint16_t)); 1085 if (psize & 0x0001) { 1086 data = sc->sc_data; 1087 MALO_WRITE_1(sc, MALO_REG_DATA_WRITE, data[psize - 1]); 1088 } 1089 MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_TX_DL_OVER); 1090 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_TX_DL_OVER); 1091 1092 ifp->if_flags |= IFF_OACTIVE; 1093 ifp->if_timer = 5; 1094 1095 DPRINTF(2, "%s: TX status=%d, pkglen=%d, pkgoffset=%zd\n", 1096 device_xname(sc->sc_dev), txdesc->status, le16toh(txdesc->pkglen), 1097 sizeof(*txdesc)); 1098 1099 return 0; 1100 } 1101 1102 static void 1103 cmalo_tx_done(struct malo_softc *sc) 1104 { 1105 struct ifnet *ifp = &sc->sc_if; 1106 int s; 1107 1108 DPRINTF(2, "%s: TX done\n", device_xname(sc->sc_dev)); 1109 1110 s = splnet(); 1111 ifp->if_opackets++; 1112 ifp->if_flags &= ~IFF_OACTIVE; 1113 ifp->if_timer = 0; 1114 cmalo_start(ifp); 1115 splx(s); 1116 } 1117 1118 static void 1119 cmalo_event(struct malo_softc *sc) 1120 { 1121 uint16_t event; 1122 1123 /* read event reason */ 1124 event = MALO_READ_2(sc, MALO_REG_CARD_STATUS); 1125 event &= MALO_VAL_CARD_STATUS_MASK; 1126 event = event >> 8; 1127 1128 switch (event) { 1129 case MALO_EVENT_DEAUTH: 1130 DPRINTF(1, "%s: got deauthentication event (0x%04x)\n", 1131 device_xname(sc->sc_dev), event); 1132 /* try to associate again */ 1133 cmalo_cmd_set_assoc(sc); 1134 break; 1135 case MALO_EVENT_DISASSOC: 1136 DPRINTF(1, "%s: got disassociation event (0x%04x)\n", 1137 device_xname(sc->sc_dev), event); 1138 /* try to associate again */ 1139 cmalo_cmd_set_assoc(sc); 1140 break; 1141 default: 1142 DPRINTF(1, "%s: got unknown event (0x%04x)\n", 1143 device_xname(sc->sc_dev), event); 1144 break; 1145 } 1146 1147 /* acknowledge event */ 1148 MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_HOST_INTR_EVENT); 1149 } 1150 1151 static void 1152 cmalo_select_network(struct malo_softc *sc) 1153 { 1154 struct ieee80211com *ic = &sc->sc_ic; 1155 int i, best_rssi; 1156 1157 /* reset last selected network */ 1158 sc->sc_net_cur = 0; 1159 1160 /* get desired network */ 1161 if (ic->ic_des_esslen) { 1162 for (i = 0; i < sc->sc_net_num; i++) { 1163 if (!strcmp(ic->ic_des_essid, sc->sc_net[i].ssid)) { 1164 sc->sc_net_cur = i; 1165 DPRINTF(1, "%s: desired network found (%s)\n", 1166 device_xname(sc->sc_dev), 1167 ic->ic_des_essid); 1168 return; 1169 } 1170 } 1171 DPRINTF(1, "%s: desired network not found in scan results " 1172 "(%s)\n", 1173 device_xname(sc->sc_dev), ic->ic_des_essid); 1174 } 1175 1176 /* get network with best signal strength */ 1177 best_rssi = sc->sc_net[0].rssi; 1178 for (i = 0; i < sc->sc_net_num; i++) { 1179 if (best_rssi < sc->sc_net[i].rssi) { 1180 best_rssi = sc->sc_net[i].rssi; 1181 sc->sc_net_cur = i; 1182 } 1183 } 1184 DPRINTF(1, "%s: best network found (%s)\n", 1185 device_xname(sc->sc_dev), sc->sc_net[sc->sc_net_cur].ssid); 1186 } 1187 1188 static void 1189 cmalo_reflect_network(struct malo_softc *sc) 1190 { 1191 struct ieee80211com *ic = &sc->sc_ic; 1192 uint8_t chan; 1193 1194 /* reflect active network to our 80211 stack */ 1195 1196 /* BSSID */ 1197 IEEE80211_ADDR_COPY(ic->ic_bss->ni_bssid, 1198 sc->sc_net[sc->sc_net_cur].bssid); 1199 1200 /* SSID */ 1201 ic->ic_bss->ni_esslen = strlen(sc->sc_net[sc->sc_net_cur].ssid); 1202 memcpy(ic->ic_bss->ni_essid, sc->sc_net[sc->sc_net_cur].ssid, 1203 ic->ic_bss->ni_esslen); 1204 1205 /* channel */ 1206 chan = sc->sc_net[sc->sc_net_cur].channel; 1207 ic->ic_curchan = &ic->ic_channels[chan]; 1208 } 1209 1210 static int 1211 cmalo_wep(struct malo_softc *sc) 1212 { 1213 struct ieee80211com *ic = &sc->sc_ic; 1214 int i; 1215 1216 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 1217 struct ieee80211_key *key = &ic->ic_crypto.cs_nw_keys[i]; 1218 1219 if (!key->wk_keylen) 1220 continue; 1221 1222 DPRINTF(1, "%s: setting wep key for index %d\n", 1223 device_xname(sc->sc_dev), i); 1224 1225 cmalo_cmd_set_wep(sc, i, key); 1226 } 1227 1228 return 0; 1229 } 1230 1231 static int 1232 cmalo_rate2bitmap(int rate) 1233 { 1234 switch (rate) { 1235 /* CCK rates */ 1236 case 0: return MALO_RATE_BITMAP_DS1; 1237 case 1: return MALO_RATE_BITMAP_DS2; 1238 case 2: return MALO_RATE_BITMAP_DS5; 1239 case 3: return MALO_RATE_BITMAP_DS11; 1240 1241 /* OFDM rates */ 1242 case 4: return MALO_RATE_BITMAP_OFDM6; 1243 case 5: return MALO_RATE_BITMAP_OFDM9; 1244 case 6: return MALO_RATE_BITMAP_OFDM12; 1245 case 7: return MALO_RATE_BITMAP_OFDM18; 1246 case 8: return MALO_RATE_BITMAP_OFDM24; 1247 case 9: return MALO_RATE_BITMAP_OFDM36; 1248 case 10: return MALO_RATE_BITMAP_OFDM48; 1249 case 11: return MALO_RATE_BITMAP_OFDM54; 1250 1251 /* unknown rate: should not happen */ 1252 default: return 0; 1253 } 1254 } 1255 1256 static void 1257 cmalo_hexdump(void *buf, int len) 1258 { 1259 #ifdef CMALO_DEBUG 1260 int i; 1261 1262 if (cmalo_d >= 2) { 1263 for (i = 0; i < len; i++) { 1264 if (i % 16 == 0) 1265 printf("%s%5i:", i ? "\n" : "", i); 1266 if (i % 4 == 0) 1267 printf(" "); 1268 printf("%02x", (int)*((u_char *)buf + i)); 1269 } 1270 printf("\n"); 1271 } 1272 #endif 1273 } 1274 1275 static int 1276 cmalo_cmd_get_hwspec(struct malo_softc *sc) 1277 { 1278 struct malo_cmd_header *hdr; 1279 struct malo_cmd_body_spec *body; 1280 const uint16_t psize = sizeof(*hdr) + sizeof(*body); 1281 1282 hdr = (struct malo_cmd_header *)sc->sc_cmd; 1283 hdr->cmd = htole16(MALO_CMD_HWSPEC); 1284 hdr->size = htole16(sizeof(*body)); 1285 hdr->seqnum = htole16(1); 1286 hdr->result = 0; 1287 1288 body = (struct malo_cmd_body_spec *)(hdr + 1); 1289 memset(body, 0, sizeof(*body)); 1290 /* set all bits for MAC address, otherwise we won't get one back */ 1291 memset(body->macaddr, 0xff, ETHER_ADDR_LEN); 1292 1293 /* process command request */ 1294 if (cmalo_cmd_request(sc, psize, 0) != 0) 1295 return EIO; 1296 1297 /* process command repsonse */ 1298 cmalo_cmd_response(sc); 1299 1300 return 0; 1301 } 1302 1303 static int 1304 cmalo_cmd_rsp_hwspec(struct malo_softc *sc) 1305 { 1306 struct ieee80211com *ic = &sc->sc_ic; 1307 struct malo_cmd_header *hdr = (struct malo_cmd_header *)sc->sc_cmd; 1308 struct malo_cmd_body_spec *body; 1309 int i; 1310 1311 body = (struct malo_cmd_body_spec *)(hdr + 1); 1312 1313 /* get our MAC address */ 1314 for (i = 0; i < ETHER_ADDR_LEN; i++) 1315 ic->ic_myaddr[i] = body->macaddr[i]; 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