[BACK]Return to if_malo.c CVS log [TXT][DIR] Up to [local] / sys / dev / pcmcia

Annotation of sys/dev/pcmcia/if_malo.c, Revision 1.1.1.1

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

CVSweb