tech-kern archive

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

malo@pci vs malo@pcmcia



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.

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.  :-)

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;
+};


Home | Main Index | Thread Index | Old Index