LCOV - code coverage report
Current view: top level - dev/pcmcia - if_malo.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1014 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 52 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13