tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: malo@pci vs malo@pcmcia



On 01/Aug - 21:43, KIYOHARA Takashi wrote:
> Hi! all,
> 
> 
> I have a 'I-O DATA WN-G54/CF'.  And some on-board 88W8686 has on
> pcmcia-bus of Gumstix.
> I think, malo@pcmcia and malo@pci is all different.  These drivers
> can't merge maybe.

From a quick review, the driver seems quite different, and it is
probably why they are not merged in OpenBSD.
> 
> http://www.openbsd.org/cgi-bin/man.cgi?query=malo&apropos=0&sektion=0&manpath=OpenBSD+Current&arch=i386&format=html
> 
> 
> Shall I commit to tree the source for malo@pcmcia?
> If 'yes' then I will try to verify next week end.  :-)

I think it would be nice to have the support for malo@pcmcia too in
NetBSD. 

> 
> Thanks,
> --
> kiyohara

> --- if_malo_pcmcia.c.orig     1970-01-01 09:00:00.000000000 +0900
> +++ if_malo_pcmcia.c  2012-08-01 13:03:31.000000000 +0900
> @@ -0,0 +1,2154 @@
> +/*   $NetBSD$        */
> +/*      $OpenBSD: if_malo.c,v 1.65 2009/03/29 21:53:53 sthen Exp $ */
> +
> +/*
> + * Copyright (c) 2007 Marcus Glocker <mglocker%openbsd.org@localhost>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/cdefs.h>
> +__KERNEL_RCSID(0, "$NetBSD$");
> +
> +#ifdef _MODULE
> +#include <sys/module.h>
> +#endif
> +
> +#include <sys/param.h>
> +#include <sys/bus.h>
> +#include <sys/condvar.h>
> +#include <sys/device.h>
> +#include <sys/intr.h>
> +#include <sys/kernel.h>
> +#include <sys/malloc.h>
> +#include <sys/mbuf.h>
> +#include <sys/mutex.h>
> +#include <sys/pmf.h>
> +#include <sys/proc.h>
> +#include <sys/socket.h>
> +#include <sys/sockio.h>
> +#include <sys/systm.h>
> +
> +#include <net/bpf.h>
> +#include <net/if.h>
> +#include <net/if_dl.h>
> +#include <net/if_ether.h>
> +#include <net/if_media.h>
> +#include <net/if_llc.h>
> +
> +#include <net80211/ieee80211_var.h>
> +#include <net80211/ieee80211_radiotap.h>
> +
> +#include <dev/firmload.h>
> +
> +#include <dev/pcmcia/pcmciareg.h>
> +#include <dev/pcmcia/pcmciavar.h>
> +#include <dev/pcmcia/pcmciadevs.h>
> +
> +#include <dev/pcmcia/if_malovar.h>
> +#include <dev/pcmcia/if_maloreg.h>
> +
> +/*
> + * Driver for the Marvell 88W8385 chip (Compact Flash).
> + */
> +
> +#ifdef CMALO_DEBUG
> +int cmalo_d = 1;
> +#define DPRINTF(l, x...)     do { if ((l) <= cmalo_d) printf(x); } while (0)
> +#else
> +#define DPRINTF(l, x...)
> +#endif
> +
> +static int   malo_pcmcia_match(device_t, cfdata_t, void *);
> +static void  malo_pcmcia_attach(device_t, device_t, void *);
> +static int   malo_pcmcia_detach(device_t, int);
> +static int   malo_pcmcia_activate(device_t, devact_t);
> +
> +static int   malo_pcmcia_validate_config(struct pcmcia_config_entry *);
> +
> +static int   malo_pcmcia_enable(struct malo_softc *);
> +static void  malo_pcmcia_disable(struct malo_softc *);
> +
> +static void  cmalo_attach(void *);
> +static void  cmalo_detach(void *);
> +static int   cmalo_intr(void *);
> +
> +static void  cmalo_start(struct ifnet *);
> +static int   cmalo_ioctl(struct ifnet *, u_long, void *);
> +static int   cmalo_init(struct ifnet *);
> +static void  cmalo_watchdog(struct ifnet *);
> +static int   cmalo_media_change(struct ifnet *);
> +static int   cmalo_newstate(struct ieee80211com *, enum ieee80211_state,
> +                            int);
> +
> +static int   firmware_load(const char *, const char *, uint8_t **, size_t *);
> +static int   cmalo_fw_alloc(struct malo_softc *);
> +static void  cmalo_fw_free(struct malo_softc *);
> +static int   cmalo_fw_load_helper(struct malo_softc *);
> +static int   cmalo_fw_load_main(struct malo_softc *);
> +
> +static void  cmalo_stop(struct malo_softc *);
> +static void  cmalo_intr_mask(struct malo_softc *, int);
> +static void  cmalo_rx(struct malo_softc *);
> +static int   cmalo_tx(struct malo_softc *, struct mbuf *);
> +static void  cmalo_tx_done(struct malo_softc *);
> +static void  cmalo_event(struct malo_softc *);
> +static void  cmalo_select_network(struct malo_softc *);
> +static void  cmalo_reflect_network(struct malo_softc *);
> +static int   cmalo_wep(struct malo_softc *);
> +static int   cmalo_rate2bitmap(int);
> +
> +static void  cmalo_hexdump(void *, int);
> +static int   cmalo_cmd_get_hwspec(struct malo_softc *);
> +static int   cmalo_cmd_rsp_hwspec(struct malo_softc *);
> +static int   cmalo_cmd_set_reset(struct malo_softc *);
> +static int   cmalo_cmd_set_scan(struct malo_softc *);
> +static int   cmalo_cmd_rsp_scan(struct malo_softc *);
> +static int   cmalo_parse_elements(struct malo_softc *, uint8_t *, int, int);
> +static int   cmalo_cmd_set_auth(struct malo_softc *);
> +static int   cmalo_cmd_set_wep(struct malo_softc *, uint16_t,
> +                 struct ieee80211_key *);
> +static int   cmalo_cmd_set_snmp(struct malo_softc *, uint16_t);
> +static int   cmalo_cmd_set_radio(struct malo_softc *, uint16_t);
> +static int   cmalo_cmd_set_channel(struct malo_softc *, uint16_t);
> +static int   cmalo_cmd_set_txpower(struct malo_softc *, int16_t);
> +static int   cmalo_cmd_set_antenna(struct malo_softc *, uint16_t);
> +static int   cmalo_cmd_set_macctrl(struct malo_softc *);
> +static int   cmalo_cmd_set_macaddr(struct malo_softc *, uint8_t *);
> +static int   cmalo_cmd_set_assoc(struct malo_softc *);
> +static int   cmalo_cmd_rsp_assoc(struct malo_softc *);
> +static int   cmalo_cmd_set_rate(struct malo_softc *, int);
> +static int   cmalo_cmd_request(struct malo_softc *, uint16_t, int);
> +static int   cmalo_cmd_response(struct malo_softc *);
> +
> +/*
> + * PCMCIA bus.
> + */
> +struct malo_pcmcia_softc {
> +     struct malo_softc        sc_malo;
> +
> +     struct pcmcia_function  *sc_pf;
> +     struct pcmcia_io_handle  sc_pcioh;
> +     int                      sc_io_window;
> +     void                    *sc_ih;
> +};
> +
> +CFATTACH_DECL_NEW(malo_pcmcia, sizeof(struct malo_pcmcia_softc),
> +     malo_pcmcia_match, malo_pcmcia_attach, malo_pcmcia_detach,
> +     malo_pcmcia_activate);
> +
> +
> +static int
> +malo_pcmcia_match(device_t parent, cfdata_t match, void *aux)
> +{
> +     struct pcmcia_attach_args *pa = aux;
> +
> +/* XXX */
> +#undef PCMCIA_VENDOR_AMBICOM
> +#define PCMCIA_VENDOR_AMBICOM        0x02df
> +#define PCMCIA_PRODUCT_AMBICOM_WL54CF        0x8103
> +/* I-O DATA WN-G54/CF has same vendor/product id as AmbiCom WL54-CF */
> +
> +     if (pa->manufacturer == PCMCIA_VENDOR_AMBICOM &&
> +         pa->product == PCMCIA_PRODUCT_AMBICOM_WL54CF)
> +             return 1;
> +
> +     return 0;
> +}
> +
> +static void
> +malo_pcmcia_attach(device_t parent, device_t self, void *aux)
> +{
> +     struct malo_pcmcia_softc *psc = device_private(self);
> +     struct malo_softc *sc = &psc->sc_malo;
> +     struct pcmcia_attach_args *pa = aux;
> +     struct pcmcia_config_entry *cfe;
> +     int error;
> +
> +     sc->sc_dev = self;
> +     psc->sc_pf = pa->pf;
> +
> +        error = pcmcia_function_configure(pa->pf, 
> malo_pcmcia_validate_config);
> +     if (error) {
> +             aprint_error_dev(self, "configure failed, error=%d\n", error);
> +             return;
> +     }
> +
> +     malo_pcmcia_enable(sc);
> +
> +     cfe = pa->pf->cfe;
> +     sc->sc_iot = cfe->iospace[0].handle.iot;
> +     sc->sc_ioh = cfe->iospace[0].handle.ioh;
> +
> +     cmalo_attach(sc);
> +     if (!(sc->sc_flags & MALO_DEVICE_ATTACHED))
> +             goto fail;
> +
> +     if (pmf_device_register(self, NULL, NULL))
> +             pmf_class_network_register(self, &sc->sc_if);
> +     else
> +             aprint_error_dev(self, "couldn't establish power handler\n");
> +
> +fail:
> +     malo_pcmcia_disable(sc);
> +
> +     if (sc->sc_flags & MALO_DEVICE_ATTACHED)
> +             return;
> +
> +     pcmcia_function_unconfigure(pa->pf);
> +     return;
> +}
> +
> +static int
> +malo_pcmcia_detach(device_t dev, int flags)
> +{
> +     struct malo_pcmcia_softc *psc = device_private(dev);
> +     struct malo_softc *sc = &psc->sc_malo;
> +
> +     cmalo_detach(sc);
> +     malo_pcmcia_disable(sc);
> +     pcmcia_function_unconfigure(psc->sc_pf);
> +
> +     return 0;
> +}
> +
> +static int
> +malo_pcmcia_activate(device_t dev, devact_t act)
> +{
> +     struct malo_pcmcia_softc *psc = device_private(dev);
> +     struct malo_softc *sc = &psc->sc_malo;
> +     struct ifnet *ifp = &sc->sc_if;
> +     int s;
> +
> +     s = splnet();
> +     switch (act) {
> +     case DVACT_DEACTIVATE:
> +             if_deactivate(ifp);
> +             break;
> +     default:
> +             return EOPNOTSUPP;
> +     }
> +     splx(s);
> +
> +     return 0;
> +}
> +
> +
> +int
> +malo_pcmcia_validate_config(struct pcmcia_config_entry *cfe)
> +{
> +
> +     if (cfe->iftype != PCMCIA_IFTYPE_IO || cfe->num_iospace != 1)
> +             return EINVAL;
> +     /* Some cards have a memory space, but we don't use it. */
> +     cfe->num_memspace = 0;
> +     return 0;
> +}
> +
> +
> +static int
> +malo_pcmcia_enable(struct malo_softc *sc)
> +{
> +     struct malo_pcmcia_softc *psc = (struct malo_pcmcia_softc *)sc;
> +
> +     /* establish interrupt */
> +     psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, cmalo_intr, sc);
> +     if (psc->sc_ih == NULL) {
> +             aprint_error(": can't establish interrupt\n");
> +             return -1;
> +     }
> +
> +     if (pcmcia_function_enable(psc->sc_pf)) {
> +             aprint_error(": can't enable function\n");
> +             pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
> +             return -1;
> +     }
> +     sc->sc_flags |= MALO_DEVICE_ENABLED;
> +
> +     return 0;
> +}
> +
> +static void
> +malo_pcmcia_disable(struct malo_softc *sc)
> +{
> +     struct malo_pcmcia_softc *psc = (struct malo_pcmcia_softc *)sc;
> +
> +     pcmcia_function_disable(psc->sc_pf);
> +     if (psc->sc_ih)
> +             pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
> +     psc->sc_ih = NULL;
> +     sc->sc_flags &= ~MALO_DEVICE_ENABLED;
> +}
> +
> +
> +/*
> + * Driver.
> + */
> +static void
> +cmalo_attach(void *arg)
> +{
> +     struct malo_softc *sc = arg;
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     struct ifnet *ifp = &sc->sc_if;
> +     int i;
> +
> +     /* disable interrupts */
> +     cmalo_intr_mask(sc, 0);
> +
> +     /* load firmware */
> +     if (cmalo_fw_alloc(sc) != 0 ||
> +         cmalo_fw_load_helper(sc) != 0 ||
> +         cmalo_fw_load_main(sc) != 0) {
> +             /* free firmware */
> +             cmalo_fw_free(sc);
> +             return;
> +     }
> +     sc->sc_flags |= MALO_FW_LOADED;
> +
> +     /* allocate command buffer */
> +     sc->sc_cmd = malloc(MALO_CMD_BUFFER_SIZE, M_DEVBUF, M_NOWAIT);
> +
> +     /* allocate data buffer */
> +     sc->sc_data = malloc(MALO_DATA_BUFFER_SIZE, M_DEVBUF, M_NOWAIT);
> +
> +     /* enable interrupts */
> +     cmalo_intr_mask(sc, 1);
> +
> +     /* we are context save here for FW commands */
> +     sc->sc_cmd_ctxsave = 1;
> +
> +     mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_VM);
> +     cv_init(&sc->sc_cv, "malo");
> +
> +     /* get hardware specs */
> +     cmalo_cmd_get_hwspec(sc);
> +
> +     /* setup interface */
> +     ifp->if_softc = sc;
> +     ifp->if_start = cmalo_start;
> +     ifp->if_ioctl = cmalo_ioctl;
> +     ifp->if_init = cmalo_init;
> +     ifp->if_watchdog = cmalo_watchdog;
> +     ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
> +     strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
> +     IFQ_SET_READY(&ifp->if_snd);
> +
> +     ic->ic_ifp = ifp;
> +     ic->ic_phytype = IEEE80211_T_OFDM;
> +     ic->ic_opmode = IEEE80211_M_STA;
> +     ic->ic_state = IEEE80211_S_INIT;
> +     ic->ic_caps = IEEE80211_C_MONITOR | IEEE80211_C_WEP;
> +
> +     ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
> +     ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
> +
> +     for (i = 0; i <= 14; i++) {
> +             ic->ic_channels[i].ic_freq =
> +                 ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
> +             ic->ic_channels[i].ic_flags =
> +                 IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
> +                 IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
> +     }
> +
> +     /* attach interface */
> +     if_attach(ifp);
> +     ieee80211_ifattach(ic);
> +
> +     sc->sc_newstate = ic->ic_newstate;
> +     ic->ic_newstate = cmalo_newstate;
> +     ieee80211_media_init(ic, cmalo_media_change, ieee80211_media_status);
> +
> +     /* second attach line */
> +     aprint_normal_dev(sc->sc_dev, "address %s\n",
> +         ether_sprintf(ic->ic_myaddr));
> +
> +     ieee80211_announce(ic);
> +
> +     /* device attached */
> +     sc->sc_flags |= MALO_DEVICE_ATTACHED;
> +}
> +
> +static void
> +cmalo_detach(void *arg)
> +{
> +     struct malo_softc *sc = arg;
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     struct ifnet *ifp = &sc->sc_if;
> +
> +     if (!(sc->sc_flags & MALO_DEVICE_ATTACHED)) {
> +             /* free firmware */
> +             cmalo_fw_free(sc);
> +
> +             /* device was not properly attached */
> +             return;
> +     }
> +
> +     if (ifp->if_flags & IFF_RUNNING)
> +             cmalo_stop(sc);
> +
> +     /* free command buffer */
> +     if (sc->sc_cmd != NULL)
> +             free(sc->sc_cmd, M_DEVBUF);
> +
> +     /* free data buffer */
> +     if (sc->sc_data != NULL)
> +             free(sc->sc_data, M_DEVBUF);
> +
> +     /* free firmware */
> +     cmalo_fw_free(sc);
> +
> +     /* detach inferface */
> +     ieee80211_ifdetach(ic);
> +     if_detach(ifp);
> +
> +     mutex_destroy(&sc->sc_mtx);
> +     cv_destroy(&sc->sc_cv);
> +}
> +
> +static int
> +cmalo_intr(void *arg)
> +{
> +     struct malo_softc *sc = arg;
> +     uint16_t intr = 0;
> +
> +     /* read interrupt reason */
> +     intr = MALO_READ_2(sc, MALO_REG_HOST_INTR_CAUSE);
> +     if (intr == 0)
> +             /* interrupt not for us */
> +             return 0;
> +     if (intr == 0xffff)
> +             /* card has been detached */
> +             return 0;
> +
> +     /* disable interrupts */
> +     cmalo_intr_mask(sc, 0);
> +
> +     /* acknowledge interrupt */
> +     MALO_WRITE_2(sc, MALO_REG_HOST_INTR_CAUSE,
> +         intr & MALO_VAL_HOST_INTR_MASK_ON);
> +
> +     /* enable interrupts */
> +     cmalo_intr_mask(sc, 1);
> +
> +     DPRINTF(2, "%s: interrupt handler called (intr = 0x%04x)\n",
> +         device_xname(sc->sc_dev), intr);
> +
> +     if (intr & MALO_VAL_HOST_INTR_TX)
> +             /* TX frame sent */
> +             cmalo_tx_done(sc);
> +     if (intr & MALO_VAL_HOST_INTR_RX)
> +             /* RX frame received */
> +             cmalo_rx(sc);
> +     if (intr & MALO_VAL_HOST_INTR_CMD) {
> +             /* command response */
> +             mutex_enter(&sc->sc_mtx);
> +             cv_signal(&sc->sc_cv);
> +             mutex_exit(&sc->sc_mtx);
> +             if (!sc->sc_cmd_ctxsave)
> +                     cmalo_cmd_response(sc);
> +     }
> +     if (intr & MALO_VAL_HOST_INTR_EVENT)
> +             /* event */
> +             cmalo_event(sc);
> +
> +     return 1;
> +}
> +
> +
> +/*
> + * Network functions
> + */
> +static void
> +cmalo_start(struct ifnet *ifp)
> +{
> +     struct malo_softc *sc = ifp->if_softc;
> +     struct mbuf *m;
> +
> +     /* don't transmit packets if interface is busy or down */
> +     if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
> +             return;
> +
> +     IFQ_POLL(&ifp->if_snd, m);
> +     if (m == NULL)
> +             return;
> +
> +     IFQ_DEQUEUE(&ifp->if_snd, m);
> +
> +     if (ifp->if_bpf)
> +             bpf_ops->bpf_mtap(ifp->if_bpf, m);
> +
> +     if (cmalo_tx(sc, m) != 0)
> +             ifp->if_oerrors++;
> +}
> +
> +static int
> +cmalo_ioctl(struct ifnet *ifp, u_long cmd, void *data)
> +{
> +     struct malo_softc *sc = ifp->if_softc;
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     int s, error = 0;
> +
> +     s = splnet();
> +
> +     switch (cmd) {
> +     case SIOCSIFFLAGS:
> +             if ((error = ifioctl_common(ifp, cmd, data)) != 0)
> +                     break;
> +             switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
> +             case IFF_RUNNING:
> +                     cmalo_stop(sc);
> +                     break;
> +
> +             case IFF_UP:
> +                     cmalo_init(ifp);
> +                     break;
> +
> +             default:
> +                     break;
> +             }
> +             error = 0;
> +             break;
> +
> +     case SIOCADDMULTI:
> +     case SIOCDELMULTI:
> +             if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET)
> +                     /* setup multicast filter, etc */
> +                     error = 0;
> +             break;
> +
> +     default:
> +             error = ieee80211_ioctl(ic, cmd, data);
> +             break;
> +     }
> +
> +     if (error == ENETRESET) {
> +             if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
> +                 (IFF_UP | IFF_RUNNING))
> +                     cmalo_init(ifp);
> +             error = 0;
> +     }
> +
> +     splx(s);
> +
> +     return error;
> +}
> +
> +static int
> +cmalo_init(struct ifnet *ifp)
> +{
> +     struct malo_softc *sc = ifp->if_softc;
> +     struct ieee80211com *ic = &sc->sc_ic;
> +
> +     if (!(sc->sc_flags & MALO_DEVICE_ENABLED))
> +             malo_pcmcia_enable(sc);
> +
> +     /* reload the firmware if necessary */
> +     if (!(sc->sc_flags & MALO_FW_LOADED)) {
> +             /* disable interrupts */
> +             cmalo_intr_mask(sc, 0);
> +
> +             /* load firmware */
> +             if (cmalo_fw_load_helper(sc) != 0)
> +                     return EIO;
> +             if (cmalo_fw_load_main(sc) != 0)
> +                     return EIO;
> +             sc->sc_flags |= MALO_FW_LOADED;
> +
> +             /* enable interrupts */
> +             cmalo_intr_mask(sc, 1);
> +     }
> +
> +     if (ifp->if_flags & IFF_RUNNING)
> +             cmalo_stop(sc);
> +
> +     /* reset association state flag */
> +     sc->sc_flags &= ~MALO_ASSOC_FAILED;
> +
> +     /* get current channel */
> +     ic->ic_curchan = ic->ic_ibss_chan;
> +     sc->sc_curchan = ieee80211_chan2ieee(ic, ic->ic_curchan);
> +     DPRINTF(1, "%s: current channel is %d\n",
> +         device_xname(sc->sc_dev), sc->sc_curchan);
> +
> +     /* setup device */
> +     if (cmalo_cmd_set_macctrl(sc) != 0)
> +             return EIO;
> +     if (cmalo_cmd_set_txpower(sc, 15) != 0)
> +             return EIO;
> +     if (cmalo_cmd_set_antenna(sc, 1) != 0)
> +             return EIO;
> +     if (cmalo_cmd_set_antenna(sc, 2) != 0)
> +             return EIO;
> +     if (cmalo_cmd_set_radio(sc, 1) != 0)
> +             return EIO;
> +     if (cmalo_cmd_set_channel(sc, sc->sc_curchan) != 0)
> +             return EIO;
> +     if (cmalo_cmd_set_rate(sc, ic->ic_fixed_rate) != 0)
> +             return EIO;
> +     if (cmalo_cmd_set_snmp(sc, MALO_OID_RTSTRESH) != 0)
> +             return EIO;
> +     if (cmalo_cmd_set_snmp(sc, MALO_OID_SHORTRETRY) != 0)
> +             return EIO;
> +     if (cmalo_cmd_set_snmp(sc, MALO_OID_FRAGTRESH) != 0)
> +             return EIO;
> +     IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
> +     if (cmalo_cmd_set_macaddr(sc, ic->ic_myaddr) != 0)
> +             return EIO;
> +     if (ic->ic_flags & IEEE80211_F_PRIVACY)
> +             if (cmalo_wep(sc) != 0)
> +                     return EIO;
> +
> +     /* device up */
> +     ifp->if_flags |= IFF_RUNNING;
> +     ifp->if_flags &= ~IFF_OACTIVE;
> +
> +     /* start network */
> +     if (ic->ic_opmode != IEEE80211_M_MONITOR)
> +             ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
> +     if (sc->sc_flags & MALO_ASSOC_FAILED)
> +             ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
> +     else
> +             ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
> +
> +     /* we are not context save anymore for FW commands */
> +     sc->sc_cmd_ctxsave = 0;
> +
> +     return 0;
> +}
> +
> +static void
> +cmalo_watchdog(struct ifnet *ifp)
> +{
> +     DPRINTF(2, "watchdog timeout\n");
> +
> +     /* accept TX packets again */
> +     ifp->if_flags &= ~IFF_OACTIVE;
> +}
> +
> +static int
> +cmalo_media_change(struct ifnet *ifp)
> +{
> +     int error;
> +
> +     if ((error = ieee80211_media_change(ifp) != ENETRESET))
> +             return error;
> +
> +     if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
> +             cmalo_init(ifp);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
> +{
> +     struct malo_softc *sc = ic->ic_ifp->if_softc;
> +     enum ieee80211_state ostate;
> +
> +     ostate = ic->ic_state;
> +
> +     if (ostate == nstate)
> +             goto out;
> +
> +     switch (nstate) {
> +             case IEEE80211_S_INIT:
> +                     DPRINTF(1, "%s: newstate is IEEE80211_S_INIT\n",
> +                         device_xname(sc->sc_dev));
> +                     break;
> +             case IEEE80211_S_SCAN:
> +                     DPRINTF(1, "%s: newstate is IEEE80211_S_SCAN\n",
> +                         device_xname(sc->sc_dev));
> +                     cmalo_cmd_set_scan(sc);
> +                     if (!sc->sc_net_num) {
> +                             /* no networks found */
> +                             DPRINTF(1, "%s: no networks found\n",
> +                                 device_xname(sc->sc_dev));
> +                             break;
> +                     }
> +                     cmalo_select_network(sc);
> +                     cmalo_cmd_set_auth(sc);
> +                     cmalo_cmd_set_assoc(sc);
> +                     break;
> +             case IEEE80211_S_AUTH:
> +                     DPRINTF(1, "%s: newstate is IEEE80211_S_AUTH\n",
> +                         device_xname(sc->sc_dev));
> +                     break;
> +             case IEEE80211_S_ASSOC:
> +                     DPRINTF(1, "%s: newstate is IEEE80211_S_ASSOC\n",
> +                         device_xname(sc->sc_dev));
> +                     break;
> +             case IEEE80211_S_RUN:
> +                     DPRINTF(1, "%s: newstate is IEEE80211_S_RUN\n",
> +                         device_xname(sc->sc_dev));
> +                     cmalo_reflect_network(sc);
> +                     break;
> +             default:
> +                     break;
> +     }
> +
> +out:
> +     return sc->sc_newstate(ic, nstate, arg);
> +}
> +
> +
> +static int
> +firmware_load(const char *dname, const char *iname, uint8_t **ucodep,
> +           size_t *sizep)
> +{
> +     firmware_handle_t fh;
> +     int error;
> +
> +     if ((error = firmware_open(dname, iname, &fh)) != 0)
> +             return error;
> +     *sizep = firmware_get_size(fh);
> +     if ((*ucodep = firmware_malloc(*sizep)) == NULL) {
> +             firmware_close(fh);
> +             return ENOMEM;
> +     }
> +     if ((error = firmware_read(fh, 0, *ucodep, *sizep)) != 0)
> +             firmware_free(*ucodep, *sizep);
> +     firmware_close(fh);
> +
> +     return error;
> +}
> +
> +static int
> +cmalo_fw_alloc(struct malo_softc *sc)
> +{
> +     const char *name_h = "malo8385-h";
> +     const char *name_m = "malo8385-m";
> +     int error;
> +
> +     if (sc->sc_fw_h == NULL) {
> +             /* read helper firmware image */
> +             error = firmware_load("malo", name_h, &sc->sc_fw_h,
> +                 &sc->sc_fw_h_size);
> +             if (error != 0) {
> +                     aprint_error_dev(sc->sc_dev,
> +                         "error %d, could not read firmware %s\n",
> +                         error, name_h);
> +                     return EIO;
> +             }
> +     }
> +
> +     if (sc->sc_fw_m == NULL) {
> +             /* read main firmware image */
> +             error = firmware_load("malo", name_m, &sc->sc_fw_m,
> +                 &sc->sc_fw_m_size);
> +             if (error != 0) {
> +                     aprint_error_dev(sc->sc_dev,
> +                         "error %d, could not read firmware %s\n",
> +                         error, name_m);
> +                     return EIO;
> +             }
> +     }
> +
> +     return 0;
> +}
> +
> +static void
> +cmalo_fw_free(struct malo_softc *sc)
> +{
> +
> +     if (sc->sc_fw_h != NULL) {
> +             firmware_free(sc->sc_fw_h, sc->sc_fw_h_size);
> +             sc->sc_fw_h = NULL;
> +     }
> +
> +     if (sc->sc_fw_m != NULL) {
> +             firmware_free(sc->sc_fw_m, sc->sc_fw_m_size);
> +             sc->sc_fw_m = NULL;
> +     }
> +}
> +
> +static int
> +cmalo_fw_load_helper(struct malo_softc *sc)
> +{
> +     uint8_t val8;
> +     uint16_t bsize, *uc;
> +     int offset, i;
> +
> +     /* verify if the card is ready for firmware download */
> +     val8 = MALO_READ_1(sc, MALO_REG_SCRATCH);
> +     if (val8 == MALO_VAL_SCRATCH_FW_LOADED)
> +             /* firmware already loaded */
> +             return 0;
> +     if (val8 != MALO_VAL_SCRATCH_READY) {
> +             /* bad register value */
> +             aprint_error_dev(sc->sc_dev,
> +                 "device not ready for FW download\n");
> +             return EIO;
> +     }
> +
> +     /* download the helper firmware */
> +     for (offset = 0; offset < sc->sc_fw_h_size; offset += bsize) {
> +             if (sc->sc_fw_h_size - offset >= MALO_FW_HELPER_BSIZE)
> +                     bsize = MALO_FW_HELPER_BSIZE;
> +             else
> +                     bsize = sc->sc_fw_h_size - offset;
> +
> +             /* send a block in words and confirm it */
> +             DPRINTF(3, "%s: download helper FW block (%d bytes, %d off)\n",
> +                 device_xname(sc->sc_dev), bsize, offset);
> +             MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, bsize);
> +             uc = (uint16_t *)(sc->sc_fw_h + offset);
> +             for (i = 0; i < bsize / 2; i++)
> +                     MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i]));
> +             MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER);
> +             MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE,
> +                 MALO_VAL_CMD_DL_OVER);
> +
> +             /* poll for an acknowledgement */
> +             for (i = 0; i < 50; i++) {
> +                     if (MALO_READ_1(sc, MALO_REG_CARD_STATUS) ==
> +                         MALO_VAL_CMD_DL_OVER)
> +                             break;
> +                     delay(1000);
> +             }
> +             if (i == 50) {
> +                     aprint_error_dev(sc->sc_dev,
> +                         "timeout while helper FW block download\n");
> +                     return EIO;
> +             }
> +     }
> +
> +     /* helper firmware download done */
> +     MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, 0);
> +     MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER);
> +     MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_CMD_DL_OVER);
> +     DPRINTF(1, "%s: helper FW downloaded\n", device_xname(sc->sc_dev));
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_fw_load_main(struct malo_softc *sc)
> +{
> +     uint16_t val16, bsize = 0, *uc;
> +     int offset, i, retry = 0;
> +
> +     /* verify if the helper firmware has been loaded correctly */
> +     for (i = 0; i < 10; i++) {
> +             if (MALO_READ_1(sc, MALO_REG_RBAL) == MALO_FW_HELPER_LOADED)
> +                     break;
> +             delay(1000);
> +     }
> +     if (i == 10) {
> +             aprint_error_dev(sc->sc_dev, "helper FW not loaded\n");
> +             return EIO;
> +     }
> +     DPRINTF(1, "%s: helper FW loaded successfully\n",
> +         device_xname(sc->sc_dev));
> +
> +     /* download the main firmware */
> +     for (offset = 0; offset < sc->sc_fw_m_size; offset += bsize) {
> +             val16 = MALO_READ_2(sc, MALO_REG_RBAL);
> +             /*
> +              * If the helper firmware serves us an odd integer then
> +              * something went wrong and we retry to download the last
> +              * block until we receive a good integer again, or give up.
> +              */
> +             if (val16 & 0x0001) {
> +                     if (retry > MALO_FW_MAIN_MAXRETRY) {
> +                             aprint_error_dev(sc->sc_dev,
> +                                 "main FW download failed\n");
> +                             return EIO;
> +                     }
> +                     retry++;
> +                     offset -= bsize;
> +             } else {
> +                     retry = 0;
> +                     bsize = val16;
> +             }
> +
> +             /* send a block in words and confirm it */
> +             DPRINTF(3, "%s: download main FW block (%d bytes, %d off)\n",
> +                 device_xname(sc->sc_dev), bsize, offset);
> +             MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, bsize);
> +             uc = (uint16_t *)(sc->sc_fw_m + offset);
> +             for (i = 0; i < bsize / 2; i++)
> +                     MALO_WRITE_2(sc, MALO_REG_CMD_WRITE, htole16(uc[i]));
> +             MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER);
> +                MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE,
> +                 MALO_VAL_CMD_DL_OVER);
> +
> +             /* poll for an acknowledgement */
> +             for (i = 0; i < 5000; i++) {
> +                     if (MALO_READ_1(sc, MALO_REG_CARD_STATUS) ==
> +                         MALO_VAL_CMD_DL_OVER)
> +                             break;
> +             }
> +             if (i == 5000) {
> +                     aprint_error_dev(sc->sc_dev,
> +                         "timeout while main FW block download\n");
> +                     return EIO;
> +             }
> +     }
> +
> +     DPRINTF(1, "%s: main FW downloaded\n", device_xname(sc->sc_dev));
> +
> +     /* verify if the main firmware has been loaded correctly */
> +     for (i = 0; i < 500; i++) {
> +             if (MALO_READ_1(sc, MALO_REG_SCRATCH) ==
> +                 MALO_VAL_SCRATCH_FW_LOADED)
> +                     break;
> +             delay(1000);
> +     }
> +     if (i == 500) {
> +             aprint_error_dev(sc->sc_dev, "main FW not loaded\n");
> +             return EIO;
> +     }
> +
> +     DPRINTF(1, "%s: main FW loaded successfully\n",
> +         device_xname(sc->sc_dev));
> +
> +     return 0;
> +}
> +
> +static void
> +cmalo_stop(struct malo_softc *sc)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +        struct ifnet *ifp = &sc->sc_if;
> +
> +     /* device down */
> +     ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
> +
> +     /* change device back to initial state */
> +     ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
> +
> +     /* reset device */
> +     cmalo_cmd_set_reset(sc);
> +     sc->sc_flags &= ~MALO_FW_LOADED;
> +
> +     if (sc->sc_flags & MALO_DEVICE_ENABLED)
> +             malo_pcmcia_disable(sc);
> +
> +     DPRINTF(1, "%s: device down\n", device_xname(sc->sc_dev));
> +}
> +
> +static void
> +cmalo_intr_mask(struct malo_softc *sc, int enable)
> +{
> +     uint16_t val16;
> +
> +     val16 = MALO_READ_2(sc, MALO_REG_HOST_INTR_MASK);
> +
> +     DPRINTF(3, "%s: intr mask changed from 0x%04x ",
> +         device_xname(sc->sc_dev), val16);
> +
> +     if (enable)
> +             MALO_WRITE_2(sc, MALO_REG_HOST_INTR_MASK,
> +                 val16 & ~MALO_VAL_HOST_INTR_MASK_ON);
> +     else
> +             MALO_WRITE_2(sc, MALO_REG_HOST_INTR_MASK,
> +                 val16 | MALO_VAL_HOST_INTR_MASK_ON);
> +
> +     val16 = MALO_READ_2(sc, MALO_REG_HOST_INTR_MASK);
> +
> +     DPRINTF(3, "to 0x%04x\n", val16);
> +}
> +
> +static void
> +cmalo_rx(struct malo_softc *sc)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     struct ifnet *ifp = &sc->sc_if;
> +     struct malo_rx_desc *rxdesc;
> +     struct mbuf *m;
> +     uint8_t *data;
> +     uint16_t psize;
> +     int i;
> +
> +     /* read the whole RX packet which is always 802.3 */
> +     psize = MALO_READ_2(sc, MALO_REG_DATA_READ_LEN);
> +     if (psize > MALO_DATA_BUFFER_SIZE) {
> +             aprint_error_dev(sc->sc_dev,
> +                 "received data too large: %dbyte\n", psize);
> +             return;
> +     }
> +
> +     MALO_READ_MULTI_2(sc, MALO_REG_DATA_READ,
> +         (uint16_t *)sc->sc_data, psize / sizeof(uint16_t));
> +     if (psize & 0x0001)
> +             sc->sc_data[psize - 1] = MALO_READ_1(sc, MALO_REG_DATA_READ);
> +     MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_RX_DL_OVER);
> +     MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_RX_DL_OVER);
> +
> +     /* access RX packet descriptor */
> +     rxdesc = (struct malo_rx_desc *)sc->sc_data;
> +     rxdesc->status = le16toh(rxdesc->status);
> +     rxdesc->pkglen = le16toh(rxdesc->pkglen);
> +     rxdesc->pkgoffset = le32toh(rxdesc->pkgoffset);
> +
> +     DPRINTF(2, "RX status=%d, pkglen=%d, pkgoffset=%d\n",
> +         rxdesc->status, rxdesc->pkglen, rxdesc->pkgoffset);
> +
> +     if (rxdesc->status != MALO_RX_STATUS_OK)
> +             /* RX packet is not OK */
> +             return;
> +
> +     /* remove the LLC / SNAP header */
> +     data = sc->sc_data + rxdesc->pkgoffset;
> +     i = (ETHER_ADDR_LEN * 2) + sizeof(struct llc);
> +     memcpy(data + (ETHER_ADDR_LEN * 2), data + i, rxdesc->pkglen - i);
> +     rxdesc->pkglen -= sizeof(struct llc);
> +
> +#define ETHER_ALIGN  2 /* XXX */
> +     /* prepare mbuf */
> +     m = m_devget(sc->sc_data + rxdesc->pkgoffset,
> +         rxdesc->pkglen, ETHER_ALIGN, ifp, NULL);
> +     if (m == NULL) {
> +             DPRINTF(1, "RX m_devget failed\n");
> +             ifp->if_ierrors++;
> +             return;
> +     }
> +
> +     if (ifp->if_bpf)
> +             bpf_ops->bpf_mtap(ifp->if_bpf, m);
> +
> +     /* push the frame up to the network stack if not in monitor mode */
> +     if (ic->ic_opmode != IEEE80211_M_MONITOR) {
> +             ether_input(ifp, m);
> +             ifp->if_ipackets++;
> +     }
> +}
> +
> +static int
> +cmalo_tx(struct malo_softc *sc, struct mbuf *m)
> +{
> +     struct ifnet *ifp = &sc->sc_if;
> +     struct malo_tx_desc *txdesc = (struct malo_tx_desc *)sc->sc_data;
> +     uint8_t *data;
> +     uint16_t psize;
> +
> +     memset(sc->sc_data, 0, sizeof(*txdesc));
> +     psize = sizeof(*txdesc) + m->m_pkthdr.len;
> +     data = mtod(m, uint8_t *);
> +
> +     /* prepare TX descriptor */
> +     txdesc->pkgoffset = htole32(sizeof(*txdesc));
> +     txdesc->pkglen = htole16(m->m_pkthdr.len);
> +     memcpy(txdesc->dstaddrhigh, data, ETHER_ADDR_LEN);
> +
> +     /* copy mbuf data to the buffer */
> +     m_copydata(m, 0, m->m_pkthdr.len, sc->sc_data + sizeof(*txdesc));
> +     m_freem(m);
> +
> +     /* send TX packet to the device */
> +     MALO_WRITE_2(sc, MALO_REG_DATA_WRITE_LEN, psize);
> +     MALO_WRITE_MULTI_2(sc, MALO_REG_DATA_WRITE,
> +         (uint16_t *)sc->sc_data, psize / sizeof(uint16_t));
> +     if (psize & 0x0001) {
> +             data = sc->sc_data;
> +             MALO_WRITE_1(sc, MALO_REG_DATA_WRITE, data[psize - 1]);
> +     }
> +     MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_TX_DL_OVER);
> +     MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_TX_DL_OVER);
> +
> +     ifp->if_flags |= IFF_OACTIVE;
> +     ifp->if_timer = 5;
> +
> +     DPRINTF(2, "%s: TX status=%d, pkglen=%d, pkgoffset=%zd\n",
> +         device_xname(sc->sc_dev), txdesc->status, le16toh(txdesc->pkglen),
> +         sizeof(*txdesc));
> +
> +     return 0;
> +}
> +
> +static void
> +cmalo_tx_done(struct malo_softc *sc)
> +{
> +     struct ifnet *ifp = &sc->sc_if;
> +
> +     DPRINTF(2, "%s: TX done\n", device_xname(sc->sc_dev));
> +
> +     ifp->if_opackets++;
> +     ifp->if_flags &= ~IFF_OACTIVE;
> +     ifp->if_timer = 0;
> +     cmalo_start(ifp);
> +}
> +
> +static void
> +cmalo_event(struct malo_softc *sc)
> +{
> +     uint16_t event;
> +
> +     /* read event reason */
> +     event = MALO_READ_2(sc, MALO_REG_CARD_STATUS);
> +     event &= MALO_VAL_CARD_STATUS_MASK;
> +     event = event >> 8;
> +
> +     switch (event) {
> +     case MALO_EVENT_DEAUTH:
> +             DPRINTF(1, "%s: got deauthentication event (0x%04x)\n",
> +                 device_xname(sc->sc_dev), event);
> +             /* try to associate again */
> +             cmalo_cmd_set_assoc(sc);
> +             break;
> +     case MALO_EVENT_DISASSOC:
> +             DPRINTF(1, "%s: got disassociation event (0x%04x)\n",
> +                 device_xname(sc->sc_dev), event);
> +             /* try to associate again */
> +             cmalo_cmd_set_assoc(sc);
> +             break;
> +     default:
> +             DPRINTF(1, "%s: got unknown event (0x%04x)\n",
> +                 device_xname(sc->sc_dev), event);
> +             break;
> +     }
> +
> +     /* acknowledge event */
> +     MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_HOST_INTR_EVENT);
> +}
> +
> +static void
> +cmalo_select_network(struct malo_softc *sc)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     int i, best_rssi;
> +
> +     /* reset last selected network */
> +     sc->sc_net_cur = 0;
> +
> +     /* get desired network */
> +     if (ic->ic_des_esslen) {
> +             for (i = 0; i < sc->sc_net_num; i++) {
> +                     if (!strcmp(ic->ic_des_essid, sc->sc_net[i].ssid)) {
> +                             sc->sc_net_cur = i;
> +                             DPRINTF(1, "%s: desired network found (%s)\n",
> +                                 device_xname(sc->sc_dev),
> +                                 ic->ic_des_essid);
> +                             return;
> +                     }
> +             }
> +             DPRINTF(1, "%s: desired network not found in scan results "
> +                 "(%s)\n",
> +                 device_xname(sc->sc_dev), ic->ic_des_essid);
> +     }
> +
> +     /* get network with best signal strength */
> +     best_rssi = sc->sc_net[0].rssi;
> +     for (i = 0; i < sc->sc_net_num; i++) {
> +             if (best_rssi < sc->sc_net[i].rssi) {
> +                     best_rssi = sc->sc_net[i].rssi;
> +                     sc->sc_net_cur = i;
> +             }
> +     }
> +     DPRINTF(1, "%s: best network found (%s)\n",
> +         device_xname(sc->sc_dev), sc->sc_net[sc->sc_net_cur].ssid);
> +}
> +
> +static void
> +cmalo_reflect_network(struct malo_softc *sc)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     uint8_t chan;
> +
> +     /* reflect active network to our 80211 stack */
> +
> +     /* BSSID */
> +     IEEE80211_ADDR_COPY(ic->ic_bss->ni_bssid,
> +         sc->sc_net[sc->sc_net_cur].bssid);
> +
> +     /* SSID */
> +     ic->ic_bss->ni_esslen = strlen(sc->sc_net[sc->sc_net_cur].ssid);
> +     memcpy(ic->ic_bss->ni_essid, sc->sc_net[sc->sc_net_cur].ssid,
> +         ic->ic_bss->ni_esslen);
> +
> +     /* channel */
> +     chan = sc->sc_net[sc->sc_net_cur].channel;
> +     ic->ic_curchan = &ic->ic_channels[chan];
> +}
> +
> +static int
> +cmalo_wep(struct malo_softc *sc)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     int i;
> +
> +     for (i = 0; i < IEEE80211_WEP_NKID; i++) {
> +             struct ieee80211_key *key = &ic->ic_crypto.cs_nw_keys[i];
> +
> +             if (!key->wk_keylen)
> +                     continue;
> +
> +             DPRINTF(1, "%s: setting wep key for index %d\n",
> +                 device_xname(sc->sc_dev), i);
> +
> +             cmalo_cmd_set_wep(sc, i, key);
> +     }
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_rate2bitmap(int rate)
> +{
> +     switch (rate) {
> +     /* CCK rates */
> +     case  0:        return MALO_RATE_BITMAP_DS1;
> +     case  1:        return MALO_RATE_BITMAP_DS2;
> +     case  2:        return MALO_RATE_BITMAP_DS5;
> +     case  3:        return MALO_RATE_BITMAP_DS11;
> +
> +     /* OFDM rates */
> +     case  4:        return MALO_RATE_BITMAP_OFDM6;
> +     case  5:        return MALO_RATE_BITMAP_OFDM9;
> +     case  6:        return MALO_RATE_BITMAP_OFDM12;
> +     case  7:        return MALO_RATE_BITMAP_OFDM18;
> +     case  8:        return MALO_RATE_BITMAP_OFDM24;
> +     case  9:        return MALO_RATE_BITMAP_OFDM36;
> +     case 10:        return MALO_RATE_BITMAP_OFDM48;
> +     case 11:        return MALO_RATE_BITMAP_OFDM54;
> +
> +     /* unknown rate: should not happen */
> +     default:        return 0;
> +     }
> +}
> +
> +static void
> +cmalo_hexdump(void *buf, int len)
> +{
> +#ifdef CMALO_DEBUG
> +     int i;
> +
> +     if (cmalo_d >= 2) {
> +             for (i = 0; i < len; i++) {
> +                     if (i % 16 == 0)
> +                             printf("%s%5i:", i ? "\n" : "", i);
> +                     if (i % 4 == 0)
> +                             printf(" ");
> +                     printf("%02x", (int)*((u_char *)buf + i));
> +             }
> +             printf("\n");
> +     }
> +#endif
> +}
> +
> +static int
> +cmalo_cmd_get_hwspec(struct malo_softc *sc)
> +{
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_spec *body;
> +     const uint16_t psize = sizeof(*hdr) + sizeof(*body);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_HWSPEC);
> +     hdr->size = htole16(sizeof(*body));
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_spec *)(hdr + 1);
> +     memset(body, 0, sizeof(*body));
> +     /* set all bits for MAC address, otherwise we won't get one back */
> +     memset(body->macaddr, 0xff, ETHER_ADDR_LEN);
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_rsp_hwspec(struct malo_softc *sc)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     struct malo_cmd_header *hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     struct malo_cmd_body_spec *body;
> +     int i;
> +
> +     body = (struct malo_cmd_body_spec *)(hdr + 1);
> +
> +     /* get our MAC address */
> +     for (i = 0; i < ETHER_ADDR_LEN; i++)
> +             ic->ic_myaddr[i] = body->macaddr[i];
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_set_reset(struct malo_softc *sc)
> +{
> +     struct malo_cmd_header *hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     const uint16_t psize = sizeof(*hdr);
> +
> +     hdr->cmd = htole16(MALO_CMD_RESET);
> +     hdr->size = 0;
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 1) != 0)
> +             return EIO;
> +
> +     /* give the device some time to finish the reset */
> +     delay(100);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_set_scan(struct malo_softc *sc)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_scan *body;
> +     struct malo_cmd_tlv_ssid *body_ssid;
> +     struct malo_cmd_tlv_chanlist *body_chanlist;
> +     struct malo_cmd_tlv_rates *body_rates;
> +     uint16_t psize;
> +     int i;
> +
> +     psize = sizeof(*hdr) + sizeof(*body) +
> +         sizeof(*body_ssid) + sizeof(*body_chanlist) + sizeof(*body_rates);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_SCAN);
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_scan *)(hdr + 1);
> +     body->bsstype = 0x03; /* any BSS */
> +     memset(body->bssid, 0xff, ETHER_ADDR_LEN);
> +
> +     body_ssid = (struct malo_cmd_tlv_ssid *)(body + 1);
> +     body_ssid->type = htole16(MALO_TLV_TYPE_SSID);
> +     body_ssid->size = htole16(0);
> +
> +     body_chanlist = (struct malo_cmd_tlv_chanlist *)(body_ssid + 1);
> +     body_chanlist->type = htole16(MALO_TLV_TYPE_CHANLIST);
> +     body_chanlist->size = htole16(sizeof(body_chanlist->data));
> +     for (i = 0; i < CHANNELS; i++) {
> +             body_chanlist->data[i].radiotype = 0x00;
> +             body_chanlist->data[i].channumber = (i + 1);
> +             body_chanlist->data[i].scantype = 0x00; /* active */
> +             body_chanlist->data[i].minscantime = htole16(0);
> +             body_chanlist->data[i].maxscantime = htole16(100);
> +     }
> +
> +     body_rates = (struct malo_cmd_tlv_rates *)(body_chanlist + 1);
> +     body_rates->type = htole16(MALO_TLV_TYPE_RATES);
> +     body_rates->size =
> +         htole16(ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates);
> +     memcpy(body_rates->data, ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates,
> +         ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates);
> +     psize += le16toh(body_rates->size);
> +
> +     memset((char *)(body_rates + 1) + le16toh(body_rates->size), 0,
> +         sizeof(struct malo_cmd_tlv_numprobes));
> +
> +     hdr->size = htole16(psize - sizeof(*hdr));
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_rsp_scan(struct malo_softc *sc)
> +{
> +     struct malo_cmd_header *hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     struct malo_cmd_body_rsp_scan *body;
> +     struct malo_cmd_body_rsp_scan_set *set;
> +     uint16_t psize;
> +     int i;
> +
> +     memset(sc->sc_net, 0, sizeof(sc->sc_net));
> +     psize = sizeof(*hdr) + sizeof(*body);
> +
> +     body = (struct malo_cmd_body_rsp_scan *)(hdr + 1);
> +     body->bufsize = le16toh(body->bufsize);
> +
> +     DPRINTF(1, "bufsize=%d, APs=%d\n", body->bufsize, body->numofset);
> +     sc->sc_net_num = body->numofset;
> +
> +     set = (struct malo_cmd_body_rsp_scan_set *)(body + 1);
> +
> +     /* cycle through found networks */
> +     for (i = 0; i < body->numofset; i++) {
> +             set->size = le16toh(set->size);
> +             set->beaconintvl = le16toh(set->beaconintvl);
> +             set->capinfo = le16toh(set->capinfo);
> +
> +             DPRINTF(1, "size=%d, bssid=%s, rssi=%d, beaconintvl=%d, "
> +                 "capinfo=0x%04x\n",
> +                 set->size, ether_sprintf(set->bssid), set->rssi,
> +                 set->beaconintvl, set->capinfo);
> +
> +             /* save scan results */
> +             memcpy(sc->sc_net[i].bssid, set->bssid, sizeof(set->bssid));
> +             sc->sc_net[i].rssi = set->rssi;
> +             memcpy(sc->sc_net[i].timestamp, set->timestamp,
> +                 sizeof(set->timestamp));
> +             sc->sc_net[i].beaconintvl = set->beaconintvl;
> +             sc->sc_net[i].capinfo = set->capinfo;
> +
> +             cmalo_parse_elements(sc, set->data,
> +                 set->size - (sizeof(*set) - sizeof(set->size)), i);
> +
> +             set = (struct malo_cmd_body_rsp_scan_set *)
> +                             ((char *)set + sizeof(set->size) + set->size);
> +     }
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_parse_elements(struct malo_softc *sc, uint8_t *buf, int size, int pos)
> +{
> +     uint8_t eid, len;
> +     int i;
> +
> +     DPRINTF(2, "element_size=%d, element_pos=%d\n", size, pos);
> +
> +     for (i = 0; i < size; ) {
> +             eid = *(uint8_t *)(buf + i);
> +             i++;
> +             len = *(uint8_t *)(buf + i);
> +             i++;
> +             DPRINTF(2, "eid=%d, len=%d, ", eid, len);
> +
> +             switch (eid) {
> +             case IEEE80211_ELEMID_SSID:
> +                     memcpy(sc->sc_net[pos].ssid, buf + i, len);
> +                     DPRINTF(2, "ssid=%s\n", sc->sc_net[pos].ssid);
> +                     break;
> +             case IEEE80211_ELEMID_RATES:
> +                     memcpy(sc->sc_net[pos].rates, buf + i, len);
> +                     DPRINTF(2, "rates\n");
> +                     break;
> +             case IEEE80211_ELEMID_DSPARMS:
> +                     sc->sc_net[pos].channel = *(uint8_t *)(buf + i);
> +                     DPRINTF(2, "chnl=%d\n", sc->sc_net[pos].channel);
> +                     break;
> +             default:
> +                     DPRINTF(2, "unknown\n");
> +                     break;
> +             }
> +
> +             i += len;
> +     }
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_set_auth(struct malo_softc *sc)
> +{
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_auth *body;
> +     const uint16_t psize = sizeof(*hdr) + sizeof(*body);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_AUTH);
> +     hdr->size = htole16(sizeof(*body));
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_auth *)(hdr + 1);
> +     memcpy(body->peermac, sc->sc_net[sc->sc_net_cur].bssid, ETHER_ADDR_LEN);
> +     body->authtype = 0;
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_set_wep(struct malo_softc *sc, uint16_t index,
> +               struct ieee80211_key *key)
> +{
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_wep *body;
> +     const uint16_t psize = sizeof(*hdr) + sizeof(*body);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_WEP);
> +     hdr->size = htole16(sizeof(*body));
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_wep *)(hdr + 1);
> +     memset(body, 0, sizeof(*body));
> +     body->action = htole16(MALO_WEP_ACTION_TYPE_ADD);
> +     body->key_index = htole16(index);
> +
> +     if (body->key_index == 0) {
> +             if (key->wk_keylen > 5)
> +                     body->key_type_1 = MALO_WEP_KEY_TYPE_104BIT;
> +             else
> +                     body->key_type_1 = MALO_WEP_KEY_TYPE_40BIT;
> +             memcpy(body->key_value_1, key->wk_key, key->wk_keylen);
> +     }
> +     if (body->key_index == 1) {
> +             if (key->wk_keylen > 5)
> +                     body->key_type_2 = MALO_WEP_KEY_TYPE_104BIT;
> +             else
> +                     body->key_type_2 = MALO_WEP_KEY_TYPE_40BIT;
> +             memcpy(body->key_value_2, key->wk_key, key->wk_keylen);
> +     }
> +     if (body->key_index == 2) {
> +             if (key->wk_keylen > 5)
> +                     body->key_type_3 = MALO_WEP_KEY_TYPE_104BIT;
> +             else
> +                     body->key_type_3 = MALO_WEP_KEY_TYPE_40BIT;
> +             memcpy(body->key_value_3, key->wk_key, key->wk_keylen);
> +     }
> +     if (body->key_index == 3) {
> +             if (key->wk_keylen > 5)
> +                     body->key_type_4 = MALO_WEP_KEY_TYPE_104BIT;
> +             else
> +                     body->key_type_4 = MALO_WEP_KEY_TYPE_40BIT;
> +             memcpy(body->key_value_4, key->wk_key, key->wk_keylen);
> +     }
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_set_snmp(struct malo_softc *sc, uint16_t oid)
> +{
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_snmp *body;
> +     const uint16_t psize = sizeof(*hdr) + sizeof(*body);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_SNMP);
> +     hdr->size = htole16(sizeof(*body));
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_snmp *)(hdr + 1);
> +     memset(body, 0, sizeof(*body));
> +     body->action = htole16(1);
> +
> +     switch (oid) {
> +     case MALO_OID_RTSTRESH:
> +             body->oid = htole16(MALO_OID_RTSTRESH);
> +             body->size = htole16(2);
> +             *(uint16_t *)body->data = htole16(2347);
> +             break;
> +     case MALO_OID_SHORTRETRY:
> +             body->oid = htole16(MALO_OID_SHORTRETRY);
> +             body->size = htole16(2);
> +             *(uint16_t *)body->data = htole16(4);
> +             break;
> +     case MALO_OID_FRAGTRESH:
> +             body->oid = htole16(MALO_OID_FRAGTRESH);
> +             body->size = htole16(2);
> +             *(uint16_t *)body->data = htole16(2346);
> +             break;
> +     case MALO_OID_80211D:
> +             body->oid = htole16(MALO_OID_80211D);
> +             body->size = htole16(2);
> +             *(uint16_t *)body->data = htole16(1);
> +             break;
> +     default:
> +             break;
> +     }
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_set_radio(struct malo_softc *sc, uint16_t control)
> +{
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_radio *body;
> +     const uint16_t psize = sizeof(*hdr) + sizeof(*body);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_RADIO);
> +     hdr->size = htole16(sizeof(*body));
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_radio *)(hdr + 1);
> +     body->action = htole16(1);
> +     if (control)
> +             body->control =
> +                 htole16(MALO_CMD_RADIO_ON | MALO_CMD_RADIO_AUTO_P);
> +     else
> +             body->control = 0;
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_set_channel(struct malo_softc *sc, uint16_t channel)
> +{
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_channel *body;
> +     const uint16_t psize = sizeof(*hdr) + sizeof(*body);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_CHANNEL);
> +     hdr->size = htole16(sizeof(*body));
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_channel *)(hdr + 1);
> +     memset(body, 0, sizeof(*body));
> +     body->action = htole16(1);
> +     body->channel = htole16(channel);
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +
> +static int
> +cmalo_cmd_set_txpower(struct malo_softc *sc, int16_t txpower)
> +{
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_txpower *body;
> +     const uint16_t psize = sizeof(*hdr) + sizeof(*body);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_TXPOWER);
> +     hdr->size = htole16(sizeof(*body));
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_txpower *)(hdr + 1);
> +     body->action = htole16(1);
> +     body->txpower = htole16(txpower);
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_set_antenna(struct malo_softc *sc, uint16_t action)
> +{
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_antenna *body;
> +     const uint16_t psize = sizeof(*hdr) + sizeof(*body);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_ANTENNA);
> +     hdr->size = htole16(sizeof(*body));
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_antenna *)(hdr + 1);
> +     /* 1 = set RX, 2 = set TX */
> +     body->action = htole16(action);
> +
> +     switch (action) {
> +     case 1:
> +             /* set RX antenna */
> +             body->antenna_mode = htole16(0xffff);
> +             break;
> +
> +     case 2:
> +             /* set TX antenna */
> +             body->antenna_mode = htole16(2);
> +             break;
> +
> +     default:
> +             body->antenna_mode = 0;
> +             break;
> +     }
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_set_macctrl(struct malo_softc *sc)
> +{
> +     struct ieee80211com *ic = &sc->sc_ic;
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_macctrl *body;
> +     uint16_t psize;
> +
> +     psize = sizeof(*hdr) + sizeof(*body);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_MACCTRL);
> +     hdr->size = htole16(sizeof(*body));
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_macctrl *)(hdr + 1);
> +     memset(body, 0, sizeof(*body));
> +     body->action = htole16(MALO_CMD_MACCTRL_RX_ON | MALO_CMD_MACCTRL_TX_ON);
> +     if (ic->ic_opmode == IEEE80211_M_MONITOR)
> +             body->action |= htole16(MALO_CMD_MACCTRL_PROMISC_ON);
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_set_macaddr(struct malo_softc *sc, uint8_t *macaddr)
> +{
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_macaddr *body;
> +     const uint16_t psize = sizeof(*hdr) + sizeof(*body);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_MACADDR);
> +     hdr->size = htole16(sizeof(*body));
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_macaddr *)(hdr + 1);
> +     body->action = htole16(1);
> +     memcpy(body->macaddr, macaddr, ETHER_ADDR_LEN);
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_set_assoc(struct malo_softc *sc)
> +{
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_assoc *body;
> +     struct malo_cmd_tlv_ssid *body_ssid;
> +     struct malo_cmd_tlv_phy *body_phy;
> +     struct malo_cmd_tlv_cf *body_cf;
> +     struct malo_cmd_tlv_rates *body_rates;
> +     struct malo_cmd_tlv_passeid *body_passeid;
> +     uint16_t psize;
> +
> +     psize = sizeof(*hdr) + sizeof(*body) + sizeof(*body_ssid) +
> +         sizeof(body_phy) + sizeof(*body_cf) + sizeof(*body_rates);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_ASSOC);
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_assoc *)(hdr + 1);
> +     memset(body, 0, sizeof(struct malo_cmd_body_assoc *));
> +     memcpy(body->peermac, sc->sc_net[sc->sc_net_cur].bssid, ETHER_ADDR_LEN);
> +     body->capinfo = htole16(sc->sc_net[sc->sc_net_cur].capinfo);
> +     body->listenintrv = htole16(10);
> +
> +     body_ssid = (struct malo_cmd_tlv_ssid *)(body + 1);
> +     body_ssid->type = htole16(MALO_TLV_TYPE_SSID);
> +     body_ssid->size = htole16(strlen(sc->sc_net[sc->sc_net_cur].ssid));
> +     memcpy(body_ssid->data, sc->sc_net[sc->sc_net_cur].ssid,
> +         le16toh(body_ssid->size));
> +     psize += le16toh(body_ssid->size);
> +
> +     body_phy = (struct malo_cmd_tlv_phy *)
> +                     ((char *)(body_ssid + 1) + le16toh(body_ssid->size));
> +     body_phy->type = htole16(MALO_TLV_TYPE_PHY);
> +     body_phy->size = htole16(1);
> +     body_phy->data[0] = sc->sc_net[sc->sc_net_cur].channel;
> +     psize += le16toh(body_phy->size);
> +
> +     body_cf = (struct malo_cmd_tlv_cf *)
> +                     ((char *)(body_phy + 1) + le16toh(body_phy->size));
> +     body_cf->type = htole16(MALO_TLV_TYPE_CF);
> +     body_cf->size = htole16(0);
> +
> +     body_rates = (struct malo_cmd_tlv_rates *)(body_cf + 1);
> +     body_rates->type = htole16(MALO_TLV_TYPE_RATES);
> +     body_rates->size = htole16(strlen(sc->sc_net[sc->sc_net_cur].rates));
> +     memcpy(body_rates->data, sc->sc_net[sc->sc_net_cur].rates,
> +         le16toh(body_rates->size));
> +     psize += le16toh(body_rates->size);
> +
> +     /* hack to correct FW's wrong generated rates-element-id */
> +     body_passeid = (struct malo_cmd_tlv_passeid *)
> +                     ((char *)(body_rates + 1) + le16toh(body_rates->size));
> +     body_passeid->type = htole16(MALO_TLV_TYPE_PASSEID);
> +     body_passeid->size = body_rates->size;
> +     memcpy(body_passeid->data, body_rates->data, le16toh(body_rates->size));
> +     psize += le16toh(body_passeid->size);
> +
> +     hdr->size = htole16(psize - sizeof(*hdr));
> +
> +     /* process command request */
> +     if (!sc->sc_cmd_ctxsave) {
> +             if (cmalo_cmd_request(sc, psize, 1) != 0)
> +                     return EIO;
> +             return 0;
> +     }
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_rsp_assoc(struct malo_softc *sc)
> +{
> +     struct malo_cmd_header *hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     struct malo_cmd_body_rsp_assoc *body;
> +
> +     body = (struct malo_cmd_body_rsp_assoc *)(hdr + 1);
> +
> +     if (body->status) {
> +             DPRINTF(1, "%s: association failed (status %d)\n",
> +                 device_xname(sc->sc_dev), body->status);
> +             sc->sc_flags |= MALO_ASSOC_FAILED;
> +     } else
> +             DPRINTF(1, "%s: association successful\n",
> +                 device_xname(sc->sc_dev));
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_set_rate(struct malo_softc *sc, int rate)
> +{
> +     struct malo_cmd_header *hdr;
> +     struct malo_cmd_body_rate *body;
> +     const uint16_t psize = sizeof(*hdr) + sizeof(*body);
> +
> +     hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     hdr->cmd = htole16(MALO_CMD_RATE);
> +     hdr->size = htole16(sizeof(*body));
> +     hdr->seqnum = htole16(1);
> +     hdr->result = 0;
> +
> +     body = (struct malo_cmd_body_rate *)(hdr + 1);
> +     body->action = htole16(1);
> +     if (rate == IEEE80211_FIXED_RATE_NONE) {
> +             body->hwauto = htole16(1);
> +             body->ratebitmap = htole16(MALO_RATE_BITMAP_AUTO);
> +     } else {
> +             body->hwauto = 0;
> +             body->ratebitmap = htole16(cmalo_rate2bitmap(rate));
> +     }
> +
> +     /* process command request */
> +     if (cmalo_cmd_request(sc, psize, 0) != 0)
> +             return EIO;
> +
> +     /* process command repsonse */
> +     cmalo_cmd_response(sc);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_request(struct malo_softc *sc, uint16_t psize, int no_response)
> +{
> +     uint8_t *cmd;
> +
> +     mutex_enter(&sc->sc_mtx);
> +
> +     cmalo_hexdump(sc->sc_cmd, psize);
> +
> +     /* send command request */
> +     MALO_WRITE_2(sc, MALO_REG_CMD_WRITE_LEN, psize);
> +     MALO_WRITE_MULTI_2(sc, MALO_REG_CMD_WRITE,
> +         (uint16_t *)sc->sc_cmd, psize / sizeof(uint16_t));
> +     if (psize & 0x0001) {
> +             cmd = sc->sc_cmd;
> +             MALO_WRITE_1(sc, MALO_REG_CMD_WRITE, cmd[psize - 1]);
> +     }
> +     MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_CMD_DL_OVER);
> +     MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_CMD_DL_OVER);
> +
> +     if (no_response) {
> +             mutex_exit(&sc->sc_mtx);
> +
> +             /* we don't expect a response */
> +             return 0;
> +     }
> +
> +     /* wait for the command response */
> +     if (cv_timedwait_sig(&sc->sc_cv, &sc->sc_mtx, 500) == EWOULDBLOCK) {
> +             mutex_exit(&sc->sc_mtx);
> +             aprint_error_dev(sc->sc_dev,
> +                 "timeout while waiting for cmd response\n");
> +             return EIO;
> +     }
> +     mutex_exit(&sc->sc_mtx);
> +
> +     return 0;
> +}
> +
> +static int
> +cmalo_cmd_response(struct malo_softc *sc)
> +{
> +     struct malo_cmd_header *hdr = (struct malo_cmd_header *)sc->sc_cmd;
> +     uint16_t psize;
> +     int s;
> +
> +     s = splnet();
> +
> +#ifdef CMALO_DEBUG
> +     memset(sc->sc_cmd, 0, MALO_CMD_BUFFER_SIZE);
> +#endif
> +
> +     /* read the whole command response */
> +     psize = MALO_READ_2(sc, MALO_REG_CMD_READ_LEN);
> +     if (psize > MALO_CMD_BUFFER_SIZE) {
> +             aprint_error_dev(sc->sc_dev,
> +                 "command response too large: %dbyte\n", psize);
> +             return EIO;
> +     }
> +
> +     MALO_READ_MULTI_2(sc, MALO_REG_CMD_READ,
> +         (uint16_t *)sc->sc_cmd, psize / sizeof(uint16_t));
> +     if (psize & 0x0001)
> +             sc->sc_cmd[psize - 1] = MALO_READ_1(sc, MALO_REG_CMD_READ);
> +
> +     cmalo_hexdump(sc->sc_cmd, psize);
> +
> +     /*
> +      * We convert the header values into the machines correct endianess,
> +      * so we don't have to le16toh() all over the code.  The body is
> +      * kept in the cards order, little endian.  We need to take care
> +      * about the body endianess in the corresponding response routines.
> +      */
> +     hdr->cmd = le16toh(hdr->cmd);
> +     hdr->size = le16toh(hdr->size);
> +     hdr->seqnum = le16toh(hdr->seqnum);
> +     hdr->result = le16toh(hdr->result);
> +
> +     /* check for a valid command response */
> +     if (!(hdr->cmd & MALO_CMD_RESP)) {
> +             aprint_error_dev(sc->sc_dev,
> +                 "got invalid command response (0x%04x)\n", hdr->cmd);
> +             splx(s);
> +             return EIO;
> +     }
> +     hdr->cmd &= ~MALO_CMD_RESP;
> +
> +     /* association cmd response is special */
> +     if (hdr->cmd == 0x0012)
> +             hdr->cmd = MALO_CMD_ASSOC;
> +
> +     /* to which command does the response belong */
> +     switch (hdr->cmd) {
> +     case MALO_CMD_HWSPEC:
> +             DPRINTF(1, "%s: got hwspec cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             cmalo_cmd_rsp_hwspec(sc);
> +             break;
> +     case MALO_CMD_RESET:
> +             /* reset will not send back a response */
> +             break;
> +     case MALO_CMD_SCAN:
> +             DPRINTF(1, "%s: got scan cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             cmalo_cmd_rsp_scan(sc);
> +             break;
> +     case MALO_CMD_AUTH:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got auth cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     case MALO_CMD_WEP:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got wep cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     case MALO_CMD_SNMP:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got snmp cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     case MALO_CMD_RADIO:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got radio cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     case MALO_CMD_CHANNEL:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got channel cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     case MALO_CMD_TXPOWER:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got txpower cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     case MALO_CMD_ANTENNA:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got antenna cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     case MALO_CMD_MACCTRL:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got macctrl cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     case MALO_CMD_MACADDR:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got macaddr cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     case MALO_CMD_ASSOC:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got assoc cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             cmalo_cmd_rsp_assoc(sc);
> +             break;
> +     case MALO_CMD_80211D:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got 80211d cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     case MALO_CMD_BGSCAN_CONFIG:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got bgscan config cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     case MALO_CMD_BGSCAN_QUERY:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got bgscan query cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     case MALO_CMD_RATE:
> +             /* do nothing */
> +             DPRINTF(1, "%s: got rate cmd response\n",
> +                 device_xname(sc->sc_dev));
> +             break;
> +     default:
> +             aprint_error_dev(sc->sc_dev,
> +                 "got unknown cmd response (0x%04x)\n", hdr->cmd);
> +             break;
> +     }
> +
> +     splx(s);
> +
> +     return 0;
> +}
> +
> +#ifdef _MODULE
> +
> +MODULE(MODULE_CLASS_DRIVER, malo_pcmcia, NULL);
> +
> +CFDRIVER_DECL(malo_pcmcia, DV_IFNET, NULL);
> +extern struct cfattach malo_pcmcia_ca;
> +static int malo_pcmcialoc[] = { -1 };
> +static struct cfparent pcmciaparent = {
> +     "pcmcia", NULL, DVUNIT_ANY
> +};
> +static struct cfdata malo_pcmcia_cfdata[] = {
> +     {
> +             .cf_name = "malo_pcmcia",
> +             .cf_atname = "malo",
> +             .cf_unit = 0,
> +             .cf_fstate = FSTATE_STAR,
> +             .cf_loc = malo_pcmcialoc,
> +             .cf_flags = 0,
> +             .cf_pspec = &pcmciaparent,
> +     },
> +     { NULL }
> +};
> +
> +static int
> +malo_pcmcia_modcmd(modcmd_t cmd, void *arg)
> +{
> +     int err;
> +
> +     switch (cmd) {
> +     case MODULE_CMD_INIT:
> +             err = config_cfdriver_attach(&malo_pcmcia_cd);
> +             if (err)
> +                     return err;
> +             err = config_cfattach_attach("malo_pcmcia", &malo_pcmcia_ca);
> +             if (err) {
> +                     config_cfdriver_detach(&malo_pcmcia_cd);
> +                     return err;
> +             }
> +             err = config_cfdata_attach(malo_pcmcia_cfdata, 1);
> +             if (err) {
> +                     config_cfattach_detach("malo_pcmcia", &malo_pcmcia_ca);
> +                     config_cfdriver_detach(&malo_pcmcia_cd);
> +                     return err;
> +             }
> +             return 0;
> +     case MODULE_CMD_FINI:
> +             err = config_cfdata_detach(malo_pcmcia_cfdata);
> +             if (err)
> +                     return err;
> +             config_cfattach_detach("malo_pcmcia", &malo_pcmcia_ca);
> +             config_cfdriver_detach(&malo_pcmcia_cd);
> +             return 0;
> +     default:
> +             return ENOTTY;
> +     }
> +}
> +#endif
> --- if_maloreg.h.orig 1970-01-01 09:00:00.000000000 +0900
> +++ if_maloreg.h      2009-01-29 15:37:07.000000000 +0900
> @@ -0,0 +1,85 @@
> +/*   $NetBSD$        */
> +/*   $OpenBSD: if_maloreg.h,v 1.15 2007/10/08 22:08:12 mglocker Exp $ */
> +
> +/*
> + * Copyright (c) 2007 Marcus Glocker <mglocker%openbsd.org@localhost>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +/* registers */
> +#define MALO_REG_HOST_STATUS         0x00
> +#define MALO_REG_CARD_INTR_CAUSE     0x02
> +#define MALO_REG_HOST_INTR_MASK              0x04
> +#define MALO_REG_DATA_READ           0x10
> +#define MALO_REG_CMD_READ            0x12
> +#define MALO_REG_DATA_WRITE_LEN              0x14
> +#define MALO_REG_DATA_WRITE          0x16
> +#define MALO_REG_CMD_WRITE_LEN               0x18
> +#define MALO_REG_CMD_WRITE           0x1a
> +#define MALO_REG_CARD_STATUS         0x20
> +#define MALO_REG_HOST_INTR_CAUSE     0x22
> +#define MALO_REG_DATA_READ_LEN               0x24
> +#define MALO_REG_RBAL                        0x28
> +#define MALO_REG_CMD_READ_LEN                0x30
> +#define MALO_REG_SCRATCH             0x3f
> +#define MALO_REG_CARD_INTR_MASK              0x44
> +
> +/* register values */
> +#define MALO_VAL_SCRATCH_READY               0x00
> +#define MALO_VAL_TX_DL_OVER          0x01
> +#define MALO_VAL_RX_DL_OVER          0x02
> +#define MALO_VAL_CMD_DL_OVER         0x04
> +#define MALO_VAL_SCRATCH_FW_LOADED   0x5a
> +#define MALO_VAL_HOST_INTR_MASK_ON   0x001f
> +#define MALO_VAL_CARD_STATUS_MASK    0x7f00
> +
> +/* interrupt reasons */
> +#define MALO_VAL_HOST_INTR_TX                (1 << 0)
> +#define MALO_VAL_HOST_INTR_RX                (1 << 1)
> +#define MALO_VAL_HOST_INTR_CMD               (1 << 3)
> +#define MALO_VAL_HOST_INTR_EVENT     (1 << 4)
> +
> +/* FW commands */
> +#define MALO_CMD_RESP                        0x8000
> +#define MALO_CMD_HWSPEC                      0x0003
> +#define MALO_CMD_RESET                       0x0005
> +#define MALO_CMD_SCAN                        0x0006
> +#define MALO_CMD_AUTH                        0x0011
> +#define MALO_CMD_WEP                 0x0013
> +#define MALO_CMD_SNMP                        0x0016
> +#define MALO_CMD_RADIO                       0x001c
> +#define MALO_CMD_CHANNEL             0x001d
> +#define MALO_CMD_TXPOWER             0x001e
> +#define MALO_CMD_ANTENNA             0x0020
> +#define MALO_CMD_MACCTRL             0x0028
> +#define MALO_CMD_MACADDR             0x004d
> +#define MALO_CMD_ASSOC                       0x0050
> +#define MALO_CMD_80211D                      0x005b
> +#define MALO_CMD_BGSCAN_CONFIG               0x006b
> +#define MALO_CMD_BGSCAN_QUERY                0x006c
> +#define MALO_CMD_RATE                        0x0076
> +
> +/* FW command values */
> +#define MALO_CMD_RADIO_OFF           0x0000
> +#define MALO_CMD_RADIO_ON            0x0001
> +#define MALO_CMD_RADIO_LONG_P                0x0000
> +#define MALO_CMD_RADIO_SHORT_P               0x0002
> +#define MALO_CMD_RADIO_AUTO_P                0x0004
> +#define MALO_CMD_MACCTRL_RX_ON               0x0001
> +#define MALO_CMD_MACCTRL_TX_ON               0x0002
> +#define MALO_CMD_MACCTRL_PROMISC_ON  0x0080
> +
> +/* events */
> +#define MALO_EVENT_DEAUTH            0x0008
> +#define MALO_EVENT_DISASSOC          0x0009
> --- if_malovar.h.orig 1970-01-01 09:00:00.000000000 +0900
> +++ if_malovar.h      2009-12-06 17:36:04.000000000 +0900
> @@ -0,0 +1,395 @@
> +/*   $NetBSD$        */
> +/*   $OpenBSD: if_malovar.h,v 1.27 2007/10/09 20:37:32 mglocker Exp $ */
> +
> +/*
> + * Copyright (c) 2007 Marcus Glocker <mglocker%openbsd.org@localhost>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +/* simplify bus space access */
> +#define MALO_READ_1(sc, reg) \
> +     bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (reg))
> +#define MALO_READ_2(sc, reg) \
> +     bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, (reg))
> +#ifdef       __BUS_SPACE_HAS_STREAM_METHODS
> +#define      MALO_READ_MULTI_2(sc, reg, off, size) \
> +     bus_space_read_multi_stream_2((sc)->sc_iot, (sc)->sc_ioh, (reg), (off), 
> (size))
> +#else
> +#if _BYTE_ORDER == _LITTLE_ENDIAN
> +#define      MALO_READ_MULTI_2(sc, reg, off, size) \
> +     bus_space_read_multi_2((sc)->sc_iot, (sc)->sc_ioh, (reg), (off), (size))
> +#else
> +#error not support bus_space_write_multi_stream_2()
> +#endif
> +#endif
> +#define MALO_WRITE_1(sc, reg, val) \
> +     bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
> +#define MALO_WRITE_2(sc, reg, val) \
> +     bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
> +#ifdef       __BUS_SPACE_HAS_STREAM_METHODS
> +#define MALO_WRITE_MULTI_2(sc, reg, off, size) \
> +     bus_space_write_multi_stream_2((sc)->sc_iot, (sc)->sc_ioh, (reg), 
> (off), (size))
> +#else
> +#if _BYTE_ORDER == _LITTLE_ENDIAN
> +#define MALO_WRITE_MULTI_2(sc, reg, off, size) \
> +     bus_space_write_multi_2((sc)->sc_iot, (sc)->sc_ioh, (reg), (off), 
> (size))
> +#else
> +#error not support bus_space_write_multi_stream_2()
> +#endif
> +#endif
> +
> +/* miscellaneous */
> +#define MALO_FW_HELPER_BSIZE 256     /* helper FW block size */
> +#define MALO_FW_HELPER_LOADED        0x10    /* helper FW loaded */
> +#define MALO_FW_MAIN_MAXRETRY        20      /* main FW block resend max 
> retry */
> +#define MALO_CMD_BUFFER_SIZE 4096    /* cmd buffer */
> +#define MALO_DATA_BUFFER_SIZE        4096    /* data buffer */
> +
> +/* device flags */
> +#define MALO_DEVICE_ATTACHED (1 << 0)
> +#define MALO_DEVICE_ENABLED  (1 << 1)
> +#define MALO_FW_LOADED               (1 << 2)
> +#define MALO_ASSOC_FAILED    (1 << 3)
> +
> +/*
> + * FW command structures
> + */
> +struct malo_cmd_header {
> +     uint16_t        cmd;
> +     uint16_t        size;
> +     uint16_t        seqnum;
> +     uint16_t        result;
> +     /* malo_cmd_body */
> +};
> +
> +struct malo_cmd_body_spec {
> +     uint16_t        hw_if_version;
> +     uint16_t        hw_version;
> +     uint16_t        num_of_wcb;
> +     uint16_t        num_of_mcast;
> +     uint8_t         macaddr[ETHER_ADDR_LEN];
> +     uint16_t        regioncode;
> +     uint16_t        num_of_antenna;
> +     uint32_t        fw_version;
> +     uint32_t        wcbbase;
> +     uint32_t        rxpdrdptr;
> +     uint32_t        rxpdwrptr;
> +     uint32_t        fw_capinfo;
> +} __packed;
> +
> +struct malo_cmd_body_scan {
> +     uint8_t         bsstype;
> +     uint8_t         bssid[ETHER_ADDR_LEN];
> +     /* malo_cmd_tlv_ssid */
> +     /* malo_cmd_tlv_chanlist */
> +     /* malo_cmd_tlv_rates */
> +     /* malo_cmd_tlv_numprobes */
> +} __packed;
> +
> +struct malo_cmd_body_rsp_scan {
> +     uint16_t        bufsize;
> +     uint8_t         numofset;
> +} __packed;
> +struct malo_cmd_body_rsp_scan_set {
> +     uint16_t        size;
> +     uint8_t         bssid[ETHER_ADDR_LEN];
> +     uint8_t         rssi;
> +     uint8_t         timestamp[8];
> +     uint16_t        beaconintvl;
> +     uint16_t        capinfo;
> +     uint8_t         data[0];
> +} __packed;
> +
> +struct malo_cmd_body_auth {
> +     uint8_t         peermac[ETHER_ADDR_LEN];
> +     uint8_t         authtype;
> +} __packed;
> +
> +#define MALO_WEP_ACTION_TYPE_ADD     0x02
> +#define MALO_WEP_ACTION_TYPE_REMOVE  0x04
> +#define MALO_WEP_ACTION_TYPE_DEFAULT 0x08
> +#define MALO_WEP_KEY_TYPE_40BIT              0x01
> +#define MALO_WEP_KEY_TYPE_104BIT     0x02
> +struct malo_cmd_body_wep {
> +     uint16_t        action;
> +     uint16_t        key_index;
> +     uint8_t         key_type_1;
> +     uint8_t         key_type_2;
> +     uint8_t         key_type_3;
> +     uint8_t         key_type_4;
> +     uint8_t         key_value_1[16];
> +     uint8_t         key_value_2[16];
> +     uint8_t         key_value_3[16];
> +     uint8_t         key_value_4[16];
> +} __packed;
> +
> +#define MALO_OID_BSS         0x00
> +#define MALO_OID_RATE                0x01
> +#define MALO_OID_BCNPERIOD   0x02
> +#define MALO_OID_DTIMPERIOD  0x03
> +#define MALO_OID_ASSOCTIMEOUT        0x04
> +#define MALO_OID_RTSTRESH    0x05
> +#define MALO_OID_SHORTRETRY  0x06
> +#define MALO_OID_LONGRETRY   0x07
> +#define MALO_OID_FRAGTRESH   0x08
> +#define MALO_OID_80211D              0x09
> +#define MALO_OID_80211H              0x0a
> +struct malo_cmd_body_snmp {
> +     uint16_t        action;
> +     uint16_t        oid;
> +     uint16_t        size;
> +     uint8_t         data[128];
> +} __packed;
> +
> +struct malo_cmd_body_radio {
> +     uint16_t        action;
> +     uint16_t        control;
> +} __packed;
> +
> +struct malo_cmd_body_channel {
> +     uint16_t        action;
> +     uint16_t        channel;
> +     uint16_t        rftype;
> +     uint16_t        reserved;
> +     uint8_t         channel_list[32];
> +} __packed;
> +
> +struct malo_cmd_body_txpower {
> +     uint16_t        action;
> +     int16_t         txpower;        
> +} __packed;
> +
> +struct malo_cmd_body_antenna {
> +     uint16_t        action;
> +     uint16_t        antenna_mode;
> +} __packed;
> +
> +struct malo_cmd_body_macctrl {
> +     uint16_t        action;
> +     uint16_t        reserved;
> +} __packed;
> +
> +struct malo_cmd_body_macaddr {
> +     uint16_t        action;
> +     uint8_t         macaddr[ETHER_ADDR_LEN];
> +} __packed;
> +
> +struct malo_cmd_body_assoc {
> +     uint8_t         peermac[ETHER_ADDR_LEN];
> +     uint16_t        capinfo;
> +     uint16_t        listenintrv;
> +     uint16_t        bcnperiod;
> +     uint8_t         dtimperiod;
> +     /* malo_cmd_tlv_ssid */
> +     /* malo_cmd_tlv_phy */
> +     /* malo_cmd_tlv_cf */
> +     /* malo_cmd_tlv_rate */
> +} __packed;
> +
> +struct malo_cmd_body_rsp_assoc {
> +     uint16_t        capinfo;
> +     uint16_t        status;
> +     uint16_t        assoc_id;
> +     uint16_t        info_len;
> +     /* uint8_t      info[270] */
> +} __packed;
> +
> +struct malo_cmd_body_80211d {
> +     uint16_t        action;
> +     /* malo_cmd_tlv_80211d */
> +} __packed;
> +
> +struct malo_cmd_body_bgscan_config {
> +     uint16_t        action;
> +     uint8_t         enable;
> +     uint8_t         bsstype;
> +     uint8_t         chperscan;
> +     uint8_t         discard;
> +     uint16_t        reserved;
> +     uint32_t        scanintvl;
> +     uint32_t        storecond;
> +     uint32_t        reportcond;
> +     uint16_t        maxscanres;
> +} __packed;
> +
> +struct malo_cmd_body_bgscan_query {
> +     uint8_t         flush;
> +} __packed;
> +
> +#define MALO_RATE_BITMAP_DS1 (1 << 0)
> +#define MALO_RATE_BITMAP_DS2 (1 << 1)
> +#define MALO_RATE_BITMAP_DS5 (1 << 2)
> +#define MALO_RATE_BITMAP_DS11        (1 << 3)
> +#define MALO_RATE_BITMAP_OFDM6       (1 << 5)
> +#define MALO_RATE_BITMAP_OFDM9       (1 << 6)
> +#define MALO_RATE_BITMAP_OFDM12      (1 << 7)
> +#define MALO_RATE_BITMAP_OFDM18      (1 << 8)
> +#define MALO_RATE_BITMAP_OFDM24      (1 << 9)
> +#define MALO_RATE_BITMAP_OFDM36      (1 << 10)
> +#define MALO_RATE_BITMAP_OFDM48      (1 << 11)
> +#define MALO_RATE_BITMAP_OFDM54      (1 << 12)
> +#define MALO_RATE_BITMAP_AUTO        0x1fef
> +struct malo_cmd_body_rate {
> +     uint16_t        action;
> +     uint16_t        hwauto;
> +     uint16_t        ratebitmap;
> +} __packed;
> +
> +/*
> + * FW command TLV structures
> + */
> +#define MALO_TLV_TYPE_SSID   0x0000
> +#define MALO_TLV_TYPE_RATES  0x0001
> +#define MALO_TLV_TYPE_PHY    0x0003
> +#define MALO_TLV_TYPE_CF     0x0004
> +#define MALO_TLV_TYPE_80211D 0x0007
> +#define MALO_TLV_TYPE_CHANLIST       0x0101
> +#define MALO_TLV_TYPE_NUMPROBES      0x0102
> +#define MALO_TLV_TYPE_PASSEID        0x010a
> +
> +struct malo_cmd_tlv_ssid {
> +     uint16_t        type;
> +     uint16_t        size;
> +     uint8_t         data[0];
> +} __packed;
> +
> +struct malo_cmd_tlv_rates {
> +     uint16_t        type;
> +     uint16_t        size;
> +     uint8_t         data[0];
> +} __packed;
> +
> +struct malo_cmd_tlv_phy {
> +     uint16_t        type;
> +     uint16_t        size;
> +     uint8_t         data[0];
> +} __packed;
> +
> +struct malo_cmd_tlv_cf {
> +     uint16_t        type;
> +     uint16_t        size;
> +     uint8_t         data[0];
> +} __packed;
> +
> +struct malo_cmd_tlv_80211d_param {
> +     uint8_t         firstchannel;
> +     uint8_t         numchannels;
> +     uint8_t         maxtxpower;
> +} __packed;
> +struct malo_cmd_tlv_80211d {
> +     uint16_t        type;
> +     uint16_t        size;
> +     uint8_t         countrycode[3];
> +     struct malo_cmd_tlv_80211d_param data[12];
> +} __packed;
> +
> +struct malo_cmd_tlv_chanlist_param {
> +     uint8_t         radiotype;
> +     uint8_t         channumber;
> +     uint8_t         scantype;
> +     uint16_t        minscantime;
> +     uint16_t        maxscantime;
> +} __packed;
> +#define CHANNELS     12
> +struct malo_cmd_tlv_chanlist {
> +     uint16_t        type;
> +     uint16_t        size;
> +     struct malo_cmd_tlv_chanlist_param data[CHANNELS];
> +} __packed;
> +
> +struct malo_cmd_tlv_numprobes {
> +     uint16_t        type;
> +     uint16_t        size;
> +     uint16_t        numprobes;
> +} __packed;
> +
> +struct malo_cmd_tlv_passeid {
> +     uint16_t        type;
> +     uint16_t        size;
> +     uint8_t         data[0];
> +} __packed;
> +
> +/* RX descriptor */
> +#define MALO_RX_STATUS_OK    0x0001
> +struct malo_rx_desc {
> +     uint16_t        status;
> +     uint8_t         snr;
> +     uint8_t         control;
> +     uint16_t        pkglen;
> +     uint8_t         nf;
> +     uint8_t         rate;
> +     uint32_t        pkgoffset;
> +     uint32_t        reserved1;
> +     uint8_t         priority;
> +     uint8_t         reserved2[3];
> +} __packed;
> +
> +/* TX descriptor */
> +struct malo_tx_desc {
> +     uint32_t        status;
> +     uint32_t        control;
> +     uint32_t        pkgoffset;
> +     uint16_t        pkglen;
> +     uint8_t         dstaddrhigh[2];
> +     uint8_t         dstaddrlow[4];
> +     uint8_t         priority;
> +     uint8_t         flags;
> +     uint8_t         reserved[2];
> +} __packed;
> +
> +/* scanned network */
> +struct malo_networks {
> +     uint8_t         bssid[ETHER_ADDR_LEN];
> +     uint8_t         rssi;
> +     uint8_t         timestamp[8];
> +     uint16_t        beaconintvl;
> +     uint16_t        capinfo;
> +     uint8_t         ssid[32];
> +     uint8_t         rates[14];
> +     uint8_t         channel;
> +} __packed;
> +
> +/*
> + * Softc
> + */
> +struct malo_softc {
> +     device_t                 sc_dev;
> +     struct ethercom          sc_ec;
> +#define sc_if        sc_ec.ec_if
> +     struct ieee80211com      sc_ic;
> +     bus_space_tag_t          sc_iot;
> +     bus_space_handle_t       sc_ioh;
> +     int                      (*sc_newstate)
> +                              (struct ieee80211com *, enum ieee80211_state,
> +                                  int);
> +
> +     int                      sc_flags;
> +     uint8_t                 *sc_fw_h;
> +     uint8_t                 *sc_fw_m;
> +     size_t                   sc_fw_h_size;
> +     size_t                   sc_fw_m_size;
> +     int                      sc_cmd_ctxsave;
> +     uint8_t                 *sc_cmd;
> +     uint8_t                 *sc_data;
> +     uint8_t                  sc_curchan;
> +     int                      sc_net_num;
> +     int                      sc_net_cur;
> +     struct malo_networks     sc_net[12];
> +     callout_t                sc_scan_ch;
> +#if NBPFILTER > 0
> +     void                    *sc_drvbpf;
> +#endif
> +     kcondvar_t               sc_cv;
> +     kmutex_t                 sc_mtx;
> +};


-- 
Arnaud Degroote
PhD Student 
RIA LAAS / CNRS

Attachment: signature.asc
Description: Digital signature



Home | Main Index | Thread Index | Old Index