root/dev/pcmcia/if_malo.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. malo_pcmcia_match
  2. malo_pcmcia_attach
  3. malo_pcmcia_detach
  4. malo_pcmcia_activate
  5. cmalo_attach
  6. cmalo_ioctl
  7. cmalo_fw_load_helper
  8. cmalo_fw_load_main
  9. cmalo_init
  10. cmalo_stop
  11. cmalo_media_change
  12. cmalo_newstate
  13. cmalo_detach
  14. cmalo_intr
  15. cmalo_intr_mask
  16. cmalo_rx
  17. cmalo_start
  18. cmalo_watchdog
  19. cmalo_tx
  20. cmalo_tx_done
  21. cmalo_event
  22. cmalo_select_network
  23. cmalo_reflect_network
  24. cmalo_wep
  25. cmalo_hexdump
  26. cmalo_cmd_get_hwspec
  27. cmalo_cmd_rsp_hwspec
  28. cmalo_cmd_set_reset
  29. cmalo_cmd_set_scan
  30. cmalo_cmd_rsp_scan
  31. cmalo_parse_elements
  32. cmalo_cmd_set_auth
  33. cmalo_cmd_set_wep
  34. cmalo_cmd_set_snmp
  35. cmalo_cmd_set_radio
  36. cmalo_cmd_set_channel
  37. cmalo_cmd_set_txpower
  38. cmalo_cmd_set_antenna
  39. cmalo_cmd_set_macctrl
  40. cmalo_cmd_set_assoc
  41. cmalo_cmd_rsp_assoc
  42. cmalo_cmd_set_80211d
  43. cmalo_cmd_set_bgscan_config
  44. cmalo_cmd_set_bgscan_query
  45. cmalo_cmd_set_rate
  46. cmalo_cmd_request
  47. cmalo_cmd_response

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

/* [<][>][^][v][top][bottom][index][help] */