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