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