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