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