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