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

Annotation of sys/dev/ic/if_wi.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_wi.c,v 1.137 2006/11/26 19:46:28 deraadt Exp $     */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1997, 1998, 1999
        !             5:  *     Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *     This product includes software developed by Bill Paul.
        !            18:  * 4. Neither the name of the author nor the names of any co-contributors
        !            19:  *    may be used to endorse or promote products derived from this software
        !            20:  *    without specific prior written permission.
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
        !            23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            25:  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
        !            26:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            27:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            28:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            29:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            30:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            31:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
        !            32:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            33:  *
        !            34:  *     From: if_wi.c,v 1.7 1999/07/04 14:40:22 wpaul Exp $
        !            35:  */
        !            36:
        !            37: /*
        !            38:  * Lucent WaveLAN/IEEE 802.11 driver for OpenBSD.
        !            39:  *
        !            40:  * Originally written by Bill Paul <wpaul@ctr.columbia.edu>
        !            41:  * Electrical Engineering Department
        !            42:  * Columbia University, New York City
        !            43:  */
        !            44:
        !            45: /*
        !            46:  * The WaveLAN/IEEE adapter is the second generation of the WaveLAN
        !            47:  * from Lucent. Unlike the older cards, the new ones are programmed
        !            48:  * entirely via a firmware-driven controller called the Hermes.
        !            49:  * Unfortunately, Lucent will not release the Hermes programming manual
        !            50:  * without an NDA (if at all). What they do release is an API library
        !            51:  * called the HCF (Hardware Control Functions) which is supposed to
        !            52:  * do the device-specific operations of a device driver for you. The
        !            53:  * publicly available version of the HCF library (the 'HCF Light') is
        !            54:  * a) extremely gross, b) lacks certain features, particularly support
        !            55:  * for 802.11 frames, and c) is contaminated by the GNU Public License.
        !            56:  *
        !            57:  * This driver does not use the HCF or HCF Light at all. Instead, it
        !            58:  * programs the Hermes controller directly, using information gleaned
        !            59:  * from the HCF Light code and corresponding documentation.
        !            60:  */
        !            61:
        !            62: #define WI_HERMES_AUTOINC_WAR  /* Work around data write autoinc bug. */
        !            63: #define WI_HERMES_STATS_WAR    /* Work around stats counter bug. */
        !            64:
        !            65: #include "bpfilter.h"
        !            66:
        !            67: #include <sys/param.h>
        !            68: #include <sys/systm.h>
        !            69: #include <sys/sockio.h>
        !            70: #include <sys/mbuf.h>
        !            71: #include <sys/malloc.h>
        !            72: #include <sys/kernel.h>
        !            73: #include <sys/proc.h>
        !            74: #include <sys/socket.h>
        !            75: #include <sys/device.h>
        !            76:
        !            77: #include <net/if.h>
        !            78: #include <net/if_dl.h>
        !            79: #include <net/if_media.h>
        !            80: #include <net/if_types.h>
        !            81:
        !            82: #ifdef INET
        !            83: #include <netinet/in.h>
        !            84: #include <netinet/in_systm.h>
        !            85: #include <netinet/in_var.h>
        !            86: #include <netinet/ip.h>
        !            87: #include <netinet/if_ether.h>
        !            88: #endif
        !            89:
        !            90: #include <net80211/ieee80211_var.h>
        !            91: #include <net80211/ieee80211_ioctl.h>
        !            92:
        !            93: #if NBPFILTER > 0
        !            94: #include <net/bpf.h>
        !            95: #endif
        !            96:
        !            97: #include <machine/bus.h>
        !            98:
        !            99: #include <dev/rndvar.h>
        !           100:
        !           101: #include <dev/ic/if_wireg.h>
        !           102: #include <dev/ic/if_wi_ieee.h>
        !           103: #include <dev/ic/if_wivar.h>
        !           104:
        !           105: #include <crypto/arc4.h>
        !           106:
        !           107: #define BPFATTACH(if_bpf,if,dlt,sz)
        !           108: #define STATIC
        !           109:
        !           110: #ifdef WIDEBUG
        !           111:
        !           112: u_int32_t      widebug = WIDEBUG;
        !           113:
        !           114: #define WID_INTR       0x01
        !           115: #define WID_START      0x02
        !           116: #define WID_IOCTL      0x04
        !           117: #define WID_INIT       0x08
        !           118: #define WID_STOP       0x10
        !           119: #define WID_RESET      0x20
        !           120:
        !           121: #define DPRINTF(mask,args) if (widebug & (mask)) printf args;
        !           122:
        !           123: #else  /* !WIDEBUG */
        !           124: #define DPRINTF(mask,args)
        !           125: #endif /* WIDEBUG */
        !           126:
        !           127: #if !defined(lint) && !defined(__OpenBSD__)
        !           128: static const char rcsid[] =
        !           129:        "$OpenBSD: if_wi.c,v 1.137 2006/11/26 19:46:28 deraadt Exp $";
        !           130: #endif /* lint */
        !           131:
        !           132: #ifdef foo
        !           133: static u_int8_t        wi_mcast_addr[6] = { 0x01, 0x60, 0x1D, 0x00, 0x01, 0x00 };
        !           134: #endif
        !           135:
        !           136: STATIC void wi_reset(struct wi_softc *);
        !           137: STATIC int wi_ioctl(struct ifnet *, u_long, caddr_t);
        !           138: STATIC void wi_init_io(struct wi_softc *);
        !           139: STATIC void wi_start(struct ifnet *);
        !           140: STATIC void wi_watchdog(struct ifnet *);
        !           141: STATIC void wi_shutdown(void *);
        !           142: STATIC void wi_rxeof(struct wi_softc *);
        !           143: STATIC void wi_txeof(struct wi_softc *, int);
        !           144: STATIC void wi_update_stats(struct wi_softc *);
        !           145: STATIC void wi_setmulti(struct wi_softc *);
        !           146:
        !           147: STATIC int wi_cmd_io(struct wi_softc *, int, int, int, int);
        !           148: STATIC int wi_read_record_io(struct wi_softc *, struct wi_ltv_gen *);
        !           149: STATIC int wi_write_record_io(struct wi_softc *, struct wi_ltv_gen *);
        !           150: STATIC int wi_read_data_io(struct wi_softc *, int,
        !           151:                                        int, caddr_t, int);
        !           152: STATIC int wi_write_data_io(struct wi_softc *, int,
        !           153:                                        int, caddr_t, int);
        !           154: STATIC int wi_seek(struct wi_softc *, int, int, int);
        !           155:
        !           156: STATIC void wi_inquire(void *);
        !           157: STATIC int wi_setdef(struct wi_softc *, struct wi_req *);
        !           158: STATIC void wi_get_id(struct wi_softc *);
        !           159:
        !           160: STATIC int wi_media_change(struct ifnet *);
        !           161: STATIC void wi_media_status(struct ifnet *, struct ifmediareq *);
        !           162:
        !           163: STATIC int wi_set_ssid(struct ieee80211_nwid *, u_int8_t *, int);
        !           164: STATIC int wi_set_nwkey(struct wi_softc *, struct ieee80211_nwkey *);
        !           165: STATIC int wi_get_nwkey(struct wi_softc *, struct ieee80211_nwkey *);
        !           166: STATIC int wi_sync_media(struct wi_softc *, int, int);
        !           167: STATIC int wi_set_pm(struct wi_softc *, struct ieee80211_power *);
        !           168: STATIC int wi_get_pm(struct wi_softc *, struct ieee80211_power *);
        !           169: STATIC int wi_set_txpower(struct wi_softc *, struct ieee80211_txpower *);
        !           170: STATIC int wi_get_txpower(struct wi_softc *, struct ieee80211_txpower *);
        !           171:
        !           172: STATIC int wi_get_debug(struct wi_softc *, struct wi_req *);
        !           173: STATIC int wi_set_debug(struct wi_softc *, struct wi_req *);
        !           174:
        !           175: STATIC void wi_do_hostencrypt(struct wi_softc *, caddr_t, int);
        !           176: STATIC int wi_do_hostdecrypt(struct wi_softc *, caddr_t, int);
        !           177:
        !           178: STATIC int wi_alloc_nicmem_io(struct wi_softc *, int, int *);
        !           179: STATIC int wi_get_fid_io(struct wi_softc *sc, int fid);
        !           180: STATIC void wi_intr_enable(struct wi_softc *sc, int mode);
        !           181: STATIC void wi_intr_ack(struct wi_softc *sc, int mode);
        !           182: void    wi_scan_timeout(void *);
        !           183:
        !           184: /* Autoconfig definition of driver back-end */
        !           185: struct cfdriver wi_cd = {
        !           186:        NULL, "wi", DV_IFNET
        !           187: };
        !           188:
        !           189: const struct wi_card_ident wi_card_ident[] = {
        !           190:        WI_CARD_IDS
        !           191: };
        !           192:
        !           193: struct wi_funcs wi_func_io = {
        !           194:         wi_cmd_io,
        !           195:         wi_read_record_io,
        !           196:         wi_write_record_io,
        !           197:         wi_alloc_nicmem_io,
        !           198:         wi_read_data_io,
        !           199:         wi_write_data_io,
        !           200:         wi_get_fid_io,
        !           201:         wi_init_io,
        !           202:
        !           203:         wi_start,
        !           204:         wi_ioctl,
        !           205:         wi_watchdog,
        !           206:         wi_inquire,
        !           207: };
        !           208:
        !           209: int
        !           210: wi_attach(struct wi_softc *sc, struct wi_funcs *funcs)
        !           211: {
        !           212:        struct ieee80211com     *ic;
        !           213:        struct ifnet            *ifp;
        !           214:        struct wi_ltv_macaddr   mac;
        !           215:        struct wi_ltv_rates     rates;
        !           216:        struct wi_ltv_gen       gen;
        !           217:        int                     error;
        !           218:
        !           219:        ic = &sc->sc_ic;
        !           220:        ifp = &ic->ic_if;
        !           221:
        !           222:        sc->sc_funcs = funcs;
        !           223:        sc->wi_cmd_count = 500;
        !           224:
        !           225:        wi_reset(sc);
        !           226:
        !           227:        /* Read the station address. */
        !           228:        mac.wi_type = WI_RID_MAC_NODE;
        !           229:        mac.wi_len = 4;
        !           230:        error = wi_read_record(sc, (struct wi_ltv_gen *)&mac);
        !           231:        if (error) {
        !           232:                printf(": unable to read station address\n");
        !           233:                return (error);
        !           234:        }
        !           235:        bcopy((char *)&mac.wi_mac_addr, (char *)&ic->ic_myaddr,
        !           236:            IEEE80211_ADDR_LEN);
        !           237:
        !           238:        wi_get_id(sc);
        !           239:        printf("address %s", ether_sprintf(ic->ic_myaddr));
        !           240:
        !           241:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
        !           242:        ifp->if_softc = sc;
        !           243:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !           244:        ifp->if_ioctl = funcs->f_ioctl;
        !           245:        ifp->if_start = funcs->f_start;
        !           246:        ifp->if_watchdog = funcs->f_watchdog;
        !           247:        ifp->if_baudrate = 10000000;
        !           248:        IFQ_SET_READY(&ifp->if_snd);
        !           249:
        !           250:        (void)wi_set_ssid(&sc->wi_node_name, WI_DEFAULT_NODENAME,
        !           251:            sizeof(WI_DEFAULT_NODENAME) - 1);
        !           252:        (void)wi_set_ssid(&sc->wi_net_name, WI_DEFAULT_NETNAME,
        !           253:            sizeof(WI_DEFAULT_NETNAME) - 1);
        !           254:        (void)wi_set_ssid(&sc->wi_ibss_name, WI_DEFAULT_IBSS,
        !           255:            sizeof(WI_DEFAULT_IBSS) - 1);
        !           256:
        !           257:        sc->wi_portnum = WI_DEFAULT_PORT;
        !           258:        sc->wi_ptype = WI_PORTTYPE_BSS;
        !           259:        sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;
        !           260:        sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;
        !           261:        sc->wi_tx_rate = WI_DEFAULT_TX_RATE;
        !           262:        sc->wi_max_data_len = WI_DEFAULT_DATALEN;
        !           263:        sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;
        !           264:        sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;
        !           265:        sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;
        !           266:        sc->wi_roaming = WI_DEFAULT_ROAMING;
        !           267:        sc->wi_authtype = WI_DEFAULT_AUTHTYPE;
        !           268:        sc->wi_diversity = WI_DEFAULT_DIVERSITY;
        !           269:        sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP;
        !           270:
        !           271:        /*
        !           272:         * Read the default channel from the NIC. This may vary
        !           273:         * depending on the country where the NIC was purchased, so
        !           274:         * we can't hard-code a default and expect it to work for
        !           275:         * everyone.
        !           276:         */
        !           277:        gen.wi_type = WI_RID_OWN_CHNL;
        !           278:        gen.wi_len = 2;
        !           279:        if (wi_read_record(sc, &gen) == 0)
        !           280:                sc->wi_channel = letoh16(gen.wi_val);
        !           281:        else
        !           282:                sc->wi_channel = 3;
        !           283:
        !           284:        /*
        !           285:         * Set flags based on firmware version.
        !           286:         */
        !           287:        switch (sc->sc_firmware_type) {
        !           288:        case WI_LUCENT:
        !           289:                sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
        !           290:                if (sc->sc_sta_firmware_ver >= 60000)
        !           291:                        sc->wi_flags |= WI_FLAGS_HAS_MOR;
        !           292:                if (sc->sc_sta_firmware_ver >= 60006) {
        !           293:                        sc->wi_flags |= WI_FLAGS_HAS_IBSS;
        !           294:                        sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
        !           295:                }
        !           296:                sc->wi_ibss_port = htole16(1);
        !           297:                break;
        !           298:        case WI_INTERSIL:
        !           299:                sc->wi_flags |= WI_FLAGS_HAS_ROAMING;
        !           300:                /* older prism firmware is slow so crank the count */
        !           301:                if (sc->sc_sta_firmware_ver < 10000)
        !           302:                        sc->wi_cmd_count = 5000;
        !           303:                else
        !           304:                        sc->wi_cmd_count = 2000;
        !           305:                if (sc->sc_sta_firmware_ver >= 800) {
        !           306: #ifndef SMALL_KERNEL
        !           307:                        /*
        !           308:                         * USB hostap is more pain than it is worth
        !           309:                         * for now, things would have to be overhauled
        !           310:                         */
        !           311:                        if ((sc->sc_sta_firmware_ver != 10402) &&
        !           312:                            (!(sc->wi_flags & WI_FLAGS_BUS_USB)))
        !           313:                                sc->wi_flags |= WI_FLAGS_HAS_HOSTAP;
        !           314: #endif
        !           315:                        sc->wi_flags |= WI_FLAGS_HAS_IBSS;
        !           316:                        sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
        !           317:                }
        !           318:                if (sc->sc_sta_firmware_ver >= 10603)
        !           319:                        sc->wi_flags |= WI_FLAGS_HAS_ENH_SECURITY;
        !           320:                sc->wi_ibss_port = htole16(0);
        !           321:                break;
        !           322:        case WI_SYMBOL:
        !           323:                sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY;
        !           324:                if (sc->sc_sta_firmware_ver >= 20000)
        !           325:                        sc->wi_flags |= WI_FLAGS_HAS_IBSS;
        !           326:                if (sc->sc_sta_firmware_ver >= 25000)
        !           327:                        sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;
        !           328:                sc->wi_ibss_port = htole16(4);
        !           329:                break;
        !           330:        }
        !           331:
        !           332:        /*
        !           333:         * Find out if we support WEP on this card.
        !           334:         */
        !           335:        gen.wi_type = WI_RID_WEP_AVAIL;
        !           336:        gen.wi_len = 2;
        !           337:        if (wi_read_record(sc, &gen) == 0 && gen.wi_val != htole16(0))
        !           338:                sc->wi_flags |= WI_FLAGS_HAS_WEP;
        !           339:        timeout_set(&sc->sc_timo, funcs->f_inquire, sc);
        !           340:
        !           341:        bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
        !           342:
        !           343:        /* Find supported rates. */
        !           344:        rates.wi_type = WI_RID_DATA_RATES;
        !           345:        rates.wi_len = sizeof(rates.wi_rates);
        !           346:        if (wi_read_record(sc, (struct wi_ltv_gen *)&rates) == 0) {
        !           347:                int i, nrates;
        !           348:
        !           349:                nrates = letoh16(*(u_int16_t *)rates.wi_rates);
        !           350:                if (nrates > sizeof(rates.wi_rates) - 2)
        !           351:                        nrates = sizeof(rates.wi_rates) - 2;
        !           352:
        !           353:                sc->wi_supprates = 0;
        !           354:                for (i = 0; i < nrates; i++)
        !           355:                        sc->wi_supprates |= rates.wi_rates[2 + i];
        !           356:        } else
        !           357:                sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |
        !           358:                    WI_SUPPRATES_5M | WI_SUPPRATES_11M;
        !           359:
        !           360:        ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);
        !           361: #define        ADD(m, c)       ifmedia_add(&sc->sc_media, (m), (c), NULL)
        !           362:        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);
        !           363:        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);
        !           364:        if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
        !           365:                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,
        !           366:                    0), 0);
        !           367:        if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
        !           368:                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
        !           369:                    IFM_IEEE80211_IBSSMASTER, 0), 0);
        !           370:        if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
        !           371:                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,
        !           372:                    IFM_IEEE80211_HOSTAP, 0), 0);
        !           373:        if (sc->wi_supprates & WI_SUPPRATES_1M) {
        !           374:                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);
        !           375:                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
        !           376:                    IFM_IEEE80211_ADHOC, 0), 0);
        !           377:                if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
        !           378:                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
        !           379:                            IFM_IEEE80211_IBSS, 0), 0);
        !           380:                if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
        !           381:                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
        !           382:                            IFM_IEEE80211_IBSSMASTER, 0), 0);
        !           383:                if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
        !           384:                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,
        !           385:                            IFM_IEEE80211_HOSTAP, 0), 0);
        !           386:        }
        !           387:        if (sc->wi_supprates & WI_SUPPRATES_2M) {
        !           388:                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
        !           389:                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
        !           390:                    IFM_IEEE80211_ADHOC, 0), 0);
        !           391:                if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
        !           392:                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
        !           393:                            IFM_IEEE80211_IBSS, 0), 0);
        !           394:                if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
        !           395:                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
        !           396:                            IFM_IEEE80211_IBSSMASTER, 0), 0);
        !           397:                if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
        !           398:                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
        !           399:                            IFM_IEEE80211_HOSTAP, 0), 0);
        !           400:        }
        !           401:        if (sc->wi_supprates & WI_SUPPRATES_5M) {
        !           402:                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
        !           403:                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
        !           404:                    IFM_IEEE80211_ADHOC, 0), 0);
        !           405:                if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
        !           406:                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
        !           407:                            IFM_IEEE80211_IBSS, 0), 0);
        !           408:                if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
        !           409:                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
        !           410:                            IFM_IEEE80211_IBSSMASTER, 0), 0);
        !           411:                if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
        !           412:                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
        !           413:                            IFM_IEEE80211_HOSTAP, 0), 0);
        !           414:        }
        !           415:        if (sc->wi_supprates & WI_SUPPRATES_11M) {
        !           416:                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
        !           417:                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
        !           418:                    IFM_IEEE80211_ADHOC, 0), 0);
        !           419:                if (sc->wi_flags & WI_FLAGS_HAS_IBSS)
        !           420:                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
        !           421:                            IFM_IEEE80211_IBSS, 0), 0);
        !           422:                if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)
        !           423:                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
        !           424:                            IFM_IEEE80211_IBSSMASTER, 0), 0);
        !           425:                if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)
        !           426:                        ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
        !           427:                            IFM_IEEE80211_HOSTAP, 0), 0);
        !           428:                ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);
        !           429:        }
        !           430: #undef ADD
        !           431:        ifmedia_set(&sc->sc_media,
        !           432:            IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));
        !           433:
        !           434:        /*
        !           435:         * Call MI attach routines.
        !           436:         */
        !           437:        if_attach(ifp);
        !           438:        memcpy(((struct arpcom *)ifp)->ac_enaddr, ic->ic_myaddr,
        !           439:            ETHER_ADDR_LEN);
        !           440:        ether_ifattach(ifp);
        !           441:        printf("\n");
        !           442:
        !           443:        sc->wi_flags |= WI_FLAGS_ATTACHED;
        !           444:
        !           445: #if NBPFILTER > 0
        !           446:        BPFATTACH(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
        !           447: #endif
        !           448:
        !           449:        sc->sc_sdhook = shutdownhook_establish(wi_shutdown, sc);
        !           450:
        !           451:        wi_init(sc);
        !           452:        wi_stop(sc);
        !           453:
        !           454:        return (0);
        !           455: }
        !           456:
        !           457: STATIC void
        !           458: wi_intr_enable(struct wi_softc *sc, int mode)
        !           459: {
        !           460:        if (!(sc->wi_flags & WI_FLAGS_BUS_USB))
        !           461:                CSR_WRITE_2(sc, WI_INT_EN, mode);
        !           462: }
        !           463:
        !           464: STATIC void
        !           465: wi_intr_ack(struct wi_softc *sc, int mode)
        !           466: {
        !           467:        if (!(sc->wi_flags & WI_FLAGS_BUS_USB))
        !           468:                CSR_WRITE_2(sc, WI_EVENT_ACK, mode);
        !           469: }
        !           470:
        !           471: int
        !           472: wi_intr(void *vsc)
        !           473: {
        !           474:        struct wi_softc         *sc = vsc;
        !           475:        struct ifnet            *ifp;
        !           476:        u_int16_t               status;
        !           477:
        !           478:        DPRINTF(WID_INTR, ("wi_intr: sc %p\n", sc));
        !           479:
        !           480:        ifp = &sc->sc_ic.ic_if;
        !           481:
        !           482:        if (!(sc->wi_flags & WI_FLAGS_ATTACHED) || !(ifp->if_flags & IFF_UP)) {
        !           483:                CSR_WRITE_2(sc, WI_INT_EN, 0);
        !           484:                CSR_WRITE_2(sc, WI_EVENT_ACK, 0xffff);
        !           485:                return (0);
        !           486:        }
        !           487:
        !           488:        /* Disable interrupts. */
        !           489:        CSR_WRITE_2(sc, WI_INT_EN, 0);
        !           490:
        !           491:        status = CSR_READ_2(sc, WI_EVENT_STAT);
        !           492:        CSR_WRITE_2(sc, WI_EVENT_ACK, ~WI_INTRS);
        !           493:
        !           494:        if (status & WI_EV_RX) {
        !           495:                wi_rxeof(sc);
        !           496:                CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
        !           497:        }
        !           498:
        !           499:        if (status & WI_EV_TX) {
        !           500:                wi_txeof(sc, status);
        !           501:                CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX);
        !           502:        }
        !           503:
        !           504:        if (status & WI_EV_ALLOC) {
        !           505:                int                     id;
        !           506:                id = CSR_READ_2(sc, WI_ALLOC_FID);
        !           507:                CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
        !           508:                if (id == sc->wi_tx_data_id)
        !           509:                        wi_txeof(sc, status);
        !           510:        }
        !           511:
        !           512:        if (status & WI_EV_INFO) {
        !           513:                wi_update_stats(sc);
        !           514:                CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
        !           515:        }
        !           516:
        !           517:        if (status & WI_EV_TX_EXC) {
        !           518:                wi_txeof(sc, status);
        !           519:                CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
        !           520:        }
        !           521:
        !           522:        if (status & WI_EV_INFO_DROP) {
        !           523:                CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO_DROP);
        !           524:        }
        !           525:
        !           526:        /* Re-enable interrupts. */
        !           527:        CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
        !           528:
        !           529:        if (!IFQ_IS_EMPTY(&ifp->if_snd))
        !           530:                wi_start(ifp);
        !           531:
        !           532:        return (1);
        !           533: }
        !           534:
        !           535: STATIC int
        !           536: wi_get_fid_io(struct wi_softc *sc, int fid)
        !           537: {
        !           538:        return CSR_READ_2(sc, fid);
        !           539: }
        !           540:
        !           541:
        !           542: void
        !           543: wi_rxeof(struct wi_softc *sc)
        !           544: {
        !           545:        struct ifnet            *ifp;
        !           546:        struct ether_header     *eh;
        !           547:        struct mbuf             *m;
        !           548:        caddr_t                 olddata;
        !           549:        u_int16_t               ftype;
        !           550:        int                     maxlen;
        !           551:        int                     id;
        !           552:
        !           553:        ifp = &sc->sc_ic.ic_if;
        !           554:
        !           555:        id = wi_get_fid(sc, WI_RX_FID);
        !           556:
        !           557:        if (sc->wi_procframe || sc->wi_debug.wi_monitor) {
        !           558:                struct wi_frame *rx_frame;
        !           559:                int             datlen, hdrlen;
        !           560:
        !           561:                MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           562:                if (m == NULL) {
        !           563:                        ifp->if_ierrors++;
        !           564:                        return;
        !           565:                }
        !           566:                MCLGET(m, M_DONTWAIT);
        !           567:                if (!(m->m_flags & M_EXT)) {
        !           568:                        m_freem(m);
        !           569:                        ifp->if_ierrors++;
        !           570:                        return;
        !           571:                }
        !           572:
        !           573:                m->m_pkthdr.rcvif = ifp;
        !           574:
        !           575:                if (wi_read_data(sc, id, 0, mtod(m, caddr_t),
        !           576:                    sizeof(struct wi_frame))) {
        !           577:                        m_freem(m);
        !           578:                        ifp->if_ierrors++;
        !           579:                        return;
        !           580:                }
        !           581:
        !           582:                rx_frame = mtod(m, struct wi_frame *);
        !           583:
        !           584:                if (rx_frame->wi_status & htole16(WI_STAT_BADCRC)) {
        !           585:                        m_freem(m);
        !           586:                        ifp->if_ierrors++;
        !           587:                        return;
        !           588:                }
        !           589:
        !           590:                switch ((letoh16(rx_frame->wi_status) & WI_STAT_MAC_PORT)
        !           591:                    >> 8) {
        !           592:                case 7:
        !           593:                        switch (letoh16(rx_frame->wi_frame_ctl) &
        !           594:                            WI_FCTL_FTYPE) {
        !           595:                        case WI_FTYPE_DATA:
        !           596:                                hdrlen = WI_DATA_HDRLEN;
        !           597:                                datlen = letoh16(rx_frame->wi_dat_len);
        !           598:                                break;
        !           599:                        case WI_FTYPE_MGMT:
        !           600:                                hdrlen = WI_MGMT_HDRLEN;
        !           601:                                datlen = letoh16(rx_frame->wi_dat_len);
        !           602:                                break;
        !           603:                        case WI_FTYPE_CTL:
        !           604:                                hdrlen = WI_CTL_HDRLEN;
        !           605:                                datlen = 0;
        !           606:                                break;
        !           607:                        default:
        !           608:                                printf(WI_PRT_FMT ": received packet of "
        !           609:                                    "unknown type on port 7\n", WI_PRT_ARG(sc));
        !           610:                                m_freem(m);
        !           611:                                ifp->if_ierrors++;
        !           612:                                return;
        !           613:                        }
        !           614:                        break;
        !           615:                case 0:
        !           616:                        hdrlen = WI_DATA_HDRLEN;
        !           617:                        datlen = letoh16(rx_frame->wi_dat_len);
        !           618:                        break;
        !           619:                default:
        !           620:                        printf(WI_PRT_FMT ": received packet on invalid port "
        !           621:                            "(wi_status=0x%x)\n", WI_PRT_ARG(sc),
        !           622:                            letoh16(rx_frame->wi_status));
        !           623:                        m_freem(m);
        !           624:                        ifp->if_ierrors++;
        !           625:                        return;
        !           626:                }
        !           627:
        !           628:                if ((hdrlen + datlen + 2) > MCLBYTES) {
        !           629:                        m_freem(m);
        !           630:                        ifp->if_ierrors++;
        !           631:                        return;
        !           632:                }
        !           633:
        !           634:                if (wi_read_data(sc, id, hdrlen, mtod(m, caddr_t) + hdrlen,
        !           635:                    datlen + 2)) {
        !           636:                        m_freem(m);
        !           637:                        ifp->if_ierrors++;
        !           638:                        return;
        !           639:                }
        !           640:
        !           641:                m->m_pkthdr.len = m->m_len = hdrlen + datlen;
        !           642:        } else {
        !           643:                struct wi_frame rx_frame;
        !           644:
        !           645:                /* First read in the frame header */
        !           646:                if (wi_read_data(sc, id, 0, (caddr_t)&rx_frame,
        !           647:                    sizeof(rx_frame))) {
        !           648:                        ifp->if_ierrors++;
        !           649:                        return;
        !           650:                }
        !           651:
        !           652:                /* Drop undecryptable or packets with receive errors here */
        !           653:                if (rx_frame.wi_status & htole16(WI_STAT_ERRSTAT)) {
        !           654:                        ifp->if_ierrors++;
        !           655:                        return;
        !           656:                }
        !           657:
        !           658:                /* Stash frame type in host byte order for later use */
        !           659:                ftype = letoh16(rx_frame.wi_frame_ctl) & WI_FCTL_FTYPE;
        !           660:
        !           661:                MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           662:                if (m == NULL) {
        !           663:                        ifp->if_ierrors++;
        !           664:                        return;
        !           665:                }
        !           666:                MCLGET(m, M_DONTWAIT);
        !           667:                if (!(m->m_flags & M_EXT)) {
        !           668:                        m_freem(m);
        !           669:                        ifp->if_ierrors++;
        !           670:                        return;
        !           671:                }
        !           672:
        !           673:                olddata = m->m_data;
        !           674:                /* Align the data after the ethernet header */
        !           675:                m->m_data = (caddr_t)ALIGN(m->m_data +
        !           676:                    sizeof(struct ether_header)) - sizeof(struct ether_header);
        !           677:
        !           678:                eh = mtod(m, struct ether_header *);
        !           679:                maxlen = MCLBYTES - (m->m_data - olddata);
        !           680:                m->m_pkthdr.rcvif = ifp;
        !           681:
        !           682:                if (ftype == WI_FTYPE_MGMT &&
        !           683:                    sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
        !           684:
        !           685:                        u_int16_t rxlen = letoh16(rx_frame.wi_dat_len);
        !           686:
        !           687:                        if ((WI_802_11_OFFSET_RAW + rxlen + 2) > maxlen) {
        !           688:                                printf("%s: oversized mgmt packet received in "
        !           689:                                    "hostap mode (wi_dat_len=%d, "
        !           690:                                    "wi_status=0x%x)\n", sc->sc_dev.dv_xname,
        !           691:                                    rxlen, letoh16(rx_frame.wi_status));
        !           692:                                m_freem(m);
        !           693:                                ifp->if_ierrors++;
        !           694:                                return;
        !           695:                        }
        !           696:
        !           697:                        /* Put the whole header in there. */
        !           698:                        bcopy(&rx_frame, mtod(m, void *),
        !           699:                            sizeof(struct wi_frame));
        !           700:                        if (wi_read_data(sc, id, WI_802_11_OFFSET_RAW,
        !           701:                            mtod(m, caddr_t) + WI_802_11_OFFSET_RAW,
        !           702:                            rxlen + 2)) {
        !           703:                                m_freem(m);
        !           704:                                if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
        !           705:                                        printf("wihap: failed to copy header\n");
        !           706:                                ifp->if_ierrors++;
        !           707:                                return;
        !           708:                        }
        !           709:
        !           710:                        m->m_pkthdr.len = m->m_len =
        !           711:                            WI_802_11_OFFSET_RAW + rxlen;
        !           712:
        !           713:                        /* XXX: consider giving packet to bhp? */
        !           714:
        !           715:                        wihap_mgmt_input(sc, &rx_frame, m);
        !           716:
        !           717:                        return;
        !           718:                }
        !           719:
        !           720:                switch (letoh16(rx_frame.wi_status) & WI_RXSTAT_MSG_TYPE) {
        !           721:                case WI_STAT_1042:
        !           722:                case WI_STAT_TUNNEL:
        !           723:                case WI_STAT_WMP_MSG:
        !           724:                        if ((letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN) >
        !           725:                            maxlen) {
        !           726:                                printf(WI_PRT_FMT ": oversized packet received "
        !           727:                                    "(wi_dat_len=%d, wi_status=0x%x)\n",
        !           728:                                    WI_PRT_ARG(sc),
        !           729:                                    letoh16(rx_frame.wi_dat_len),
        !           730:                                    letoh16(rx_frame.wi_status));
        !           731:                                m_freem(m);
        !           732:                                ifp->if_ierrors++;
        !           733:                                return;
        !           734:                        }
        !           735:                        m->m_pkthdr.len = m->m_len =
        !           736:                            letoh16(rx_frame.wi_dat_len) + WI_SNAPHDR_LEN;
        !           737:
        !           738:                        bcopy((char *)&rx_frame.wi_dst_addr,
        !           739:                            (char *)&eh->ether_dhost, ETHER_ADDR_LEN);
        !           740:                        bcopy((char *)&rx_frame.wi_src_addr,
        !           741:                            (char *)&eh->ether_shost, ETHER_ADDR_LEN);
        !           742:                        bcopy((char *)&rx_frame.wi_type,
        !           743:                            (char *)&eh->ether_type, ETHER_TYPE_LEN);
        !           744:
        !           745:                        if (wi_read_data(sc, id, WI_802_11_OFFSET,
        !           746:                            mtod(m, caddr_t) + sizeof(struct ether_header),
        !           747:                            m->m_len + 2)) {
        !           748:                                ifp->if_ierrors++;
        !           749:                                m_freem(m);
        !           750:                                return;
        !           751:                        }
        !           752:                        break;
        !           753:                default:
        !           754:                        if ((letoh16(rx_frame.wi_dat_len) +
        !           755:                            sizeof(struct ether_header)) > maxlen) {
        !           756:                                printf(WI_PRT_FMT ": oversized packet received "
        !           757:                                    "(wi_dat_len=%d, wi_status=0x%x)\n",
        !           758:                                    WI_PRT_ARG(sc),
        !           759:                                    letoh16(rx_frame.wi_dat_len),
        !           760:                                    letoh16(rx_frame.wi_status));
        !           761:                                m_freem(m);
        !           762:                                ifp->if_ierrors++;
        !           763:                                return;
        !           764:                        }
        !           765:                        m->m_pkthdr.len = m->m_len =
        !           766:                            letoh16(rx_frame.wi_dat_len) +
        !           767:                            sizeof(struct ether_header);
        !           768:
        !           769:                        if (wi_read_data(sc, id, WI_802_3_OFFSET,
        !           770:                            mtod(m, caddr_t), m->m_len + 2)) {
        !           771:                                m_freem(m);
        !           772:                                ifp->if_ierrors++;
        !           773:                                return;
        !           774:                        }
        !           775:                        break;
        !           776:                }
        !           777:
        !           778:                ifp->if_ipackets++;
        !           779:
        !           780:                if (sc->wi_use_wep &&
        !           781:                    rx_frame.wi_frame_ctl & htole16(WI_FCTL_WEP)) {
        !           782:                        int len;
        !           783:
        !           784:                        switch (sc->wi_crypto_algorithm) {
        !           785:                        case WI_CRYPTO_FIRMWARE_WEP:
        !           786:                                break;
        !           787:                        case WI_CRYPTO_SOFTWARE_WEP:
        !           788:                                m_copydata(m, 0, m->m_pkthdr.len,
        !           789:                                    (caddr_t)sc->wi_rxbuf);
        !           790:                                len = m->m_pkthdr.len -
        !           791:                                    sizeof(struct ether_header);
        !           792:                                if (wi_do_hostdecrypt(sc, sc->wi_rxbuf +
        !           793:                                    sizeof(struct ether_header), len)) {
        !           794:                                        if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
        !           795:                                                printf(WI_PRT_FMT ": Error decrypting incoming packet.\n", WI_PRT_ARG(sc));
        !           796:                                        m_freem(m);
        !           797:                                        ifp->if_ierrors++;
        !           798:                                        return;
        !           799:                                }
        !           800:                                len -= IEEE80211_WEP_IVLEN +
        !           801:                                    IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
        !           802:                                /*
        !           803:                                 * copy data back to mbufs:
        !           804:                                 * we need to ditch the IV & most LLC/SNAP stuff
        !           805:                                 * (except SNAP type, we're going use that to
        !           806:                                 * overwrite the ethertype in the ether_header)
        !           807:                                 */
        !           808:                                m_copyback(m, sizeof(struct ether_header) -
        !           809:                                    WI_ETHERTYPE_LEN, WI_ETHERTYPE_LEN +
        !           810:                                    (len - WI_SNAPHDR_LEN),
        !           811:                                    sc->wi_rxbuf + sizeof(struct ether_header) +
        !           812:                                    IEEE80211_WEP_IVLEN +
        !           813:                                    IEEE80211_WEP_KIDLEN + WI_SNAPHDR_LEN);
        !           814:                                m_adj(m, -(WI_ETHERTYPE_LEN +
        !           815:                                    IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
        !           816:                                    WI_SNAPHDR_LEN));
        !           817:                                break;
        !           818:                        }
        !           819:                }
        !           820:
        !           821:                if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
        !           822:                        /*
        !           823:                         * Give host AP code first crack at data packets.
        !           824:                         * If it decides to handle it (or drop it), it will
        !           825:                         * return a non-zero.  Otherwise, it is destined for
        !           826:                         * this host.
        !           827:                         */
        !           828:                        if (wihap_data_input(sc, &rx_frame, m))
        !           829:                                return;
        !           830:                }
        !           831:        }
        !           832:
        !           833: #if NBPFILTER > 0
        !           834:        /* Handle BPF listeners. */
        !           835:        if (ifp->if_bpf)
        !           836:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !           837: #endif
        !           838:
        !           839:        /* Receive packet unless in procframe or monitor mode. */
        !           840:        if (sc->wi_procframe || sc->wi_debug.wi_monitor)
        !           841:                m_freem(m);
        !           842:        else
        !           843:                ether_input_mbuf(ifp, m);
        !           844:
        !           845:        return;
        !           846: }
        !           847:
        !           848: void
        !           849: wi_txeof(struct wi_softc *sc, int status)
        !           850: {
        !           851:        struct ifnet            *ifp;
        !           852:
        !           853:        ifp = &sc->sc_ic.ic_if;
        !           854:
        !           855:        ifp->if_timer = 0;
        !           856:        ifp->if_flags &= ~IFF_OACTIVE;
        !           857:
        !           858:        if (status & WI_EV_TX_EXC)
        !           859:                ifp->if_oerrors++;
        !           860:        else
        !           861:                ifp->if_opackets++;
        !           862:
        !           863:        return;
        !           864: }
        !           865:
        !           866: void
        !           867: wi_inquire(void *xsc)
        !           868: {
        !           869:        struct wi_softc         *sc;
        !           870:        struct ifnet            *ifp;
        !           871:        int s, rv;
        !           872:
        !           873:        sc = xsc;
        !           874:        ifp = &sc->sc_ic.ic_if;
        !           875:
        !           876:        timeout_add(&sc->sc_timo, hz * 60);
        !           877:
        !           878:        /* Don't do this while we're transmitting */
        !           879:        if (ifp->if_flags & IFF_OACTIVE)
        !           880:                return;
        !           881:
        !           882:        s = splnet();
        !           883:        rv = wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_COUNTERS, 0, 0);
        !           884:        splx(s);
        !           885:        if (rv)
        !           886:                printf(WI_PRT_FMT ": wi_cmd failed with %d\n", WI_PRT_ARG(sc),
        !           887:                    rv);
        !           888:
        !           889:        return;
        !           890: }
        !           891:
        !           892: void
        !           893: wi_update_stats(struct wi_softc *sc)
        !           894: {
        !           895:        struct wi_ltv_gen       gen;
        !           896:        u_int16_t               id;
        !           897:        struct ifnet            *ifp;
        !           898:        u_int32_t               *ptr;
        !           899:        int                     len, i;
        !           900:        u_int16_t               t;
        !           901:
        !           902:        ifp = &sc->sc_ic.ic_if;
        !           903:
        !           904:        id = wi_get_fid(sc, WI_INFO_FID);
        !           905:
        !           906:        wi_read_data(sc, id, 0, (char *)&gen, 4);
        !           907:
        !           908:        if (gen.wi_type == htole16(WI_INFO_SCAN_RESULTS)) {
        !           909:                sc->wi_scanbuf_len = letoh16(gen.wi_len);
        !           910:                wi_read_data(sc, id, 4, (caddr_t)sc->wi_scanbuf,
        !           911:                    sc->wi_scanbuf_len * 2);
        !           912:                return;
        !           913:        } else if (gen.wi_type != htole16(WI_INFO_COUNTERS))
        !           914:                return;
        !           915:
        !           916:        /* Some card versions have a larger stats structure */
        !           917:        len = (letoh16(gen.wi_len) - 1 < sizeof(sc->wi_stats) / 4) ?
        !           918:            letoh16(gen.wi_len) - 1 : sizeof(sc->wi_stats) / 4;
        !           919:
        !           920:        ptr = (u_int32_t *)&sc->wi_stats;
        !           921:
        !           922:        for (i = 0; i < len; i++) {
        !           923:                if (sc->wi_flags & WI_FLAGS_BUS_USB) {
        !           924:                        wi_read_data(sc, id, 4 + i*2, (char *)&t, 2);
        !           925:                        t = letoh16(t);
        !           926:                } else
        !           927:                        t = CSR_READ_2(sc, WI_DATA1);
        !           928: #ifdef WI_HERMES_STATS_WAR
        !           929:                if (t > 0xF000)
        !           930:                        t = ~t & 0xFFFF;
        !           931: #endif
        !           932:                ptr[i] += t;
        !           933:        }
        !           934:
        !           935:        ifp->if_collisions = sc->wi_stats.wi_tx_single_retries +
        !           936:            sc->wi_stats.wi_tx_multi_retries +
        !           937:            sc->wi_stats.wi_tx_retry_limit;
        !           938:
        !           939:        return;
        !           940: }
        !           941:
        !           942: STATIC int
        !           943: wi_cmd_io(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
        !           944: {
        !           945:        int                     i, s = 0;
        !           946:
        !           947:        /* Wait for the busy bit to clear. */
        !           948:        for (i = sc->wi_cmd_count; i--; DELAY(1000)) {
        !           949:                if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
        !           950:                        break;
        !           951:        }
        !           952:        if (i < 0) {
        !           953:                if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
        !           954:                        printf(WI_PRT_FMT ": wi_cmd_io: busy bit won't clear\n",
        !           955:                            WI_PRT_ARG(sc));
        !           956:                return(ETIMEDOUT);
        !           957:        }
        !           958:
        !           959:        CSR_WRITE_2(sc, WI_PARAM0, val0);
        !           960:        CSR_WRITE_2(sc, WI_PARAM1, val1);
        !           961:        CSR_WRITE_2(sc, WI_PARAM2, val2);
        !           962:        CSR_WRITE_2(sc, WI_COMMAND, cmd);
        !           963:
        !           964:        for (i = WI_TIMEOUT; i--; DELAY(WI_DELAY)) {
        !           965:                /*
        !           966:                 * Wait for 'command complete' bit to be
        !           967:                 * set in the event status register.
        !           968:                 */
        !           969:                s = CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_CMD;
        !           970:                if (s) {
        !           971:                        /* Ack the event and read result code. */
        !           972:                        s = CSR_READ_2(sc, WI_STATUS);
        !           973:                        CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
        !           974:                        if (s & WI_STAT_CMD_RESULT)
        !           975:                                return(EIO);
        !           976:                        break;
        !           977:                }
        !           978:        }
        !           979:
        !           980:        if (i < 0) {
        !           981:                if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
        !           982:                        printf(WI_PRT_FMT
        !           983:                            ": timeout in wi_cmd 0x%04x; event status 0x%04x\n",
        !           984:                            WI_PRT_ARG(sc), cmd, s);
        !           985:                return(ETIMEDOUT);
        !           986:        }
        !           987:
        !           988:        return(0);
        !           989: }
        !           990:
        !           991: STATIC void
        !           992: wi_reset(struct wi_softc *sc)
        !           993: {
        !           994:        int error, tries = 3;
        !           995:
        !           996:        DPRINTF(WID_RESET, ("wi_reset: sc %p\n", sc));
        !           997:
        !           998:        /* Symbol firmware cannot be initialized more than once. */
        !           999:        if (sc->sc_firmware_type == WI_SYMBOL) {
        !          1000:                if (sc->wi_flags & WI_FLAGS_INITIALIZED)
        !          1001:                        return;
        !          1002:                tries = 1;
        !          1003:        }
        !          1004:
        !          1005:        for (; tries--; DELAY(WI_DELAY * 1000)) {
        !          1006:                if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0)
        !          1007:                        break;
        !          1008:        }
        !          1009:        if (tries < 0) {
        !          1010:                printf(WI_PRT_FMT ": init failed\n", WI_PRT_ARG(sc));
        !          1011:                return;
        !          1012:        }
        !          1013:        sc->wi_flags |= WI_FLAGS_INITIALIZED;
        !          1014:
        !          1015:        wi_intr_enable(sc, 0);
        !          1016:        wi_intr_ack(sc, 0xffff);
        !          1017:
        !          1018:        /* Calibrate timer. */
        !          1019:        WI_SETVAL(WI_RID_TICK_TIME, 8);
        !          1020:
        !          1021:        return;
        !          1022: }
        !          1023:
        !          1024: STATIC void
        !          1025: wi_cor_reset(struct wi_softc *sc)
        !          1026: {
        !          1027:        u_int8_t cor_value;
        !          1028:
        !          1029:        DPRINTF(WID_RESET, ("wi_cor_reset: sc %p\n", sc));
        !          1030:
        !          1031:        /*
        !          1032:         * Do a soft reset of the card; this is required for Symbol cards.
        !          1033:         * This shouldn't hurt other cards but there have been reports
        !          1034:         * of the COR reset messing up old Lucent firmware revisions so
        !          1035:         * we avoid soft reset on Lucent cards for now.
        !          1036:         */
        !          1037:        if (sc->sc_firmware_type != WI_LUCENT) {
        !          1038:                cor_value = bus_space_read_1(sc->wi_ltag, sc->wi_lhandle,
        !          1039:                    sc->wi_cor_offset);
        !          1040:                bus_space_write_1(sc->wi_ltag, sc->wi_lhandle,
        !          1041:                    sc->wi_cor_offset, (cor_value | WI_COR_SOFT_RESET));
        !          1042:                DELAY(1000);
        !          1043:                bus_space_write_1(sc->wi_ltag, sc->wi_lhandle,
        !          1044:                    sc->wi_cor_offset, (cor_value & ~WI_COR_SOFT_RESET));
        !          1045:                DELAY(1000);
        !          1046:        }
        !          1047:
        !          1048:        return;
        !          1049: }
        !          1050:
        !          1051: /*
        !          1052:  * Read an LTV record from the NIC.
        !          1053:  */
        !          1054: STATIC int
        !          1055: wi_read_record_io(struct wi_softc *sc, struct wi_ltv_gen *ltv)
        !          1056: {
        !          1057:        u_int8_t                *ptr;
        !          1058:        int                     len, code;
        !          1059:        struct wi_ltv_gen       *oltv, p2ltv;
        !          1060:
        !          1061:        if (sc->sc_firmware_type != WI_LUCENT) {
        !          1062:                oltv = ltv;
        !          1063:                switch (ltv->wi_type) {
        !          1064:                case WI_RID_ENCRYPTION:
        !          1065:                        p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
        !          1066:                        p2ltv.wi_len = 2;
        !          1067:                        ltv = &p2ltv;
        !          1068:                        break;
        !          1069:                case WI_RID_TX_CRYPT_KEY:
        !          1070:                        if (ltv->wi_val > WI_NLTV_KEYS)
        !          1071:                                return (EINVAL);
        !          1072:                        p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
        !          1073:                        p2ltv.wi_len = 2;
        !          1074:                        ltv = &p2ltv;
        !          1075:                        break;
        !          1076:                }
        !          1077:        }
        !          1078:
        !          1079:        /* Tell the NIC to enter record read mode. */
        !          1080:        if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type, 0, 0))
        !          1081:                return(EIO);
        !          1082:
        !          1083:        /* Seek to the record. */
        !          1084:        if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
        !          1085:                return(EIO);
        !          1086:
        !          1087:        /*
        !          1088:         * Read the length and record type and make sure they
        !          1089:         * match what we expect (this verifies that we have enough
        !          1090:         * room to hold all of the returned data).
        !          1091:         */
        !          1092:        len = CSR_READ_2(sc, WI_DATA1);
        !          1093:        if (len > ltv->wi_len)
        !          1094:                return(ENOSPC);
        !          1095:        code = CSR_READ_2(sc, WI_DATA1);
        !          1096:        if (code != ltv->wi_type)
        !          1097:                return(EIO);
        !          1098:
        !          1099:        ltv->wi_len = len;
        !          1100:        ltv->wi_type = code;
        !          1101:
        !          1102:        /* Now read the data. */
        !          1103:        ptr = (u_int8_t *)&ltv->wi_val;
        !          1104:        if (ltv->wi_len > 1)
        !          1105:                CSR_READ_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1)*2);
        !          1106:
        !          1107:        if (ltv->wi_type == WI_RID_PORTTYPE && sc->wi_ptype == WI_PORTTYPE_IBSS
        !          1108:            && ltv->wi_val == sc->wi_ibss_port) {
        !          1109:                /*
        !          1110:                 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
        !          1111:                 * Since Lucent uses port type 1 for BSS *and* IBSS we
        !          1112:                 * have to rely on wi_ptype to distinguish this for us.
        !          1113:                 */
        !          1114:                ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
        !          1115:        } else if (sc->sc_firmware_type != WI_LUCENT) {
        !          1116:                int v;
        !          1117:
        !          1118:                switch (oltv->wi_type) {
        !          1119:                case WI_RID_TX_RATE:
        !          1120:                case WI_RID_CUR_TX_RATE:
        !          1121:                        switch (letoh16(ltv->wi_val)) {
        !          1122:                        case 1: v = 1; break;
        !          1123:                        case 2: v = 2; break;
        !          1124:                        case 3: v = 6; break;
        !          1125:                        case 4: v = 5; break;
        !          1126:                        case 7: v = 7; break;
        !          1127:                        case 8: v = 11; break;
        !          1128:                        case 15: v = 3; break;
        !          1129:                        default: v = 0x100 + letoh16(ltv->wi_val); break;
        !          1130:                        }
        !          1131:                        oltv->wi_val = htole16(v);
        !          1132:                        break;
        !          1133:                case WI_RID_ENCRYPTION:
        !          1134:                        oltv->wi_len = 2;
        !          1135:                        if (ltv->wi_val & htole16(0x01))
        !          1136:                                oltv->wi_val = htole16(1);
        !          1137:                        else
        !          1138:                                oltv->wi_val = htole16(0);
        !          1139:                        break;
        !          1140:                case WI_RID_TX_CRYPT_KEY:
        !          1141:                case WI_RID_CNFAUTHMODE:
        !          1142:                        oltv->wi_len = 2;
        !          1143:                        oltv->wi_val = ltv->wi_val;
        !          1144:                        break;
        !          1145:                }
        !          1146:        }
        !          1147:
        !          1148:        return(0);
        !          1149: }
        !          1150:
        !          1151: /*
        !          1152:  * Same as read, except we inject data instead of reading it.
        !          1153:  */
        !          1154: STATIC int
        !          1155: wi_write_record_io(struct wi_softc *sc, struct wi_ltv_gen *ltv)
        !          1156: {
        !          1157:        u_int8_t                *ptr;
        !          1158:        u_int16_t               val = 0;
        !          1159:        int                     i;
        !          1160:        struct wi_ltv_gen       p2ltv;
        !          1161:
        !          1162:        if (ltv->wi_type == WI_RID_PORTTYPE &&
        !          1163:            letoh16(ltv->wi_val) == WI_PORTTYPE_IBSS) {
        !          1164:                /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
        !          1165:                p2ltv.wi_type = WI_RID_PORTTYPE;
        !          1166:                p2ltv.wi_len = 2;
        !          1167:                p2ltv.wi_val = sc->wi_ibss_port;
        !          1168:                ltv = &p2ltv;
        !          1169:        } else if (sc->sc_firmware_type != WI_LUCENT) {
        !          1170:                int v;
        !          1171:
        !          1172:                switch (ltv->wi_type) {
        !          1173:                case WI_RID_TX_RATE:
        !          1174:                        p2ltv.wi_type = WI_RID_TX_RATE;
        !          1175:                        p2ltv.wi_len = 2;
        !          1176:                        switch (letoh16(ltv->wi_val)) {
        !          1177:                        case 1: v = 1; break;
        !          1178:                        case 2: v = 2; break;
        !          1179:                        case 3: v = 15; break;
        !          1180:                        case 5: v = 4; break;
        !          1181:                        case 6: v = 3; break;
        !          1182:                        case 7: v = 7; break;
        !          1183:                        case 11: v = 8; break;
        !          1184:                        default: return EINVAL;
        !          1185:                        }
        !          1186:                        p2ltv.wi_val = htole16(v);
        !          1187:                        ltv = &p2ltv;
        !          1188:                        break;
        !          1189:                case WI_RID_ENCRYPTION:
        !          1190:                        p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
        !          1191:                        p2ltv.wi_len = 2;
        !          1192:                        if (ltv->wi_val & htole16(0x01)) {
        !          1193:                                val = PRIVACY_INVOKED;
        !          1194:                                /*
        !          1195:                                 * If using shared key WEP we must set the
        !          1196:                                 * EXCLUDE_UNENCRYPTED bit.  Symbol cards
        !          1197:                                 * need this bit set even when not using
        !          1198:                                 * shared key. We can't just test for
        !          1199:                                 * IEEE80211_AUTH_SHARED since Symbol cards
        !          1200:                                 * have 2 shared key modes.
        !          1201:                                 */
        !          1202:                                if (sc->wi_authtype != IEEE80211_AUTH_OPEN ||
        !          1203:                                    sc->sc_firmware_type == WI_SYMBOL)
        !          1204:                                        val |= EXCLUDE_UNENCRYPTED;
        !          1205:
        !          1206:                                switch (sc->wi_crypto_algorithm) {
        !          1207:                                case WI_CRYPTO_FIRMWARE_WEP:
        !          1208:                                        /*
        !          1209:                                         * TX encryption is broken in
        !          1210:                                         * Host AP mode.
        !          1211:                                         */
        !          1212:                                        if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
        !          1213:                                                val |= HOST_ENCRYPT;
        !          1214:                                        break;
        !          1215:                                case WI_CRYPTO_SOFTWARE_WEP:
        !          1216:                                        val |= HOST_ENCRYPT|HOST_DECRYPT;
        !          1217:                                        break;
        !          1218:                                }
        !          1219:                                p2ltv.wi_val = htole16(val);
        !          1220:                        } else
        !          1221:                                p2ltv.wi_val = htole16(HOST_ENCRYPT | HOST_DECRYPT);
        !          1222:                        ltv = &p2ltv;
        !          1223:                        break;
        !          1224:                case WI_RID_TX_CRYPT_KEY:
        !          1225:                        if (ltv->wi_val > WI_NLTV_KEYS)
        !          1226:                                return (EINVAL);
        !          1227:                        p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
        !          1228:                        p2ltv.wi_len = 2;
        !          1229:                        p2ltv.wi_val = ltv->wi_val;
        !          1230:                        ltv = &p2ltv;
        !          1231:                        break;
        !          1232:                case WI_RID_DEFLT_CRYPT_KEYS: {
        !          1233:                                int error;
        !          1234:                                int keylen;
        !          1235:                                struct wi_ltv_str ws;
        !          1236:                                struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv;
        !          1237:
        !          1238:                                keylen = wk->wi_keys[sc->wi_tx_key].wi_keylen;
        !          1239:                                keylen = letoh16(keylen);
        !          1240:
        !          1241:                                for (i = 0; i < 4; i++) {
        !          1242:                                        bzero(&ws, sizeof(ws));
        !          1243:                                        ws.wi_len = (keylen > 5) ? 8 : 4;
        !          1244:                                        ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
        !          1245:                                        bcopy(&wk->wi_keys[i].wi_keydat,
        !          1246:                                            ws.wi_str, keylen);
        !          1247:                                        error = wi_write_record(sc,
        !          1248:                                            (struct wi_ltv_gen *)&ws);
        !          1249:                                        if (error)
        !          1250:                                                return (error);
        !          1251:                                }
        !          1252:                        }
        !          1253:                        return (0);
        !          1254:                }
        !          1255:        }
        !          1256:
        !          1257:        if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
        !          1258:                return(EIO);
        !          1259:
        !          1260:        CSR_WRITE_2(sc, WI_DATA1, ltv->wi_len);
        !          1261:        CSR_WRITE_2(sc, WI_DATA1, ltv->wi_type);
        !          1262:
        !          1263:        ptr = (u_int8_t *)&ltv->wi_val;
        !          1264:        if (ltv->wi_len > 1)
        !          1265:                CSR_WRITE_RAW_2(sc, WI_DATA1, ptr, (ltv->wi_len-1) *2);
        !          1266:
        !          1267:        if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_WRITE, ltv->wi_type, 0, 0))
        !          1268:                return(EIO);
        !          1269:
        !          1270:        return(0);
        !          1271: }
        !          1272:
        !          1273: STATIC int
        !          1274: wi_seek(struct wi_softc *sc, int id, int off, int chan)
        !          1275: {
        !          1276:        int                     i;
        !          1277:        int                     selreg, offreg;
        !          1278:
        !          1279:        switch (chan) {
        !          1280:        case WI_BAP0:
        !          1281:                selreg = WI_SEL0;
        !          1282:                offreg = WI_OFF0;
        !          1283:                break;
        !          1284:        case WI_BAP1:
        !          1285:                selreg = WI_SEL1;
        !          1286:                offreg = WI_OFF1;
        !          1287:                break;
        !          1288:        default:
        !          1289:                printf(WI_PRT_FMT ": invalid data path: %x\n", WI_PRT_ARG(sc),
        !          1290:                    chan);
        !          1291:                return(EIO);
        !          1292:        }
        !          1293:
        !          1294:        CSR_WRITE_2(sc, selreg, id);
        !          1295:        CSR_WRITE_2(sc, offreg, off);
        !          1296:
        !          1297:        for (i = WI_TIMEOUT; i--; DELAY(1))
        !          1298:                if (!(CSR_READ_2(sc, offreg) & (WI_OFF_BUSY|WI_OFF_ERR)))
        !          1299:                        break;
        !          1300:
        !          1301:        if (i < 0)
        !          1302:                return(ETIMEDOUT);
        !          1303:
        !          1304:        return(0);
        !          1305: }
        !          1306:
        !          1307: STATIC int
        !          1308: wi_read_data_io(struct wi_softc *sc, int id, int off, caddr_t buf, int len)
        !          1309: {
        !          1310:        u_int8_t                *ptr;
        !          1311:
        !          1312:        if (wi_seek(sc, id, off, WI_BAP1))
        !          1313:                return(EIO);
        !          1314:
        !          1315:        ptr = (u_int8_t *)buf;
        !          1316:        CSR_READ_RAW_2(sc, WI_DATA1, ptr, len);
        !          1317:
        !          1318:        return(0);
        !          1319: }
        !          1320:
        !          1321: /*
        !          1322:  * According to the comments in the HCF Light code, there is a bug in
        !          1323:  * the Hermes (or possibly in certain Hermes firmware revisions) where
        !          1324:  * the chip's internal autoincrement counter gets thrown off during
        !          1325:  * data writes: the autoincrement is missed, causing one data word to
        !          1326:  * be overwritten and subsequent words to be written to the wrong memory
        !          1327:  * locations. The end result is that we could end up transmitting bogus
        !          1328:  * frames without realizing it. The workaround for this is to write a
        !          1329:  * couple of extra guard words after the end of the transfer, then
        !          1330:  * attempt to read then back. If we fail to locate the guard words where
        !          1331:  * we expect them, we preform the transfer over again.
        !          1332:  */
        !          1333: STATIC int
        !          1334: wi_write_data_io(struct wi_softc *sc, int id, int off, caddr_t buf, int len)
        !          1335: {
        !          1336:        u_int8_t                *ptr;
        !          1337:
        !          1338: #ifdef WI_HERMES_AUTOINC_WAR
        !          1339: again:
        !          1340: #endif
        !          1341:
        !          1342:        if (wi_seek(sc, id, off, WI_BAP0))
        !          1343:                return(EIO);
        !          1344:
        !          1345:        ptr = (u_int8_t *)buf;
        !          1346:        CSR_WRITE_RAW_2(sc, WI_DATA0, ptr, len);
        !          1347:
        !          1348: #ifdef WI_HERMES_AUTOINC_WAR
        !          1349:        CSR_WRITE_2(sc, WI_DATA0, 0x1234);
        !          1350:        CSR_WRITE_2(sc, WI_DATA0, 0x5678);
        !          1351:
        !          1352:        if (wi_seek(sc, id, off + len, WI_BAP0))
        !          1353:                return(EIO);
        !          1354:
        !          1355:        if (CSR_READ_2(sc, WI_DATA0) != 0x1234 ||
        !          1356:            CSR_READ_2(sc, WI_DATA0) != 0x5678)
        !          1357:                goto again;
        !          1358: #endif
        !          1359:
        !          1360:        return(0);
        !          1361: }
        !          1362:
        !          1363: /*
        !          1364:  * Allocate a region of memory inside the NIC and zero
        !          1365:  * it out.
        !          1366:  */
        !          1367: STATIC int
        !          1368: wi_alloc_nicmem_io(struct wi_softc *sc, int len, int *id)
        !          1369: {
        !          1370:        int                     i;
        !          1371:
        !          1372:        if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
        !          1373:                printf(WI_PRT_FMT ": failed to allocate %d bytes on NIC\n",
        !          1374:                    WI_PRT_ARG(sc), len);
        !          1375:                return(ENOMEM);
        !          1376:        }
        !          1377:
        !          1378:        for (i = WI_TIMEOUT; i--; DELAY(1)) {
        !          1379:                if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC)
        !          1380:                        break;
        !          1381:        }
        !          1382:
        !          1383:        if (i < 0)
        !          1384:                return(ETIMEDOUT);
        !          1385:
        !          1386:        *id = CSR_READ_2(sc, WI_ALLOC_FID);
        !          1387:        CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
        !          1388:
        !          1389:        if (wi_seek(sc, *id, 0, WI_BAP0))
        !          1390:                return(EIO);
        !          1391:
        !          1392:        for (i = 0; i < len / 2; i++)
        !          1393:                CSR_WRITE_2(sc, WI_DATA0, 0);
        !          1394:
        !          1395:        return(0);
        !          1396: }
        !          1397:
        !          1398: STATIC void
        !          1399: wi_setmulti(struct wi_softc *sc)
        !          1400: {
        !          1401:        struct ifnet            *ifp;
        !          1402:        int                     i = 0;
        !          1403:        struct wi_ltv_mcast     mcast;
        !          1404:        struct ether_multistep  step;
        !          1405:        struct ether_multi      *enm;
        !          1406:
        !          1407:        ifp = &sc->sc_ic.ic_if;
        !          1408:
        !          1409:        bzero((char *)&mcast, sizeof(mcast));
        !          1410:
        !          1411:        mcast.wi_type = WI_RID_MCAST_LIST;
        !          1412:        mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
        !          1413:
        !          1414: allmulti:
        !          1415:        if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
        !          1416:                wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
        !          1417:                return;
        !          1418:        }
        !          1419:
        !          1420:        ETHER_FIRST_MULTI(step, &sc->sc_ic.ic_ac, enm);
        !          1421:        while (enm != NULL) {
        !          1422:                if (i >= 16) {
        !          1423:                        bzero((char *)&mcast, sizeof(mcast));
        !          1424:                        break;
        !          1425:                }
        !          1426:
        !          1427:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
        !          1428:                        ifp->if_flags |= IFF_ALLMULTI;
        !          1429:                        goto allmulti;
        !          1430:                }
        !          1431:                bcopy(enm->enm_addrlo, (char *)&mcast.wi_mcast[i],
        !          1432:                    ETHER_ADDR_LEN);
        !          1433:                i++;
        !          1434:                ETHER_NEXT_MULTI(step, enm);
        !          1435:        }
        !          1436:
        !          1437:        mcast.wi_len = (i * 3) + 1;
        !          1438:        wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
        !          1439:
        !          1440:        return;
        !          1441: }
        !          1442:
        !          1443: STATIC int
        !          1444: wi_setdef(struct wi_softc *sc, struct wi_req *wreq)
        !          1445: {
        !          1446:        struct ifnet            *ifp;
        !          1447:        int error = 0;
        !          1448:
        !          1449:        ifp = &sc->sc_ic.ic_if;
        !          1450:
        !          1451:        switch(wreq->wi_type) {
        !          1452:        case WI_RID_MAC_NODE:
        !          1453:                bcopy((char *)&wreq->wi_val, LLADDR(ifp->if_sadl),
        !          1454:                    ETHER_ADDR_LEN);
        !          1455:                bcopy((char *)&wreq->wi_val, (char *)&sc->sc_ic.ic_myaddr,
        !          1456:                    ETHER_ADDR_LEN);
        !          1457:                break;
        !          1458:        case WI_RID_PORTTYPE:
        !          1459:                error = wi_sync_media(sc, letoh16(wreq->wi_val[0]),
        !          1460:                    sc->wi_tx_rate);
        !          1461:                break;
        !          1462:        case WI_RID_TX_RATE:
        !          1463:                error = wi_sync_media(sc, sc->wi_ptype,
        !          1464:                    letoh16(wreq->wi_val[0]));
        !          1465:                break;
        !          1466:        case WI_RID_MAX_DATALEN:
        !          1467:                sc->wi_max_data_len = letoh16(wreq->wi_val[0]);
        !          1468:                break;
        !          1469:        case WI_RID_RTS_THRESH:
        !          1470:                sc->wi_rts_thresh = letoh16(wreq->wi_val[0]);
        !          1471:                break;
        !          1472:        case WI_RID_SYSTEM_SCALE:
        !          1473:                sc->wi_ap_density = letoh16(wreq->wi_val[0]);
        !          1474:                break;
        !          1475:        case WI_RID_CREATE_IBSS:
        !          1476:                sc->wi_create_ibss = letoh16(wreq->wi_val[0]);
        !          1477:                error = wi_sync_media(sc, sc->wi_ptype, sc->wi_tx_rate);
        !          1478:                break;
        !          1479:        case WI_RID_OWN_CHNL:
        !          1480:                sc->wi_channel = letoh16(wreq->wi_val[0]);
        !          1481:                break;
        !          1482:        case WI_RID_NODENAME:
        !          1483:                error = wi_set_ssid(&sc->wi_node_name,
        !          1484:                    (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
        !          1485:                break;
        !          1486:        case WI_RID_DESIRED_SSID:
        !          1487:                error = wi_set_ssid(&sc->wi_net_name,
        !          1488:                    (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
        !          1489:                break;
        !          1490:        case WI_RID_OWN_SSID:
        !          1491:                error = wi_set_ssid(&sc->wi_ibss_name,
        !          1492:                    (u_int8_t *)&wreq->wi_val[1], letoh16(wreq->wi_val[0]));
        !          1493:                break;
        !          1494:        case WI_RID_PM_ENABLED:
        !          1495:                sc->wi_pm_enabled = letoh16(wreq->wi_val[0]);
        !          1496:                break;
        !          1497:        case WI_RID_MICROWAVE_OVEN:
        !          1498:                sc->wi_mor_enabled = letoh16(wreq->wi_val[0]);
        !          1499:                break;
        !          1500:        case WI_RID_MAX_SLEEP:
        !          1501:                sc->wi_max_sleep = letoh16(wreq->wi_val[0]);
        !          1502:                break;
        !          1503:        case WI_RID_CNFAUTHMODE:
        !          1504:                sc->wi_authtype = letoh16(wreq->wi_val[0]);
        !          1505:                break;
        !          1506:        case WI_RID_ROAMING_MODE:
        !          1507:                sc->wi_roaming = letoh16(wreq->wi_val[0]);
        !          1508:                break;
        !          1509:        case WI_RID_SYMBOL_DIVERSITY:
        !          1510:                sc->wi_diversity = letoh16(wreq->wi_val[0]);
        !          1511:                break;
        !          1512:        case WI_RID_ENH_SECURITY:
        !          1513:                sc->wi_enh_security = letoh16(wreq->wi_val[0]);
        !          1514:                break;
        !          1515:        case WI_RID_ENCRYPTION:
        !          1516:                sc->wi_use_wep = letoh16(wreq->wi_val[0]);
        !          1517:                break;
        !          1518:        case WI_RID_TX_CRYPT_KEY:
        !          1519:                sc->wi_tx_key = letoh16(wreq->wi_val[0]);
        !          1520:                break;
        !          1521:        case WI_RID_DEFLT_CRYPT_KEYS:
        !          1522:                bcopy((char *)wreq, (char *)&sc->wi_keys,
        !          1523:                    sizeof(struct wi_ltv_keys));
        !          1524:                break;
        !          1525:        case WI_FRID_CRYPTO_ALG:
        !          1526:                switch (letoh16(wreq->wi_val[0])) {
        !          1527:                case WI_CRYPTO_FIRMWARE_WEP:
        !          1528:                        sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP;
        !          1529:                        break;
        !          1530:                case WI_CRYPTO_SOFTWARE_WEP:
        !          1531:                        sc->wi_crypto_algorithm = WI_CRYPTO_SOFTWARE_WEP;
        !          1532:                        break;
        !          1533:                default:
        !          1534:                        printf(WI_PRT_FMT ": unsupported crypto algorithm %d\n",
        !          1535:                            WI_PRT_ARG(sc), letoh16(wreq->wi_val[0]));
        !          1536:                        error = EINVAL;
        !          1537:                }
        !          1538:                break;
        !          1539:        default:
        !          1540:                error = EINVAL;
        !          1541:                break;
        !          1542:        }
        !          1543:
        !          1544:        return (error);
        !          1545: }
        !          1546:
        !          1547: STATIC int
        !          1548: wi_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
        !          1549: {
        !          1550:        int                     s, error = 0, i, j, len;
        !          1551:        struct wi_softc         *sc;
        !          1552:        struct ifreq            *ifr;
        !          1553:        struct proc             *p = curproc;
        !          1554:        struct ifaddr           *ifa = (struct ifaddr *)data;
        !          1555:        struct wi_scan_res      *res;
        !          1556:        struct wi_scan_p2_hdr   *p2;
        !          1557:        struct wi_req           *wreq = NULL;
        !          1558:        u_int32_t               flags;
        !          1559:
        !          1560:        struct ieee80211_nwid           *nwidp = NULL;
        !          1561:        struct ieee80211_nodereq_all    *na;
        !          1562:        struct ieee80211_bssid          *bssid;
        !          1563:
        !          1564:        s = splnet();
        !          1565:
        !          1566:        sc = ifp->if_softc;
        !          1567:        ifr = (struct ifreq *)data;
        !          1568:
        !          1569:        if (!(sc->wi_flags & WI_FLAGS_ATTACHED)) {
        !          1570:                splx(s);
        !          1571:                return(ENODEV);
        !          1572:        }
        !          1573:
        !          1574:        DPRINTF (WID_IOCTL, ("wi_ioctl: command %lu data %p\n",
        !          1575:            command, data));
        !          1576:
        !          1577:        if ((error = ether_ioctl(ifp, &sc->sc_ic.ic_ac, command, data)) > 0) {
        !          1578:                splx(s);
        !          1579:                return error;
        !          1580:        }
        !          1581:
        !          1582:        switch(command) {
        !          1583:        case SIOCSIFADDR:
        !          1584:                ifp->if_flags |= IFF_UP;
        !          1585:                switch (ifa->ifa_addr->sa_family) {
        !          1586: #ifdef INET
        !          1587:                case AF_INET:
        !          1588:                        wi_init(sc);
        !          1589:                        arp_ifinit(&sc->sc_ic.ic_ac, ifa);
        !          1590:                        break;
        !          1591: #endif /* INET */
        !          1592:                default:
        !          1593:                        wi_init(sc);
        !          1594:                        break;
        !          1595:                }
        !          1596:                break;
        !          1597:
        !          1598:        case SIOCSIFMTU:
        !          1599:                if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
        !          1600:                        error = EINVAL;
        !          1601:                } else if (ifp->if_mtu != ifr->ifr_mtu) {
        !          1602:                        ifp->if_mtu = ifr->ifr_mtu;
        !          1603:                }
        !          1604:                break;
        !          1605:
        !          1606:        case SIOCSIFFLAGS:
        !          1607:                if (ifp->if_flags & IFF_UP) {
        !          1608:                        if (ifp->if_flags & IFF_RUNNING &&
        !          1609:                            ifp->if_flags & IFF_PROMISC &&
        !          1610:                            !(sc->wi_if_flags & IFF_PROMISC)) {
        !          1611:                                if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
        !          1612:                                        WI_SETVAL(WI_RID_PROMISC, 1);
        !          1613:                        } else if (ifp->if_flags & IFF_RUNNING &&
        !          1614:                            !(ifp->if_flags & IFF_PROMISC) &&
        !          1615:                            sc->wi_if_flags & IFF_PROMISC) {
        !          1616:                                if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
        !          1617:                                        WI_SETVAL(WI_RID_PROMISC, 0);
        !          1618:                        } else
        !          1619:                                wi_init(sc);
        !          1620:                } else if (ifp->if_flags & IFF_RUNNING)
        !          1621:                        wi_stop(sc);
        !          1622:                sc->wi_if_flags = ifp->if_flags;
        !          1623:                error = 0;
        !          1624:                break;
        !          1625:        case SIOCADDMULTI:
        !          1626:        case SIOCDELMULTI:
        !          1627:                /* Update our multicast list. */
        !          1628:                error = (command == SIOCADDMULTI) ?
        !          1629:                    ether_addmulti(ifr, &sc->sc_ic.ic_ac) :
        !          1630:                    ether_delmulti(ifr, &sc->sc_ic.ic_ac);
        !          1631:
        !          1632:                if (error == ENETRESET) {
        !          1633:                        /*
        !          1634:                         * Multicast list has changed; set the hardware filter
        !          1635:                         * accordingly.
        !          1636:                         */
        !          1637:                        if (ifp->if_flags & IFF_RUNNING)
        !          1638:                                wi_setmulti(sc);
        !          1639:                        error = 0;
        !          1640:                }
        !          1641:                break;
        !          1642:        case SIOCSIFMEDIA:
        !          1643:        case SIOCGIFMEDIA:
        !          1644:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, command);
        !          1645:                break;
        !          1646:        case SIOCGWAVELAN:
        !          1647:                wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
        !          1648:                bzero(wreq, sizeof(*wreq));
        !          1649:                error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
        !          1650:                if (error)
        !          1651:                        break;
        !          1652:                if (wreq->wi_len > WI_MAX_DATALEN) {
        !          1653:                        error = EINVAL;
        !          1654:                        break;
        !          1655:                }
        !          1656:                switch (wreq->wi_type) {
        !          1657:                case WI_RID_IFACE_STATS:
        !          1658:                        /* XXX native byte order */
        !          1659:                        bcopy((char *)&sc->wi_stats, (char *)&wreq->wi_val,
        !          1660:                            sizeof(sc->wi_stats));
        !          1661:                        wreq->wi_len = (sizeof(sc->wi_stats) / 2) + 1;
        !          1662:                        break;
        !          1663:                case WI_RID_DEFLT_CRYPT_KEYS:
        !          1664:                        /* For non-root user, return all-zeroes keys */
        !          1665:                        if (suser(p, 0))
        !          1666:                                bzero(wreq, sizeof(struct wi_ltv_keys));
        !          1667:                        else
        !          1668:                                bcopy((char *)&sc->wi_keys, wreq,
        !          1669:                                        sizeof(struct wi_ltv_keys));
        !          1670:                        break;
        !          1671:                case WI_RID_PROCFRAME:
        !          1672:                        wreq->wi_len = 2;
        !          1673:                        wreq->wi_val[0] = htole16(sc->wi_procframe);
        !          1674:                        break;
        !          1675:                case WI_RID_PRISM2:
        !          1676:                        wreq->wi_len = 2;
        !          1677:                        wreq->wi_val[0] = htole16(sc->sc_firmware_type ==
        !          1678:                            WI_LUCENT ? 0 : 1);
        !          1679:                        break;
        !          1680:                case WI_FRID_CRYPTO_ALG:
        !          1681:                        wreq->wi_val[0] =
        !          1682:                            htole16((u_int16_t)sc->wi_crypto_algorithm);
        !          1683:                        wreq->wi_len = 1;
        !          1684:                        break;
        !          1685:                case WI_RID_SCAN_RES:
        !          1686:                        if (sc->sc_firmware_type == WI_LUCENT) {
        !          1687:                                memcpy((char *)wreq->wi_val,
        !          1688:                                    (char *)sc->wi_scanbuf,
        !          1689:                                    sc->wi_scanbuf_len * 2);
        !          1690:                                wreq->wi_len = sc->wi_scanbuf_len;
        !          1691:                                break;
        !          1692:                        }
        !          1693:                        /* FALLTHROUGH */
        !          1694:                default:
        !          1695:                        if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
        !          1696:                                error = EINVAL;
        !          1697:                        }
        !          1698:                        break;
        !          1699:                }
        !          1700:                error = copyout(wreq, ifr->ifr_data, sizeof(*wreq));
        !          1701:                break;
        !          1702:        case SIOCSWAVELAN:
        !          1703:                if ((error = suser(curproc, 0)) != 0)
        !          1704:                        break;
        !          1705:                wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
        !          1706:                bzero(wreq, sizeof(*wreq));
        !          1707:                error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
        !          1708:                if (error)
        !          1709:                        break;
        !          1710:                error = EINVAL;
        !          1711:                if (wreq->wi_len > WI_MAX_DATALEN)
        !          1712:                        break;
        !          1713:                switch (wreq->wi_type) {
        !          1714:                case WI_RID_IFACE_STATS:
        !          1715:                        break;
        !          1716:                case WI_RID_MGMT_XMIT:
        !          1717:                        error = wi_mgmt_xmit(sc, (caddr_t)&wreq->wi_val,
        !          1718:                            wreq->wi_len);
        !          1719:                        break;
        !          1720:                case WI_RID_PROCFRAME:
        !          1721:                        sc->wi_procframe = letoh16(wreq->wi_val[0]);
        !          1722:                        error = 0;
        !          1723:                        break;
        !          1724:                case WI_RID_SCAN_REQ:
        !          1725:                        error = 0;
        !          1726:                        if (sc->sc_firmware_type == WI_LUCENT)
        !          1727:                                wi_cmd(sc, WI_CMD_INQUIRE,
        !          1728:                                    WI_INFO_SCAN_RESULTS, 0, 0);
        !          1729:                        else
        !          1730:                                error = wi_write_record(sc,
        !          1731:                                    (struct wi_ltv_gen *)wreq);
        !          1732:                        break;
        !          1733:                case WI_FRID_CRYPTO_ALG:
        !          1734:                        if (sc->sc_firmware_type != WI_LUCENT) {
        !          1735:                                error = wi_setdef(sc, wreq);
        !          1736:                                if (!error && (ifp->if_flags & IFF_UP))
        !          1737:                                        wi_init(sc);
        !          1738:                        }
        !          1739:                        break;
        !          1740:                case WI_RID_SYMBOL_DIVERSITY:
        !          1741:                case WI_RID_ROAMING_MODE:
        !          1742:                case WI_RID_CREATE_IBSS:
        !          1743:                case WI_RID_MICROWAVE_OVEN:
        !          1744:                case WI_RID_OWN_SSID:
        !          1745:                case WI_RID_ENH_SECURITY:
        !          1746:                        /*
        !          1747:                         * Check for features that may not be supported
        !          1748:                         * (must be just before default case).
        !          1749:                         */
        !          1750:                        if ((wreq->wi_type == WI_RID_SYMBOL_DIVERSITY &&
        !          1751:                            !(sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)) ||
        !          1752:                            (wreq->wi_type == WI_RID_ROAMING_MODE &&
        !          1753:                            !(sc->wi_flags & WI_FLAGS_HAS_ROAMING)) ||
        !          1754:                            (wreq->wi_type == WI_RID_CREATE_IBSS &&
        !          1755:                            !(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)) ||
        !          1756:                            (wreq->wi_type == WI_RID_MICROWAVE_OVEN &&
        !          1757:                            !(sc->wi_flags & WI_FLAGS_HAS_MOR)) ||
        !          1758:                            (wreq->wi_type == WI_RID_ENH_SECURITY &&
        !          1759:                            !(sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY)) ||
        !          1760:                            (wreq->wi_type == WI_RID_OWN_SSID &&
        !          1761:                            wreq->wi_len != 0))
        !          1762:                                break;
        !          1763:                        /* FALLTHROUGH */
        !          1764:                default:
        !          1765:                        error = wi_write_record(sc, (struct wi_ltv_gen *)wreq);
        !          1766:                        if (!error)
        !          1767:                                error = wi_setdef(sc, wreq);
        !          1768:                        if (!error && (ifp->if_flags & IFF_UP))
        !          1769:                                wi_init(sc);
        !          1770:                }
        !          1771:                break;
        !          1772:        case SIOCGPRISM2DEBUG:
        !          1773:                wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
        !          1774:                bzero(wreq, sizeof(*wreq));
        !          1775:                error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
        !          1776:                if (error)
        !          1777:                        break;
        !          1778:                if (!(ifp->if_flags & IFF_RUNNING) ||
        !          1779:                    sc->sc_firmware_type == WI_LUCENT) {
        !          1780:                        error = EIO;
        !          1781:                        break;
        !          1782:                }
        !          1783:                error = wi_get_debug(sc, wreq);
        !          1784:                if (error == 0)
        !          1785:                        error = copyout(wreq, ifr->ifr_data, sizeof(*wreq));
        !          1786:                break;
        !          1787:        case SIOCSPRISM2DEBUG:
        !          1788:                if ((error = suser(curproc, 0)) != 0)
        !          1789:                        break;
        !          1790:                wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
        !          1791:                bzero(wreq, sizeof(*wreq));
        !          1792:                error = copyin(ifr->ifr_data, wreq, sizeof(*wreq));
        !          1793:                if (error)
        !          1794:                        break;
        !          1795:                error = wi_set_debug(sc, wreq);
        !          1796:                break;
        !          1797:        case SIOCG80211NWID:
        !          1798:                if ((ifp->if_flags & IFF_UP) && sc->wi_net_name.i_len > 0) {
        !          1799:                        /* Return the desired ID */
        !          1800:                        error = copyout(&sc->wi_net_name, ifr->ifr_data,
        !          1801:                            sizeof(sc->wi_net_name));
        !          1802:                } else {
        !          1803:                        wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
        !          1804:                        bzero(wreq, sizeof(*wreq));
        !          1805:                        wreq->wi_type = WI_RID_CURRENT_SSID;
        !          1806:                        wreq->wi_len = WI_MAX_DATALEN;
        !          1807:                        if (wi_read_record(sc, (struct wi_ltv_gen *)wreq) ||
        !          1808:                            letoh16(wreq->wi_val[0]) > IEEE80211_NWID_LEN)
        !          1809:                                error = EINVAL;
        !          1810:                        else {
        !          1811:                                nwidp = malloc(sizeof *nwidp, M_DEVBUF, M_WAITOK);
        !          1812:                                bzero(nwidp, sizeof(*nwidp));
        !          1813:                                wi_set_ssid(nwidp, (u_int8_t *)&wreq->wi_val[1],
        !          1814:                                    letoh16(wreq->wi_val[0]));
        !          1815:                                error = copyout(nwidp, ifr->ifr_data,
        !          1816:                                    sizeof(*nwidp));
        !          1817:                        }
        !          1818:                }
        !          1819:                break;
        !          1820:        case SIOCS80211NWID:
        !          1821:                if ((error = suser(curproc, 0)) != 0)
        !          1822:                        break;
        !          1823:                nwidp = malloc(sizeof *nwidp, M_DEVBUF, M_WAITOK);
        !          1824:                error = copyin(ifr->ifr_data, nwidp, sizeof(*nwidp));
        !          1825:                if (error)
        !          1826:                        break;
        !          1827:                if (nwidp->i_len > IEEE80211_NWID_LEN) {
        !          1828:                        error = EINVAL;
        !          1829:                        break;
        !          1830:                }
        !          1831:                if (sc->wi_net_name.i_len == nwidp->i_len &&
        !          1832:                    memcmp(sc->wi_net_name.i_nwid, nwidp->i_nwid, nwidp->i_len) == 0)
        !          1833:                        break;
        !          1834:                wi_set_ssid(&sc->wi_net_name, nwidp->i_nwid, nwidp->i_len);
        !          1835:                WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
        !          1836:                if (ifp->if_flags & IFF_UP)
        !          1837:                        /* Reinitialize WaveLAN. */
        !          1838:                        wi_init(sc);
        !          1839:                break;
        !          1840:        case SIOCS80211NWKEY:
        !          1841:                if ((error = suser(curproc, 0)) != 0)
        !          1842:                        break;
        !          1843:                error = wi_set_nwkey(sc, (struct ieee80211_nwkey *)data);
        !          1844:                break;
        !          1845:        case SIOCG80211NWKEY:
        !          1846:                error = wi_get_nwkey(sc, (struct ieee80211_nwkey *)data);
        !          1847:                break;
        !          1848:        case SIOCS80211POWER:
        !          1849:                if ((error = suser(curproc, 0)) != 0)
        !          1850:                        break;
        !          1851:                error = wi_set_pm(sc, (struct ieee80211_power *)data);
        !          1852:                break;
        !          1853:        case SIOCG80211POWER:
        !          1854:                error = wi_get_pm(sc, (struct ieee80211_power *)data);
        !          1855:                break;
        !          1856:        case SIOCS80211TXPOWER:
        !          1857:                if ((error = suser(curproc, 0)) != 0)
        !          1858:                        break;
        !          1859:                error = wi_set_txpower(sc, (struct ieee80211_txpower *)data);
        !          1860:                break;
        !          1861:        case SIOCG80211TXPOWER:
        !          1862:                error = wi_get_txpower(sc, (struct ieee80211_txpower *)data);
        !          1863:                break;
        !          1864:        case SIOCS80211CHANNEL:
        !          1865:                if ((error = suser(curproc, 0)) != 0)
        !          1866:                        break;
        !          1867:                if (((struct ieee80211chanreq *)data)->i_channel > 14) {
        !          1868:                        error = EINVAL;
        !          1869:                        break;
        !          1870:                }
        !          1871:                wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
        !          1872:                bzero(wreq, sizeof(*wreq));
        !          1873:                wreq->wi_type = WI_RID_OWN_CHNL;
        !          1874:                wreq->wi_val[0] =
        !          1875:                    htole16(((struct ieee80211chanreq *)data)->i_channel);
        !          1876:                error = wi_setdef(sc, wreq);
        !          1877:                if (!error && (ifp->if_flags & IFF_UP))
        !          1878:                        wi_init(sc);
        !          1879:                break;
        !          1880:        case SIOCG80211CHANNEL:
        !          1881:                wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
        !          1882:                bzero(wreq, sizeof(*wreq));
        !          1883:                wreq->wi_type = WI_RID_CURRENT_CHAN;
        !          1884:                wreq->wi_len = WI_MAX_DATALEN;
        !          1885:                if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
        !          1886:                        error = EINVAL;
        !          1887:                        break;
        !          1888:                }
        !          1889:                ((struct ieee80211chanreq *)data)->i_channel =
        !          1890:                    letoh16(wreq->wi_val[0]);
        !          1891:                break;
        !          1892:        case SIOCG80211BSSID:
        !          1893:                bssid = (struct ieee80211_bssid *)data;
        !          1894:                wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
        !          1895:                bzero(wreq, sizeof(*wreq));
        !          1896:                wreq->wi_type = WI_RID_CURRENT_BSSID;
        !          1897:                wreq->wi_len = WI_MAX_DATALEN;
        !          1898:                if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
        !          1899:                        error = EINVAL;
        !          1900:                        break;
        !          1901:                }
        !          1902:                IEEE80211_ADDR_COPY(bssid->i_bssid, wreq->wi_val);
        !          1903:                break;
        !          1904:        case SIOCS80211SCAN:
        !          1905:                if ((error = suser(curproc, 0)) != 0)
        !          1906:                        break;
        !          1907:                if (sc->wi_ptype == WI_PORTTYPE_HOSTAP)
        !          1908:                        break;
        !          1909:                if ((ifp->if_flags & IFF_UP) == 0) {
        !          1910:                        error = ENETDOWN;
        !          1911:                        break;
        !          1912:                }
        !          1913:                if (sc->sc_firmware_type == WI_LUCENT) {
        !          1914:                        wi_cmd(sc, WI_CMD_INQUIRE,
        !          1915:                            WI_INFO_SCAN_RESULTS, 0, 0);
        !          1916:                } else {
        !          1917:                        wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
        !          1918:                        bzero(wreq, sizeof(*wreq));
        !          1919:                        wreq->wi_len = 3;
        !          1920:                        wreq->wi_type = WI_RID_SCAN_REQ;
        !          1921:                        wreq->wi_val[0] = 0x3FFF;
        !          1922:                        wreq->wi_val[1] = 0x000F;
        !          1923:
        !          1924:                        error = wi_write_record(sc,
        !          1925:                            (struct wi_ltv_gen *)wreq);
        !          1926:                        if (error)
        !          1927:                                break;
        !          1928:                }
        !          1929:                sc->wi_scan_lock = 0;
        !          1930:                timeout_set(&sc->wi_scan_timeout, wi_scan_timeout, sc);
        !          1931:                len = WI_WAVELAN_RES_TIMEOUT;
        !          1932:                if (sc->wi_flags & WI_FLAGS_BUS_USB) {
        !          1933:                        /* Use a longer timeout for wi@usb */
        !          1934:                        len = WI_WAVELAN_RES_TIMEOUT * 4;
        !          1935:                }
        !          1936:                timeout_add(&sc->wi_scan_timeout, len);
        !          1937:
        !          1938:                /* Let the userspace process wait for completion */
        !          1939:                error = tsleep(&sc->wi_scan_lock, PCATCH, "wiscan",
        !          1940:                    hz * IEEE80211_SCAN_TIMEOUT);
        !          1941:                break;
        !          1942:        case SIOCG80211ALLNODES:
        !          1943:            {
        !          1944:                struct ieee80211_nodereq        *nr = NULL;
        !          1945:
        !          1946:                if ((error = suser(curproc, 0)) != 0)
        !          1947:                        break;
        !          1948:                na = (struct ieee80211_nodereq_all *)data;
        !          1949:                if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
        !          1950:                        /* List all associated stations */
        !          1951:                        error = wihap_ioctl(sc, command, data);
        !          1952:                        break;
        !          1953:                }
        !          1954:                wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
        !          1955:                bzero(wreq, sizeof(*wreq));
        !          1956:                wreq->wi_len = WI_MAX_DATALEN;
        !          1957:                wreq->wi_type = WI_RID_SCAN_RES;
        !          1958:                if (sc->sc_firmware_type == WI_LUCENT) {
        !          1959:                        bcopy(sc->wi_scanbuf, wreq->wi_val,
        !          1960:                            sc->wi_scanbuf_len * 2);
        !          1961:                        wreq->wi_len = sc->wi_scanbuf_len;
        !          1962:                        i = 0;
        !          1963:                        len = WI_WAVELAN_RES_SIZE;
        !          1964:                } else {
        !          1965:                        if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
        !          1966:                                error = EINVAL;
        !          1967:                                break;
        !          1968:                        }
        !          1969:                        p2 = (struct wi_scan_p2_hdr *)wreq->wi_val;
        !          1970:                        if (p2->wi_reason == 0)
        !          1971:                                break;
        !          1972:                        i = sizeof(*p2);
        !          1973:                        len = WI_PRISM2_RES_SIZE;
        !          1974:                }
        !          1975:
        !          1976:                for (na->na_nodes = j = 0; (i < (wreq->wi_len * 2) - len) &&
        !          1977:                    (na->na_size >= j + sizeof(struct ieee80211_nodereq));
        !          1978:                    i += len) {
        !          1979:
        !          1980:                        if (nr == NULL)
        !          1981:                                nr = malloc(sizeof *nr, M_DEVBUF, M_WAITOK);
        !          1982:                        res = (struct wi_scan_res *)((char *)wreq->wi_val + i);
        !          1983:                        if (res == NULL)
        !          1984:                                break;
        !          1985:
        !          1986:                        bzero(nr, sizeof(*nr));
        !          1987:                        IEEE80211_ADDR_COPY(nr->nr_macaddr, res->wi_bssid);
        !          1988:                        IEEE80211_ADDR_COPY(nr->nr_bssid, res->wi_bssid);
        !          1989:                        nr->nr_channel = letoh16(res->wi_chan);
        !          1990:                        nr->nr_chan_flags = IEEE80211_CHAN_B;
        !          1991:                        nr->nr_rssi = letoh16(res->wi_signal);
        !          1992:                        nr->nr_max_rssi = 0; /* XXX */
        !          1993:                        nr->nr_nwid_len = letoh16(res->wi_ssid_len);
        !          1994:                        bcopy(res->wi_ssid, nr->nr_nwid, nr->nr_nwid_len);
        !          1995:                        nr->nr_intval = letoh16(res->wi_interval);
        !          1996:                        nr->nr_capinfo = letoh16(res->wi_capinfo);
        !          1997:                        nr->nr_txrate = res->wi_rate == WI_WAVELAN_RES_1M ? 2 :
        !          1998:                            (res->wi_rate == WI_WAVELAN_RES_2M ? 4 :
        !          1999:                            (res->wi_rate == WI_WAVELAN_RES_5M ? 11 :
        !          2000:                            (res->wi_rate == WI_WAVELAN_RES_11M ? 22 : 0)));
        !          2001:                        nr->nr_nrates = 0;
        !          2002:                        while (res->wi_srates[nr->nr_nrates] != 0) {
        !          2003:                                nr->nr_rates[nr->nr_nrates] =
        !          2004:                                    res->wi_srates[nr->nr_nrates] &
        !          2005:                                    WI_VAR_SRATES_MASK;
        !          2006:                                nr->nr_nrates++;
        !          2007:                        }
        !          2008:                        nr->nr_flags = 0;
        !          2009:                        if (bcmp(nr->nr_macaddr, nr->nr_bssid,
        !          2010:                            IEEE80211_ADDR_LEN) == 0)
        !          2011:                                nr->nr_flags |= IEEE80211_NODEREQ_AP;
        !          2012:
        !          2013:                        error = copyout(nr, (caddr_t)na->na_node + j,
        !          2014:                            sizeof(struct ieee80211_nodereq));
        !          2015:                        if (error)
        !          2016:                                break;
        !          2017:                        j += sizeof(struct ieee80211_nodereq);
        !          2018:                        na->na_nodes++;
        !          2019:                }
        !          2020:                if (nr)
        !          2021:                        free(nr, M_DEVBUF);
        !          2022:                break;
        !          2023:            }
        !          2024:        case SIOCG80211FLAGS:
        !          2025:                if (sc->wi_ptype != WI_PORTTYPE_HOSTAP)
        !          2026:                        break;
        !          2027:                ifr->ifr_flags = 0;
        !          2028:                if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY) {
        !          2029:                        wreq = malloc(sizeof *wreq, M_DEVBUF, M_WAITOK);
        !          2030:                        bzero(wreq, sizeof(*wreq));
        !          2031:                        wreq->wi_len = WI_MAX_DATALEN;
        !          2032:                        wreq->wi_type = WI_RID_ENH_SECURITY;
        !          2033:                        if (wi_read_record(sc, (struct wi_ltv_gen *)wreq)) {
        !          2034:                                error = EINVAL;
        !          2035:                                break;
        !          2036:                        }
        !          2037:                        sc->wi_enh_security = letoh16(wreq->wi_val[0]);
        !          2038:                        if (sc->wi_enh_security == WI_HIDESSID_IGNPROBES)
        !          2039:                                ifr->ifr_flags |= IEEE80211_F_HIDENWID >>
        !          2040:                                    IEEE80211_F_USERSHIFT;
        !          2041:                }
        !          2042:                break;
        !          2043:        case SIOCS80211FLAGS:
        !          2044:                if ((error = suser(curproc, 0)) != 0)
        !          2045:                        break;
        !          2046:                if (sc->wi_ptype != WI_PORTTYPE_HOSTAP) {
        !          2047:                        error = EINVAL;
        !          2048:                        break;
        !          2049:                }
        !          2050:                flags = (u_int32_t)ifr->ifr_flags << IEEE80211_F_USERSHIFT;
        !          2051:                if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY) {
        !          2052:                        sc->wi_enh_security = (flags & IEEE80211_F_HIDENWID) ?
        !          2053:                            WI_HIDESSID_IGNPROBES : 0;
        !          2054:                        WI_SETVAL(WI_RID_ENH_SECURITY, sc->wi_enh_security);
        !          2055:                }
        !          2056:                break;
        !          2057:        case SIOCHOSTAP_ADD:
        !          2058:        case SIOCHOSTAP_DEL:
        !          2059:        case SIOCHOSTAP_GET:
        !          2060:        case SIOCHOSTAP_GETALL:
        !          2061:        case SIOCHOSTAP_GFLAGS:
        !          2062:        case SIOCHOSTAP_SFLAGS:
        !          2063:                /* Send all Host AP specific ioctl's to Host AP code. */
        !          2064:                error = wihap_ioctl(sc, command, data);
        !          2065:                break;
        !          2066:        default:
        !          2067:                error = EINVAL;
        !          2068:                break;
        !          2069:        }
        !          2070:
        !          2071:        if (wreq)
        !          2072:                free(wreq, M_DEVBUF);
        !          2073:        if (nwidp)
        !          2074:                free(nwidp, M_DEVBUF);
        !          2075:        splx(s);
        !          2076:        return(error);
        !          2077: }
        !          2078:
        !          2079: void
        !          2080: wi_scan_timeout(void *arg)
        !          2081: {
        !          2082:        struct wi_softc         *sc = (struct wi_softc *)arg;
        !          2083:        struct wi_req           wreq;
        !          2084:
        !          2085:        if (sc->wi_scan_lock++ < WI_WAVELAN_RES_TRIES &&
        !          2086:            sc->sc_firmware_type != WI_LUCENT &&
        !          2087:            (sc->wi_flags & WI_FLAGS_BUS_USB) == 0) {
        !          2088:                /*
        !          2089:                 * The Prism2/2.5/3 chipsets will set an extra field in the
        !          2090:                 * scan result if the scan request has been completed by the
        !          2091:                 * firmware. This allows to poll for completion and to
        !          2092:                 * wait for some more time if the scan is still in progress.
        !          2093:                 *
        !          2094:                 * XXX This doesn't work with wi@usb because it isn't safe
        !          2095:                 * to call wi_read_record_usb() while beeing in the timeout
        !          2096:                 * handler.
        !          2097:                 */
        !          2098:                wreq.wi_len = WI_MAX_DATALEN;
        !          2099:                wreq.wi_type = WI_RID_SCAN_RES;
        !          2100:
        !          2101:                if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
        !          2102:                    ((struct wi_scan_p2_hdr *)wreq.wi_val)->wi_reason == 0) {
        !          2103:                        /* Wait some more time for scan completion */
        !          2104:                        timeout_add(&sc->wi_scan_timeout, WI_WAVELAN_RES_TIMEOUT);
        !          2105:                        return;
        !          2106:                }
        !          2107:        }
        !          2108:
        !          2109:        if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
        !          2110:                printf(WI_PRT_FMT ": wi_scan_timeout: %d tries\n",
        !          2111:                    WI_PRT_ARG(sc), sc->wi_scan_lock);
        !          2112:
        !          2113:        /* Wakeup the userland */
        !          2114:        wakeup(&sc->wi_scan_lock);
        !          2115:        sc->wi_scan_lock = 0;
        !          2116: }
        !          2117:
        !          2118: STATIC void
        !          2119: wi_init_io(struct wi_softc *sc)
        !          2120: {
        !          2121:        struct ifnet            *ifp = &sc->sc_ic.ic_ac.ac_if;
        !          2122:        int                     s;
        !          2123:        struct wi_ltv_macaddr   mac;
        !          2124:        int                     id = 0;
        !          2125:
        !          2126:        if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
        !          2127:                return;
        !          2128:
        !          2129:        DPRINTF(WID_INIT, ("wi_init: sc %p\n", sc));
        !          2130:
        !          2131:        s = splnet();
        !          2132:
        !          2133:        if (ifp->if_flags & IFF_RUNNING)
        !          2134:                wi_stop(sc);
        !          2135:
        !          2136:        wi_reset(sc);
        !          2137:
        !          2138:        /* Program max data length. */
        !          2139:        WI_SETVAL(WI_RID_MAX_DATALEN, sc->wi_max_data_len);
        !          2140:
        !          2141:        /* Set the port type. */
        !          2142:        WI_SETVAL(WI_RID_PORTTYPE, sc->wi_ptype);
        !          2143:
        !          2144:        /* Enable/disable IBSS creation. */
        !          2145:        WI_SETVAL(WI_RID_CREATE_IBSS, sc->wi_create_ibss);
        !          2146:
        !          2147:        /* Program the RTS/CTS threshold. */
        !          2148:        WI_SETVAL(WI_RID_RTS_THRESH, sc->wi_rts_thresh);
        !          2149:
        !          2150:        /* Program the TX rate */
        !          2151:        WI_SETVAL(WI_RID_TX_RATE, sc->wi_tx_rate);
        !          2152:
        !          2153:        /* Access point density */
        !          2154:        WI_SETVAL(WI_RID_SYSTEM_SCALE, sc->wi_ap_density);
        !          2155:
        !          2156:        /* Power Management Enabled */
        !          2157:        WI_SETVAL(WI_RID_PM_ENABLED, sc->wi_pm_enabled);
        !          2158:
        !          2159:        /* Power Management Max Sleep */
        !          2160:        WI_SETVAL(WI_RID_MAX_SLEEP, sc->wi_max_sleep);
        !          2161:
        !          2162:        /* Set Enhanced Security if supported. */
        !          2163:        if (sc->wi_flags & WI_FLAGS_HAS_ENH_SECURITY)
        !          2164:                WI_SETVAL(WI_RID_ENH_SECURITY, sc->wi_enh_security);
        !          2165:
        !          2166:        /* Set Roaming Mode unless this is a Symbol card. */
        !          2167:        if (sc->wi_flags & WI_FLAGS_HAS_ROAMING)
        !          2168:                WI_SETVAL(WI_RID_ROAMING_MODE, sc->wi_roaming);
        !          2169:
        !          2170:        /* Set Antenna Diversity if this is a Symbol card. */
        !          2171:        if (sc->wi_flags & WI_FLAGS_HAS_DIVERSITY)
        !          2172:                WI_SETVAL(WI_RID_SYMBOL_DIVERSITY, sc->wi_diversity);
        !          2173:
        !          2174:        /* Specify the network name */
        !          2175:        WI_SETSTR(WI_RID_DESIRED_SSID, sc->wi_net_name);
        !          2176:
        !          2177:        /* Specify the IBSS name */
        !          2178:        if (sc->wi_net_name.i_len != 0 && (sc->wi_ptype == WI_PORTTYPE_HOSTAP ||
        !          2179:            (sc->wi_create_ibss && sc->wi_ptype == WI_PORTTYPE_IBSS)))
        !          2180:                WI_SETSTR(WI_RID_OWN_SSID, sc->wi_net_name);
        !          2181:        else
        !          2182:                WI_SETSTR(WI_RID_OWN_SSID, sc->wi_ibss_name);
        !          2183:
        !          2184:        /* Specify the frequency to use */
        !          2185:        WI_SETVAL(WI_RID_OWN_CHNL, sc->wi_channel);
        !          2186:
        !          2187:        /* Program the nodename. */
        !          2188:        WI_SETSTR(WI_RID_NODENAME, sc->wi_node_name);
        !          2189:
        !          2190:        /* Set our MAC address. */
        !          2191:        mac.wi_len = 4;
        !          2192:        mac.wi_type = WI_RID_MAC_NODE;
        !          2193:        bcopy(LLADDR(ifp->if_sadl),
        !          2194:            (char *)&sc->sc_ic.ic_myaddr, ETHER_ADDR_LEN);
        !          2195:        bcopy((char *)&sc->sc_ic.ic_myaddr,
        !          2196:            (char *)&mac.wi_mac_addr, ETHER_ADDR_LEN);
        !          2197:        wi_write_record(sc, (struct wi_ltv_gen *)&mac);
        !          2198:
        !          2199:        /*
        !          2200:         * Initialize promisc mode.
        !          2201:         *      Being in the Host-AP mode causes
        !          2202:         *      great deal of pain if promisc mode is set.
        !          2203:         *      Therefore we avoid confusing the firmware
        !          2204:         *      and always reset promisc mode in Host-AP regime,
        !          2205:         *      it shows us all the packets anyway.
        !          2206:         */
        !          2207:        if (sc->wi_ptype != WI_PORTTYPE_HOSTAP && ifp->if_flags & IFF_PROMISC)
        !          2208:                WI_SETVAL(WI_RID_PROMISC, 1);
        !          2209:        else
        !          2210:                WI_SETVAL(WI_RID_PROMISC, 0);
        !          2211:
        !          2212:        /* Configure WEP. */
        !          2213:        if (sc->wi_flags & WI_FLAGS_HAS_WEP) {
        !          2214:                WI_SETVAL(WI_RID_ENCRYPTION, sc->wi_use_wep);
        !          2215:                WI_SETVAL(WI_RID_TX_CRYPT_KEY, sc->wi_tx_key);
        !          2216:                sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
        !          2217:                sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
        !          2218:                wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
        !          2219:                if (sc->sc_firmware_type != WI_LUCENT && sc->wi_use_wep) {
        !          2220:                        /*
        !          2221:                         * HWB3163 EVAL-CARD Firmware version less than 0.8.2.
        !          2222:                         *
        !          2223:                         * If promiscuous mode is disabled, the Prism2 chip
        !          2224:                         * does not work with WEP .
        !          2225:                         * I'm currently investigating the details of this.
        !          2226:                         * (ichiro@netbsd.org)
        !          2227:                         */
        !          2228:                         if (sc->sc_firmware_type == WI_INTERSIL &&
        !          2229:                            sc->sc_sta_firmware_ver < 802 ) {
        !          2230:                                /* firm ver < 0.8.2 */
        !          2231:                                WI_SETVAL(WI_RID_PROMISC, 1);
        !          2232:                         }
        !          2233:                         WI_SETVAL(WI_RID_CNFAUTHMODE, sc->wi_authtype);
        !          2234:                }
        !          2235:        }
        !          2236:
        !          2237:        /* Set multicast filter. */
        !          2238:        wi_setmulti(sc);
        !          2239:
        !          2240:        /* Enable desired port */
        !          2241:        wi_cmd(sc, WI_CMD_ENABLE | sc->wi_portnum, 0, 0, 0);
        !          2242:
        !          2243:        if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
        !          2244:                printf(WI_PRT_FMT ": tx buffer allocation failed\n",
        !          2245:                    WI_PRT_ARG(sc));
        !          2246:        sc->wi_tx_data_id = id;
        !          2247:
        !          2248:        if (wi_alloc_nicmem(sc, ETHER_MAX_LEN + sizeof(struct wi_frame) + 8, &id))
        !          2249:                printf(WI_PRT_FMT ": mgmt. buffer allocation failed\n",
        !          2250:                    WI_PRT_ARG(sc));
        !          2251:        sc->wi_tx_mgmt_id = id;
        !          2252:
        !          2253:        /* Set txpower */
        !          2254:        if (sc->wi_flags & WI_FLAGS_TXPOWER)
        !          2255:                wi_set_txpower(sc, NULL);
        !          2256:
        !          2257:        /* enable interrupts */
        !          2258:        wi_intr_enable(sc, WI_INTRS);
        !          2259:
        !          2260:         wihap_init(sc);
        !          2261:
        !          2262:        splx(s);
        !          2263:
        !          2264:        ifp->if_flags |= IFF_RUNNING;
        !          2265:        ifp->if_flags &= ~IFF_OACTIVE;
        !          2266:
        !          2267:        timeout_add(&sc->sc_timo, hz * 60);
        !          2268:
        !          2269:        return;
        !          2270: }
        !          2271:
        !          2272: static const u_int32_t crc32tab[] = {
        !          2273:        0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
        !          2274:        0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
        !          2275:        0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
        !          2276:        0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
        !          2277:        0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
        !          2278:        0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
        !          2279:        0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
        !          2280:        0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
        !          2281:        0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
        !          2282:        0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
        !          2283:        0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
        !          2284:        0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
        !          2285:        0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
        !          2286:        0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
        !          2287:        0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
        !          2288:        0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
        !          2289:        0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
        !          2290:        0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
        !          2291:        0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
        !          2292:        0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
        !          2293:        0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
        !          2294:        0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
        !          2295:        0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
        !          2296:        0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
        !          2297:        0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
        !          2298:        0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
        !          2299:        0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
        !          2300:        0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
        !          2301:        0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
        !          2302:        0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
        !          2303:        0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
        !          2304:        0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
        !          2305:        0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
        !          2306:        0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
        !          2307:        0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
        !          2308:        0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
        !          2309:        0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
        !          2310:        0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
        !          2311:        0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
        !          2312:        0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
        !          2313:        0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
        !          2314:        0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
        !          2315:        0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
        !          2316:        0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
        !          2317:        0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
        !          2318:        0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
        !          2319:        0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
        !          2320:        0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
        !          2321:        0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
        !          2322:        0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
        !          2323:        0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
        !          2324:        0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
        !          2325:        0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
        !          2326:        0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
        !          2327:        0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
        !          2328:        0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
        !          2329:        0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
        !          2330:        0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
        !          2331:        0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
        !          2332:        0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
        !          2333:        0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
        !          2334:        0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
        !          2335:        0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
        !          2336:        0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
        !          2337: };
        !          2338:
        !          2339: STATIC void
        !          2340: wi_do_hostencrypt(struct wi_softc *sc, caddr_t buf, int len)
        !          2341: {
        !          2342:        u_int32_t i, crc, klen;
        !          2343:        u_int8_t key[RC4KEYLEN];
        !          2344:        u_int8_t *dat;
        !          2345:        struct rc4_ctx ctx;
        !          2346:
        !          2347:        if (!sc->wi_icv_flag) {
        !          2348:                sc->wi_icv = arc4random();
        !          2349:                sc->wi_icv_flag++;
        !          2350:         } else
        !          2351:                sc->wi_icv++;
        !          2352:        /*
        !          2353:         * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
        !          2354:         * (B, 255, N) with 3 <= B < 8
        !          2355:         */
        !          2356:        if (sc->wi_icv >= 0x03ff00 &&
        !          2357:             (sc->wi_icv & 0xf8ff00) == 0x00ff00)
        !          2358:                 sc->wi_icv += 0x000100;
        !          2359:
        !          2360:        /* prepend 24bit IV to tx key, byte order does not matter */
        !          2361:        bzero(key, sizeof(key));
        !          2362:        key[0] = sc->wi_icv >> 16;
        !          2363:        key[1] = sc->wi_icv >> 8;
        !          2364:        key[2] = sc->wi_icv;
        !          2365:
        !          2366:        klen = letoh16(sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keylen);
        !          2367:        bcopy((char *)&sc->wi_keys.wi_keys[sc->wi_tx_key].wi_keydat,
        !          2368:            (char *)key + IEEE80211_WEP_IVLEN, klen);
        !          2369:        klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2;
        !          2370:
        !          2371:        /* rc4 keysetup */
        !          2372:        rc4_keysetup(&ctx, key, klen);
        !          2373:
        !          2374:        /* output: IV, tx keyid, rc4(data), rc4(crc32(data)) */
        !          2375:        dat = buf;
        !          2376:        dat[0] = key[0];
        !          2377:        dat[1] = key[1];
        !          2378:        dat[2] = key[2];
        !          2379:        dat[3] = sc->wi_tx_key << 6;            /* pad and keyid */
        !          2380:        dat += 4;
        !          2381:
        !          2382:        /* compute crc32 over data and encrypt */
        !          2383:        crc = ~0;
        !          2384:        for (i = 0; i < len; i++)
        !          2385:                crc = crc32tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
        !          2386:        crc = ~crc;
        !          2387:        rc4_crypt(&ctx, dat, dat, len);
        !          2388:        dat += len;
        !          2389:
        !          2390:        /* append little-endian crc32 and encrypt */
        !          2391:        dat[0] = crc;
        !          2392:        dat[1] = crc >> 8;
        !          2393:        dat[2] = crc >> 16;
        !          2394:        dat[3] = crc >> 24;
        !          2395:        rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN);
        !          2396: }
        !          2397:
        !          2398: STATIC int
        !          2399: wi_do_hostdecrypt(struct wi_softc *sc, caddr_t buf, int len)
        !          2400: {
        !          2401:        u_int32_t i, crc, klen, kid;
        !          2402:        u_int8_t key[RC4KEYLEN];
        !          2403:        u_int8_t *dat;
        !          2404:        struct rc4_ctx ctx;
        !          2405:
        !          2406:        if (len < IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
        !          2407:            IEEE80211_WEP_CRCLEN)
        !          2408:                return -1;
        !          2409:        len -= (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
        !          2410:            IEEE80211_WEP_CRCLEN);
        !          2411:
        !          2412:        dat = buf;
        !          2413:
        !          2414:        bzero(key, sizeof(key));
        !          2415:        key[0] = dat[0];
        !          2416:        key[1] = dat[1];
        !          2417:        key[2] = dat[2];
        !          2418:        kid = (dat[3] >> 6) % 4;
        !          2419:        dat += 4;
        !          2420:
        !          2421:        klen = letoh16(sc->wi_keys.wi_keys[kid].wi_keylen);
        !          2422:        bcopy((char *)&sc->wi_keys.wi_keys[kid].wi_keydat,
        !          2423:            (char *)key + IEEE80211_WEP_IVLEN, klen);
        !          2424:        klen = (klen > IEEE80211_WEP_KEYLEN) ? RC4KEYLEN : RC4KEYLEN / 2;
        !          2425:
        !          2426:        /* rc4 keysetup */
        !          2427:        rc4_keysetup(&ctx, key, klen);
        !          2428:
        !          2429:        /* decrypt and compute crc32 over data */
        !          2430:        rc4_crypt(&ctx, dat, dat, len);
        !          2431:        crc = ~0;
        !          2432:        for (i = 0; i < len; i++)
        !          2433:                crc = crc32tab[(crc ^ dat[i]) & 0xff] ^ (crc >> 8);
        !          2434:        crc = ~crc;
        !          2435:        dat += len;
        !          2436:
        !          2437:        /* decrypt little-endian crc32 and verify */
        !          2438:        rc4_crypt(&ctx, dat, dat, IEEE80211_WEP_CRCLEN);
        !          2439:
        !          2440:        if ((dat[0] != crc) && (dat[1] != crc >> 8) &&
        !          2441:            (dat[2] != crc >> 16) && (dat[3] != crc >> 24)) {
        !          2442:                if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
        !          2443:                        printf(WI_PRT_FMT ": wi_do_hostdecrypt: iv mismatch: "
        !          2444:                            "0x%02x%02x%02x%02x vs. 0x%x\n", WI_PRT_ARG(sc),
        !          2445:                            dat[3], dat[2], dat[1], dat[0], crc);
        !          2446:                return -1;
        !          2447:        }
        !          2448:
        !          2449:        return 0;
        !          2450: }
        !          2451:
        !          2452: void
        !          2453: wi_start(struct ifnet *ifp)
        !          2454: {
        !          2455:        struct wi_softc         *sc;
        !          2456:        struct mbuf             *m0;
        !          2457:        struct wi_frame         tx_frame;
        !          2458:        struct ether_header     *eh;
        !          2459:        int                     id, hostencrypt = 0;
        !          2460:
        !          2461:        sc = ifp->if_softc;
        !          2462:
        !          2463:        DPRINTF(WID_START, ("wi_start: ifp %p sc %p\n", ifp, sc));
        !          2464:
        !          2465:        if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
        !          2466:                return;
        !          2467:
        !          2468:        if (ifp->if_flags & IFF_OACTIVE)
        !          2469:                return;
        !          2470:
        !          2471: nextpkt:
        !          2472:        IFQ_DEQUEUE(&ifp->if_snd, m0);
        !          2473:        if (m0 == NULL)
        !          2474:                return;
        !          2475:
        !          2476:        bzero((char *)&tx_frame, sizeof(tx_frame));
        !          2477:        tx_frame.wi_frame_ctl = htole16(WI_FTYPE_DATA | WI_STYPE_DATA);
        !          2478:        id = sc->wi_tx_data_id;
        !          2479:        eh = mtod(m0, struct ether_header *);
        !          2480:
        !          2481:        if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
        !          2482:                if (!wihap_check_tx(&sc->wi_hostap_info, eh->ether_dhost,
        !          2483:                    &tx_frame.wi_tx_rate) && !(ifp->if_flags & IFF_PROMISC)) {
        !          2484:                        if (ifp->if_flags & IFF_DEBUG)
        !          2485:                                printf(WI_PRT_FMT
        !          2486:                                    ": wi_start: dropping unassoc dst %s\n",
        !          2487:                                    WI_PRT_ARG(sc),
        !          2488:                                    ether_sprintf(eh->ether_dhost));
        !          2489:                        m_freem(m0);
        !          2490:                        goto nextpkt;
        !          2491:                }
        !          2492:        }
        !          2493:
        !          2494:        /*
        !          2495:         * Use RFC1042 encoding for IP and ARP datagrams,
        !          2496:         * 802.3 for anything else.
        !          2497:         */
        !          2498:        if (eh->ether_type == htons(ETHERTYPE_IP) ||
        !          2499:            eh->ether_type == htons(ETHERTYPE_ARP) ||
        !          2500:            eh->ether_type == htons(ETHERTYPE_REVARP) ||
        !          2501:            eh->ether_type == htons(ETHERTYPE_IPV6)) {
        !          2502:                bcopy((char *)&eh->ether_dhost,
        !          2503:                    (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
        !          2504:                if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) {
        !          2505:                        tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); /* XXX */
        !          2506:                        tx_frame.wi_frame_ctl |= htole16(WI_FCTL_FROMDS);
        !          2507:                        bcopy((char *)&sc->sc_ic.ic_myaddr,
        !          2508:                            (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
        !          2509:                        bcopy((char *)&eh->ether_shost,
        !          2510:                            (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN);
        !          2511:                        if (sc->wi_use_wep)
        !          2512:                                hostencrypt = 1;
        !          2513:                } else if (sc->wi_ptype == WI_PORTTYPE_BSS && sc->wi_use_wep &&
        !          2514:                    sc->wi_crypto_algorithm != WI_CRYPTO_FIRMWARE_WEP) {
        !          2515:                        tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT); /* XXX */
        !          2516:                        tx_frame.wi_frame_ctl |= htole16(WI_FCTL_TODS);
        !          2517:                        bcopy((char *)&sc->sc_ic.ic_myaddr,
        !          2518:                            (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
        !          2519:                        bcopy((char *)&eh->ether_dhost,
        !          2520:                            (char *)&tx_frame.wi_addr3, ETHER_ADDR_LEN);
        !          2521:                        hostencrypt = 1;
        !          2522:                } else
        !          2523:                        bcopy((char *)&eh->ether_shost,
        !          2524:                            (char *)&tx_frame.wi_addr2, ETHER_ADDR_LEN);
        !          2525:                bcopy((char *)&eh->ether_dhost,
        !          2526:                    (char *)&tx_frame.wi_dst_addr, ETHER_ADDR_LEN);
        !          2527:                bcopy((char *)&eh->ether_shost,
        !          2528:                    (char *)&tx_frame.wi_src_addr, ETHER_ADDR_LEN);
        !          2529:
        !          2530:                tx_frame.wi_dat_len = m0->m_pkthdr.len - WI_SNAPHDR_LEN;
        !          2531:                tx_frame.wi_dat[0] = htons(WI_SNAP_WORD0);
        !          2532:                tx_frame.wi_dat[1] = htons(WI_SNAP_WORD1);
        !          2533:                tx_frame.wi_len = htons(m0->m_pkthdr.len - WI_SNAPHDR_LEN);
        !          2534:                tx_frame.wi_type = eh->ether_type;
        !          2535:
        !          2536:                if (hostencrypt) {
        !          2537:
        !          2538:                        /* Do host encryption. */
        !          2539:                        tx_frame.wi_frame_ctl |= htole16(WI_FCTL_WEP);
        !          2540:                        bcopy(&tx_frame.wi_dat[0], &sc->wi_txbuf[4], 8);
        !          2541:
        !          2542:                        m_copydata(m0, sizeof(struct ether_header),
        !          2543:                            m0->m_pkthdr.len - sizeof(struct ether_header),
        !          2544:                            (caddr_t)&sc->wi_txbuf[12]);
        !          2545:
        !          2546:                        wi_do_hostencrypt(sc, (caddr_t)&sc->wi_txbuf,
        !          2547:                            tx_frame.wi_dat_len);
        !          2548:
        !          2549:                        tx_frame.wi_dat_len += IEEE80211_WEP_IVLEN +
        !          2550:                            IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
        !          2551:
        !          2552:                        tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
        !          2553:                        wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
        !          2554:                            sizeof(struct wi_frame));
        !          2555:                        wi_write_data(sc, id, WI_802_11_OFFSET_RAW,
        !          2556:                            (caddr_t)&sc->wi_txbuf,
        !          2557:                            (m0->m_pkthdr.len -
        !          2558:                             sizeof(struct ether_header)) + 18);
        !          2559:                } else {
        !          2560:                        m_copydata(m0, sizeof(struct ether_header),
        !          2561:                            m0->m_pkthdr.len - sizeof(struct ether_header),
        !          2562:                            (caddr_t)&sc->wi_txbuf);
        !          2563:
        !          2564:                        tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
        !          2565:                        wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
        !          2566:                            sizeof(struct wi_frame));
        !          2567:                        wi_write_data(sc, id, WI_802_11_OFFSET,
        !          2568:                            (caddr_t)&sc->wi_txbuf,
        !          2569:                            (m0->m_pkthdr.len -
        !          2570:                             sizeof(struct ether_header)) + 2);
        !          2571:                }
        !          2572:        } else {
        !          2573:                tx_frame.wi_dat_len = htole16(m0->m_pkthdr.len);
        !          2574:
        !          2575:                if (sc->wi_ptype == WI_PORTTYPE_HOSTAP && sc->wi_use_wep) {
        !          2576:
        !          2577:                        /* Do host encryption. (XXX - not implemented) */
        !          2578:                        printf(WI_PRT_FMT
        !          2579:                            ": host encrypt not implemented for 802.3\n",
        !          2580:                            WI_PRT_ARG(sc));
        !          2581:                } else {
        !          2582:                        m_copydata(m0, 0, m0->m_pkthdr.len,
        !          2583:                            (caddr_t)&sc->wi_txbuf);
        !          2584:
        !          2585:                        wi_write_data(sc, id, 0, (caddr_t)&tx_frame,
        !          2586:                            sizeof(struct wi_frame));
        !          2587:                        wi_write_data(sc, id, WI_802_3_OFFSET,
        !          2588:                            (caddr_t)&sc->wi_txbuf, m0->m_pkthdr.len + 2);
        !          2589:                }
        !          2590:        }
        !          2591:
        !          2592: #if NBPFILTER > 0
        !          2593:        /*
        !          2594:         * If there's a BPF listener, bounce a copy of
        !          2595:         * this frame to him.
        !          2596:         */
        !          2597:        if (ifp->if_bpf)
        !          2598:                bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
        !          2599: #endif
        !          2600:
        !          2601:        m_freem(m0);
        !          2602:
        !          2603:        ifp->if_flags |= IFF_OACTIVE;
        !          2604:
        !          2605:        /*
        !          2606:         * Set a timeout in case the chip goes out to lunch.
        !          2607:         */
        !          2608:        ifp->if_timer = 5;
        !          2609:
        !          2610:        if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0))
        !          2611:                printf(WI_PRT_FMT ": wi_start: xmit failed\n", WI_PRT_ARG(sc));
        !          2612:
        !          2613:        return;
        !          2614: }
        !          2615:
        !          2616: STATIC int
        !          2617: wi_mgmt_xmit(struct wi_softc *sc, caddr_t data, int len)
        !          2618: {
        !          2619:        struct wi_frame         tx_frame;
        !          2620:        int                     id;
        !          2621:        struct wi_80211_hdr     *hdr;
        !          2622:        caddr_t                 dptr;
        !          2623:
        !          2624:        if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
        !          2625:                return(ENODEV);
        !          2626:
        !          2627:        hdr = (struct wi_80211_hdr *)data;
        !          2628:        dptr = data + sizeof(struct wi_80211_hdr);
        !          2629:
        !          2630:        bzero((char *)&tx_frame, sizeof(tx_frame));
        !          2631:        id = sc->wi_tx_mgmt_id;
        !          2632:
        !          2633:        bcopy((char *)hdr, (char *)&tx_frame.wi_frame_ctl,
        !          2634:           sizeof(struct wi_80211_hdr));
        !          2635:
        !          2636:        tx_frame.wi_tx_ctl = htole16(WI_ENC_TX_MGMT);
        !          2637:        tx_frame.wi_dat_len = len - sizeof(struct wi_80211_hdr);
        !          2638:        tx_frame.wi_len = htole16(tx_frame.wi_dat_len);
        !          2639:
        !          2640:        tx_frame.wi_dat_len = htole16(tx_frame.wi_dat_len);
        !          2641:        wi_write_data(sc, id, 0, (caddr_t)&tx_frame, sizeof(struct wi_frame));
        !          2642:        wi_write_data(sc, id, WI_802_11_OFFSET_RAW, dptr,
        !          2643:            (len - sizeof(struct wi_80211_hdr)) + 2);
        !          2644:
        !          2645:        if (wi_cmd(sc, WI_CMD_TX|WI_RECLAIM, id, 0, 0)) {
        !          2646:                printf(WI_PRT_FMT ": wi_mgmt_xmit: xmit failed\n",
        !          2647:                    WI_PRT_ARG(sc));
        !          2648:                /*
        !          2649:                 * Hostile stations or corrupt frames may crash the card
        !          2650:                 * and cause the kernel to get stuck printing complaints.
        !          2651:                 * Reset the card and hope the problem goes away.
        !          2652:                 */
        !          2653:                wi_reset(sc);
        !          2654:                return(EIO);
        !          2655:        }
        !          2656:
        !          2657:        return(0);
        !          2658: }
        !          2659:
        !          2660: void
        !          2661: wi_stop(struct wi_softc *sc)
        !          2662: {
        !          2663:        struct ifnet            *ifp;
        !          2664:
        !          2665:        wihap_shutdown(sc);
        !          2666:
        !          2667:        if (!(sc->wi_flags & WI_FLAGS_ATTACHED))
        !          2668:                return;
        !          2669:
        !          2670:        DPRINTF(WID_STOP, ("wi_stop: sc %p\n", sc));
        !          2671:
        !          2672:        timeout_del(&sc->sc_timo);
        !          2673:
        !          2674:        ifp = &sc->sc_ic.ic_if;
        !          2675:
        !          2676:        wi_intr_enable(sc, 0);
        !          2677:        wi_cmd(sc, WI_CMD_DISABLE|sc->wi_portnum, 0, 0, 0);
        !          2678:
        !          2679:        ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
        !          2680:        ifp->if_timer = 0;
        !          2681:
        !          2682:        return;
        !          2683: }
        !          2684:
        !          2685:
        !          2686: void
        !          2687: wi_watchdog(struct ifnet *ifp)
        !          2688: {
        !          2689:        struct wi_softc         *sc;
        !          2690:
        !          2691:        sc = ifp->if_softc;
        !          2692:
        !          2693:        printf(WI_PRT_FMT ": device timeout\n", WI_PRT_ARG(sc));
        !          2694:
        !          2695:        wi_cor_reset(sc);
        !          2696:        wi_init(sc);
        !          2697:
        !          2698:        ifp->if_oerrors++;
        !          2699:
        !          2700:        return;
        !          2701: }
        !          2702:
        !          2703: void
        !          2704: wi_detach(struct wi_softc *sc)
        !          2705: {
        !          2706:        struct ifnet *ifp;
        !          2707:        ifp = &sc->sc_ic.ic_if;
        !          2708:
        !          2709:        if (ifp->if_flags & IFF_RUNNING)
        !          2710:                wi_stop(sc);
        !          2711:
        !          2712:        if (sc->wi_flags & WI_FLAGS_ATTACHED) {
        !          2713:                sc->wi_flags &= ~WI_FLAGS_ATTACHED;
        !          2714:                if (sc->sc_sdhook != NULL)
        !          2715:                        shutdownhook_disestablish(sc->sc_sdhook);
        !          2716:        }
        !          2717: }
        !          2718:
        !          2719: STATIC void
        !          2720: wi_shutdown(void *arg)
        !          2721: {
        !          2722:        struct wi_softc         *sc;
        !          2723:
        !          2724:        sc = arg;
        !          2725:        wi_stop(sc);
        !          2726:
        !          2727:        return;
        !          2728: }
        !          2729:
        !          2730: STATIC void
        !          2731: wi_get_id(struct wi_softc *sc)
        !          2732: {
        !          2733:        struct wi_ltv_ver               ver;
        !          2734:        const struct wi_card_ident      *id;
        !          2735:        u_int16_t                       pri_fw_ver[3];
        !          2736:        const char                      *card_name;
        !          2737:        u_int16_t                       card_id;
        !          2738:
        !          2739:        /* get chip identity */
        !          2740:        bzero(&ver, sizeof(ver));
        !          2741:        ver.wi_type = WI_RID_CARD_ID;
        !          2742:        ver.wi_len = 5;
        !          2743:        wi_read_record(sc, (struct wi_ltv_gen *)&ver);
        !          2744:        card_id = letoh16(ver.wi_ver[0]);
        !          2745:        for (id = wi_card_ident; id->firm_type != WI_NOTYPE; id++) {
        !          2746:                if (card_id == id->card_id)
        !          2747:                        break;
        !          2748:        }
        !          2749:        if (id->firm_type != WI_NOTYPE) {
        !          2750:                sc->sc_firmware_type = id->firm_type;
        !          2751:                card_name = id->card_name;
        !          2752:        } else if (ver.wi_ver[0] & htole16(0x8000)) {
        !          2753:                sc->sc_firmware_type = WI_INTERSIL;
        !          2754:                card_name = "Unknown PRISM2 chip";
        !          2755:        } else {
        !          2756:                sc->sc_firmware_type = WI_LUCENT;
        !          2757:        }
        !          2758:
        !          2759:        /* get primary firmware version (XXX - how to do Lucent?) */
        !          2760:        if (sc->sc_firmware_type != WI_LUCENT) {
        !          2761:                bzero(&ver, sizeof(ver));
        !          2762:                ver.wi_type = WI_RID_PRI_IDENTITY;
        !          2763:                ver.wi_len = 5;
        !          2764:                wi_read_record(sc, (struct wi_ltv_gen *)&ver);
        !          2765:                pri_fw_ver[0] = letoh16(ver.wi_ver[2]);
        !          2766:                pri_fw_ver[1] = letoh16(ver.wi_ver[3]);
        !          2767:                pri_fw_ver[2] = letoh16(ver.wi_ver[1]);
        !          2768:        }
        !          2769:
        !          2770:        /* get station firmware version */
        !          2771:        bzero(&ver, sizeof(ver));
        !          2772:        ver.wi_type = WI_RID_STA_IDENTITY;
        !          2773:        ver.wi_len = 5;
        !          2774:        wi_read_record(sc, (struct wi_ltv_gen *)&ver);
        !          2775:        ver.wi_ver[1] = letoh16(ver.wi_ver[1]);
        !          2776:        ver.wi_ver[2] = letoh16(ver.wi_ver[2]);
        !          2777:        ver.wi_ver[3] = letoh16(ver.wi_ver[3]);
        !          2778:        sc->sc_sta_firmware_ver = ver.wi_ver[2] * 10000 +
        !          2779:            ver.wi_ver[3] * 100 + ver.wi_ver[1];
        !          2780:
        !          2781:        if (sc->sc_firmware_type == WI_INTERSIL &&
        !          2782:            (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
        !          2783:                struct wi_ltv_str sver;
        !          2784:                char *p;
        !          2785:
        !          2786:                bzero(&sver, sizeof(sver));
        !          2787:                sver.wi_type = WI_RID_SYMBOL_IDENTITY;
        !          2788:                sver.wi_len = 7;
        !          2789:                /* value should be something like "V2.00-11" */
        !          2790:                if (wi_read_record(sc, (struct wi_ltv_gen *)&sver) == 0 &&
        !          2791:                    *(p = (char *)sver.wi_str) >= 'A' &&
        !          2792:                    p[2] == '.' && p[5] == '-' && p[8] == '\0') {
        !          2793:                        sc->sc_firmware_type = WI_SYMBOL;
        !          2794:                        sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
        !          2795:                            (p[3] - '0') * 1000 + (p[4] - '0') * 100 +
        !          2796:                            (p[6] - '0') * 10 + (p[7] - '0');
        !          2797:                }
        !          2798:        }
        !          2799:
        !          2800:        if (sc->sc_firmware_type == WI_LUCENT) {
        !          2801:                printf("%s: Firmware %d.%02d variant %d, ", WI_PRT_ARG(sc),
        !          2802:                    ver.wi_ver[2], ver.wi_ver[3], ver.wi_ver[1]);
        !          2803:        } else {
        !          2804:                printf("%s: %s%s (0x%04x), Firmware %d.%d.%d (primary), %d.%d.%d (station), ",
        !          2805:                    WI_PRT_ARG(sc),
        !          2806:                    sc->sc_firmware_type == WI_SYMBOL ? "Symbol " : "",
        !          2807:                    card_name, card_id, pri_fw_ver[0], pri_fw_ver[1],
        !          2808:                    pri_fw_ver[2], sc->sc_sta_firmware_ver / 10000,
        !          2809:                    (sc->sc_sta_firmware_ver % 10000) / 100,
        !          2810:                    sc->sc_sta_firmware_ver % 100);
        !          2811:        }
        !          2812: }
        !          2813:
        !          2814: STATIC int
        !          2815: wi_sync_media(struct wi_softc *sc, int ptype, int txrate)
        !          2816: {
        !          2817:        int media = sc->sc_media.ifm_cur->ifm_media;
        !          2818:        int options = IFM_OPTIONS(media);
        !          2819:        int subtype;
        !          2820:
        !          2821:        switch (txrate) {
        !          2822:        case 1:
        !          2823:                subtype = IFM_IEEE80211_DS1;
        !          2824:                break;
        !          2825:        case 2:
        !          2826:                subtype = IFM_IEEE80211_DS2;
        !          2827:                break;
        !          2828:        case 3:
        !          2829:                subtype = IFM_AUTO;
        !          2830:                break;
        !          2831:        case 5:
        !          2832:                subtype = IFM_IEEE80211_DS5;
        !          2833:                break;
        !          2834:        case 11:
        !          2835:                subtype = IFM_IEEE80211_DS11;
        !          2836:                break;
        !          2837:        default:
        !          2838:                subtype = IFM_MANUAL;           /* Unable to represent */
        !          2839:                break;
        !          2840:        }
        !          2841:
        !          2842:        options &= ~IFM_OMASK;
        !          2843:        switch (ptype) {
        !          2844:        case WI_PORTTYPE_BSS:
        !          2845:                /* default port type */
        !          2846:                break;
        !          2847:        case WI_PORTTYPE_ADHOC:
        !          2848:                options |= IFM_IEEE80211_ADHOC;
        !          2849:                break;
        !          2850:        case WI_PORTTYPE_HOSTAP:
        !          2851:                options |= IFM_IEEE80211_HOSTAP;
        !          2852:                break;
        !          2853:        case WI_PORTTYPE_IBSS:
        !          2854:                if (sc->wi_create_ibss)
        !          2855:                        options |= IFM_IEEE80211_IBSSMASTER;
        !          2856:                else
        !          2857:                        options |= IFM_IEEE80211_IBSS;
        !          2858:                break;
        !          2859:        default:
        !          2860:                subtype = IFM_MANUAL;           /* Unable to represent */
        !          2861:                break;
        !          2862:        }
        !          2863:        media = IFM_MAKEWORD(IFM_TYPE(media), subtype, options,
        !          2864:        IFM_INST(media));
        !          2865:        if (ifmedia_match(&sc->sc_media, media, sc->sc_media.ifm_mask) == NULL)
        !          2866:                return (EINVAL);
        !          2867:        ifmedia_set(&sc->sc_media, media);
        !          2868:        sc->wi_ptype = ptype;
        !          2869:        sc->wi_tx_rate = txrate;
        !          2870:        return (0);
        !          2871: }
        !          2872:
        !          2873: STATIC int
        !          2874: wi_media_change(struct ifnet *ifp)
        !          2875: {
        !          2876:        struct wi_softc *sc = ifp->if_softc;
        !          2877:        int otype = sc->wi_ptype;
        !          2878:        int orate = sc->wi_tx_rate;
        !          2879:        int ocreate_ibss = sc->wi_create_ibss;
        !          2880:
        !          2881:        if ((sc->sc_media.ifm_cur->ifm_media & IFM_IEEE80211_HOSTAP) &&
        !          2882:            sc->sc_firmware_type != WI_INTERSIL)
        !          2883:                return (EINVAL);
        !          2884:
        !          2885:        sc->wi_create_ibss = 0;
        !          2886:
        !          2887:        switch (sc->sc_media.ifm_cur->ifm_media & IFM_OMASK) {
        !          2888:        case 0:
        !          2889:                sc->wi_ptype = WI_PORTTYPE_BSS;
        !          2890:                break;
        !          2891:        case IFM_IEEE80211_ADHOC:
        !          2892:                sc->wi_ptype = WI_PORTTYPE_ADHOC;
        !          2893:                break;
        !          2894:        case IFM_IEEE80211_HOSTAP:
        !          2895:                sc->wi_ptype = WI_PORTTYPE_HOSTAP;
        !          2896:                break;
        !          2897:        case IFM_IEEE80211_IBSSMASTER:
        !          2898:        case IFM_IEEE80211_IBSSMASTER|IFM_IEEE80211_IBSS:
        !          2899:                if (!(sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS))
        !          2900:                        return (EINVAL);
        !          2901:                sc->wi_create_ibss = 1;
        !          2902:                /* FALLTHROUGH */
        !          2903:        case IFM_IEEE80211_IBSS:
        !          2904:                sc->wi_ptype = WI_PORTTYPE_IBSS;
        !          2905:                break;
        !          2906:        default:
        !          2907:                /* Invalid combination. */
        !          2908:                return (EINVAL);
        !          2909:        }
        !          2910:
        !          2911:        switch (IFM_SUBTYPE(sc->sc_media.ifm_cur->ifm_media)) {
        !          2912:        case IFM_IEEE80211_DS1:
        !          2913:                sc->wi_tx_rate = 1;
        !          2914:                break;
        !          2915:        case IFM_IEEE80211_DS2:
        !          2916:                sc->wi_tx_rate = 2;
        !          2917:                break;
        !          2918:        case IFM_AUTO:
        !          2919:                sc->wi_tx_rate = 3;
        !          2920:                break;
        !          2921:        case IFM_IEEE80211_DS5:
        !          2922:                sc->wi_tx_rate = 5;
        !          2923:                break;
        !          2924:        case IFM_IEEE80211_DS11:
        !          2925:                sc->wi_tx_rate = 11;
        !          2926:                break;
        !          2927:        }
        !          2928:
        !          2929:        if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
        !          2930:                if (otype != sc->wi_ptype || orate != sc->wi_tx_rate ||
        !          2931:                    ocreate_ibss != sc->wi_create_ibss)
        !          2932:                        wi_init(sc);
        !          2933:        }
        !          2934:
        !          2935:        ifp->if_baudrate = ifmedia_baudrate(sc->sc_media.ifm_cur->ifm_media);
        !          2936:
        !          2937:        return (0);
        !          2938: }
        !          2939:
        !          2940: STATIC void
        !          2941: wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
        !          2942: {
        !          2943:        struct wi_softc *sc = ifp->if_softc;
        !          2944:        struct wi_req wreq;
        !          2945:
        !          2946:        if (!(sc->sc_ic.ic_if.if_flags & IFF_UP)) {
        !          2947:                imr->ifm_active = IFM_IEEE80211|IFM_NONE;
        !          2948:                imr->ifm_status = 0;
        !          2949:                return;
        !          2950:        }
        !          2951:
        !          2952:        if (sc->wi_tx_rate == 3) {
        !          2953:                imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
        !          2954:
        !          2955:                wreq.wi_type = WI_RID_CUR_TX_RATE;
        !          2956:                wreq.wi_len = WI_MAX_DATALEN;
        !          2957:                if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0) {
        !          2958:                        switch (letoh16(wreq.wi_val[0])) {
        !          2959:                        case 1:
        !          2960:                                imr->ifm_active |= IFM_IEEE80211_DS1;
        !          2961:                                break;
        !          2962:                        case 2:
        !          2963:                                imr->ifm_active |= IFM_IEEE80211_DS2;
        !          2964:                                break;
        !          2965:                        case 6:
        !          2966:                                imr->ifm_active |= IFM_IEEE80211_DS5;
        !          2967:                                break;
        !          2968:                        case 11:
        !          2969:                                imr->ifm_active |= IFM_IEEE80211_DS11;
        !          2970:                                break;
        !          2971:                        }
        !          2972:                }
        !          2973:        } else {
        !          2974:                imr->ifm_active = sc->sc_media.ifm_cur->ifm_media;
        !          2975:        }
        !          2976:
        !          2977:        imr->ifm_status = IFM_AVALID;
        !          2978:        switch (sc->wi_ptype) {
        !          2979:        case WI_PORTTYPE_ADHOC:
        !          2980:        case WI_PORTTYPE_IBSS:
        !          2981:                /*
        !          2982:                 * XXX: It would be nice if we could give some actually
        !          2983:                 * useful status like whether we joined another IBSS or
        !          2984:                 * created one ourselves.
        !          2985:                 */
        !          2986:                /* FALLTHROUGH */
        !          2987:        case WI_PORTTYPE_HOSTAP:
        !          2988:                imr->ifm_status |= IFM_ACTIVE;
        !          2989:                break;
        !          2990:        default:
        !          2991:                wreq.wi_type = WI_RID_COMMQUAL;
        !          2992:                wreq.wi_len = WI_MAX_DATALEN;
        !          2993:                if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq) == 0 &&
        !          2994:                    letoh16(wreq.wi_val[0]) != 0)
        !          2995:                        imr->ifm_status |= IFM_ACTIVE;
        !          2996:        }
        !          2997: }
        !          2998:
        !          2999: STATIC int
        !          3000: wi_set_nwkey(struct wi_softc *sc, struct ieee80211_nwkey *nwkey)
        !          3001: {
        !          3002:        int i, len, error;
        !          3003:        struct wi_req wreq;
        !          3004:        struct wi_ltv_keys *wk = (struct wi_ltv_keys *)&wreq;
        !          3005:
        !          3006:        if (!(sc->wi_flags & WI_FLAGS_HAS_WEP))
        !          3007:                return ENODEV;
        !          3008:        if (nwkey->i_defkid <= 0 || nwkey->i_defkid > IEEE80211_WEP_NKID)
        !          3009:                return EINVAL;
        !          3010:        memcpy(wk, &sc->wi_keys, sizeof(*wk));
        !          3011:        for (i = 0; i < IEEE80211_WEP_NKID; i++) {
        !          3012:                if (nwkey->i_key[i].i_keydat == NULL)
        !          3013:                        continue;
        !          3014:                len = nwkey->i_key[i].i_keylen;
        !          3015:                if (len > sizeof(wk->wi_keys[i].wi_keydat))
        !          3016:                        return EINVAL;
        !          3017:                error = copyin(nwkey->i_key[i].i_keydat,
        !          3018:                    wk->wi_keys[i].wi_keydat, len);
        !          3019:                if (error)
        !          3020:                        return error;
        !          3021:                wk->wi_keys[i].wi_keylen = htole16(len);
        !          3022:        }
        !          3023:
        !          3024:        wk->wi_len = (sizeof(*wk) / 2) + 1;
        !          3025:        wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
        !          3026:        if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
        !          3027:                error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
        !          3028:                if (error)
        !          3029:                        return error;
        !          3030:        }
        !          3031:        if ((error = wi_setdef(sc, &wreq)))
        !          3032:                return (error);
        !          3033:
        !          3034:        wreq.wi_len = 2;
        !          3035:        wreq.wi_type = WI_RID_TX_CRYPT_KEY;
        !          3036:        wreq.wi_val[0] = htole16(nwkey->i_defkid - 1);
        !          3037:        if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
        !          3038:                error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
        !          3039:                if (error)
        !          3040:                        return error;
        !          3041:        }
        !          3042:        if ((error = wi_setdef(sc, &wreq)))
        !          3043:                return (error);
        !          3044:
        !          3045:        wreq.wi_type = WI_RID_ENCRYPTION;
        !          3046:        wreq.wi_val[0] = htole16(nwkey->i_wepon);
        !          3047:        if (sc->sc_ic.ic_if.if_flags & IFF_UP) {
        !          3048:                error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
        !          3049:                if (error)
        !          3050:                        return error;
        !          3051:        }
        !          3052:        if ((error = wi_setdef(sc, &wreq)))
        !          3053:                return (error);
        !          3054:
        !          3055:        if (sc->sc_ic.ic_if.if_flags & IFF_UP)
        !          3056:                wi_init(sc);
        !          3057:        return 0;
        !          3058: }
        !          3059:
        !          3060: STATIC int
        !          3061: wi_get_nwkey(struct wi_softc *sc, struct ieee80211_nwkey *nwkey)
        !          3062: {
        !          3063:        int i, len, error;
        !          3064:        struct wi_ltv_keys *wk = &sc->wi_keys;
        !          3065:
        !          3066:        if (!(sc->wi_flags & WI_FLAGS_HAS_WEP))
        !          3067:                return ENODEV;
        !          3068:        nwkey->i_wepon = sc->wi_use_wep;
        !          3069:        nwkey->i_defkid = sc->wi_tx_key + 1;
        !          3070:
        !          3071:        /* do not show any keys to non-root user */
        !          3072:        error = suser(curproc, 0);
        !          3073:        for (i = 0; i < IEEE80211_WEP_NKID; i++) {
        !          3074:                if (nwkey->i_key[i].i_keydat == NULL)
        !          3075:                        continue;
        !          3076:                /* error holds results of suser() for the first time */
        !          3077:                if (error)
        !          3078:                        return error;
        !          3079:                len = letoh16(wk->wi_keys[i].wi_keylen);
        !          3080:                if (nwkey->i_key[i].i_keylen < len)
        !          3081:                        return ENOSPC;
        !          3082:                nwkey->i_key[i].i_keylen = len;
        !          3083:                error = copyout(wk->wi_keys[i].wi_keydat,
        !          3084:                    nwkey->i_key[i].i_keydat, len);
        !          3085:                if (error)
        !          3086:                        return error;
        !          3087:        }
        !          3088:        return 0;
        !          3089: }
        !          3090:
        !          3091: STATIC int
        !          3092: wi_set_pm(struct wi_softc *sc, struct ieee80211_power *power)
        !          3093: {
        !          3094:
        !          3095:        sc->wi_pm_enabled = power->i_enabled;
        !          3096:        sc->wi_max_sleep = power->i_maxsleep;
        !          3097:
        !          3098:        if (sc->sc_ic.ic_if.if_flags & IFF_UP)
        !          3099:                wi_init(sc);
        !          3100:
        !          3101:        return (0);
        !          3102: }
        !          3103:
        !          3104: STATIC int
        !          3105: wi_get_pm(struct wi_softc *sc, struct ieee80211_power *power)
        !          3106: {
        !          3107:
        !          3108:        power->i_enabled = sc->wi_pm_enabled;
        !          3109:        power->i_maxsleep = sc->wi_max_sleep;
        !          3110:
        !          3111:        return (0);
        !          3112: }
        !          3113:
        !          3114: STATIC int
        !          3115: wi_set_txpower(struct wi_softc *sc, struct ieee80211_txpower *txpower)
        !          3116: {
        !          3117:        u_int16_t       cmd;
        !          3118:        u_int16_t       power;
        !          3119:        int8_t          tmp;
        !          3120:        int             error;
        !          3121:        int             alc;
        !          3122:
        !          3123:        if (txpower == NULL) {
        !          3124:                if (!(sc->wi_flags & WI_FLAGS_TXPOWER))
        !          3125:                        return (EINVAL);
        !          3126:                alc = 0;                /* disable ALC */
        !          3127:        } else {
        !          3128:                if (txpower->i_mode == IEEE80211_TXPOWER_MODE_AUTO) {
        !          3129:                        alc = 1;        /* enable ALC */
        !          3130:                        sc->wi_flags &= ~WI_FLAGS_TXPOWER;
        !          3131:                } else {
        !          3132:                        alc = 0;        /* disable ALC */
        !          3133:                        sc->wi_flags |= WI_FLAGS_TXPOWER;
        !          3134:                        sc->wi_txpower = txpower->i_val;
        !          3135:                }
        !          3136:        }
        !          3137:
        !          3138:        /* Set ALC */
        !          3139:        cmd = WI_CMD_DEBUG | (WI_DEBUG_CONFBITS << 8);
        !          3140:        if ((error = wi_cmd(sc, cmd, alc, 0x8, 0)) != 0)
        !          3141:                return (error);
        !          3142:
        !          3143:        /* No need to set the TX power value if ALC is enabled */
        !          3144:        if (alc)
        !          3145:                return (0);
        !          3146:
        !          3147:        /* Convert dBM to internal TX power value */
        !          3148:        if (sc->wi_txpower > 20)
        !          3149:                power = 128;
        !          3150:        else if (sc->wi_txpower < -43)
        !          3151:                power = 127;
        !          3152:        else {
        !          3153:                tmp = sc->wi_txpower;
        !          3154:                tmp = -12 - tmp;
        !          3155:                tmp <<= 2;
        !          3156:
        !          3157:                power = (u_int16_t)tmp;
        !          3158:        }
        !          3159:
        !          3160:        /* Set manual TX power */
        !          3161:        cmd = WI_CMD_WRITE_MIF;
        !          3162:        if ((error = wi_cmd(sc, cmd,
        !          3163:                 WI_HFA384X_CR_MANUAL_TX_POWER, power, 0)) != 0)
        !          3164:                return (error);
        !          3165:
        !          3166:        if (sc->sc_ic.ic_if.if_flags & IFF_DEBUG)
        !          3167:                printf("%s: %u (%d dBm)\n", sc->sc_dev.dv_xname, power,
        !          3168:                    sc->wi_txpower);
        !          3169:
        !          3170:        return (0);
        !          3171: }
        !          3172:
        !          3173: STATIC int
        !          3174: wi_get_txpower(struct wi_softc *sc, struct ieee80211_txpower *txpower)
        !          3175: {
        !          3176:        u_int16_t       cmd;
        !          3177:        u_int16_t       power;
        !          3178:        int8_t          tmp;
        !          3179:        int             error;
        !          3180:
        !          3181:        if (sc->wi_flags & WI_FLAGS_BUS_USB)
        !          3182:                return (EOPNOTSUPP);
        !          3183:
        !          3184:        /* Get manual TX power */
        !          3185:        cmd = WI_CMD_READ_MIF;
        !          3186:        if ((error = wi_cmd(sc, cmd,
        !          3187:                 WI_HFA384X_CR_MANUAL_TX_POWER, 0, 0)) != 0)
        !          3188:                return (error);
        !          3189:
        !          3190:        power = CSR_READ_2(sc, WI_RESP0);
        !          3191:
        !          3192:        /* Convert internal TX power value to dBM */
        !          3193:        if (power > 255)
        !          3194:                txpower->i_val = 255;
        !          3195:        else {
        !          3196:                tmp = power;
        !          3197:                tmp >>= 2;
        !          3198:                txpower->i_val = (u_int16_t)(-12 - tmp);
        !          3199:        }
        !          3200:
        !          3201:        if (sc->wi_flags & WI_FLAGS_TXPOWER)
        !          3202:                txpower->i_mode = IEEE80211_TXPOWER_MODE_FIXED;
        !          3203:        else
        !          3204:                txpower->i_mode = IEEE80211_TXPOWER_MODE_AUTO;
        !          3205:
        !          3206:        return (0);
        !          3207: }
        !          3208:
        !          3209: STATIC int
        !          3210: wi_set_ssid(struct ieee80211_nwid *ws, u_int8_t *id, int len)
        !          3211: {
        !          3212:
        !          3213:        if (len > IEEE80211_NWID_LEN)
        !          3214:                return (EINVAL);
        !          3215:        ws->i_len = len;
        !          3216:        memcpy(ws->i_nwid, id, len);
        !          3217:        return (0);
        !          3218: }
        !          3219:
        !          3220: STATIC int
        !          3221: wi_get_debug(struct wi_softc *sc, struct wi_req *wreq)
        !          3222: {
        !          3223:        int                     error = 0;
        !          3224:
        !          3225:        wreq->wi_len = 1;
        !          3226:
        !          3227:        switch (wreq->wi_type) {
        !          3228:        case WI_DEBUG_SLEEP:
        !          3229:                wreq->wi_len++;
        !          3230:                wreq->wi_val[0] = htole16(sc->wi_debug.wi_sleep);
        !          3231:                break;
        !          3232:        case WI_DEBUG_DELAYSUPP:
        !          3233:                wreq->wi_len++;
        !          3234:                wreq->wi_val[0] = htole16(sc->wi_debug.wi_delaysupp);
        !          3235:                break;
        !          3236:        case WI_DEBUG_TXSUPP:
        !          3237:                wreq->wi_len++;
        !          3238:                wreq->wi_val[0] = htole16(sc->wi_debug.wi_txsupp);
        !          3239:                break;
        !          3240:        case WI_DEBUG_MONITOR:
        !          3241:                wreq->wi_len++;
        !          3242:                wreq->wi_val[0] = htole16(sc->wi_debug.wi_monitor);
        !          3243:                break;
        !          3244:        case WI_DEBUG_LEDTEST:
        !          3245:                wreq->wi_len += 3;
        !          3246:                wreq->wi_val[0] = htole16(sc->wi_debug.wi_ledtest);
        !          3247:                wreq->wi_val[1] = htole16(sc->wi_debug.wi_ledtest_param0);
        !          3248:                wreq->wi_val[2] = htole16(sc->wi_debug.wi_ledtest_param1);
        !          3249:                break;
        !          3250:        case WI_DEBUG_CONTTX:
        !          3251:                wreq->wi_len += 2;
        !          3252:                wreq->wi_val[0] = htole16(sc->wi_debug.wi_conttx);
        !          3253:                wreq->wi_val[1] = htole16(sc->wi_debug.wi_conttx_param0);
        !          3254:                break;
        !          3255:        case WI_DEBUG_CONTRX:
        !          3256:                wreq->wi_len++;
        !          3257:                wreq->wi_val[0] = htole16(sc->wi_debug.wi_contrx);
        !          3258:                break;
        !          3259:        case WI_DEBUG_SIGSTATE:
        !          3260:                wreq->wi_len += 2;
        !          3261:                wreq->wi_val[0] = htole16(sc->wi_debug.wi_sigstate);
        !          3262:                wreq->wi_val[1] = htole16(sc->wi_debug.wi_sigstate_param0);
        !          3263:                break;
        !          3264:        case WI_DEBUG_CONFBITS:
        !          3265:                wreq->wi_len += 2;
        !          3266:                wreq->wi_val[0] = htole16(sc->wi_debug.wi_confbits);
        !          3267:                wreq->wi_val[1] = htole16(sc->wi_debug.wi_confbits_param0);
        !          3268:                break;
        !          3269:        default:
        !          3270:                error = EIO;
        !          3271:                break;
        !          3272:        }
        !          3273:
        !          3274:        return (error);
        !          3275: }
        !          3276:
        !          3277: STATIC int
        !          3278: wi_set_debug(struct wi_softc *sc, struct wi_req *wreq)
        !          3279: {
        !          3280:        int                             error = 0;
        !          3281:        u_int16_t                       cmd, param0 = 0, param1 = 0;
        !          3282:
        !          3283:        switch (wreq->wi_type) {
        !          3284:        case WI_DEBUG_RESET:
        !          3285:        case WI_DEBUG_INIT:
        !          3286:        case WI_DEBUG_CALENABLE:
        !          3287:                break;
        !          3288:        case WI_DEBUG_SLEEP:
        !          3289:                sc->wi_debug.wi_sleep = 1;
        !          3290:                break;
        !          3291:        case WI_DEBUG_WAKE:
        !          3292:                sc->wi_debug.wi_sleep = 0;
        !          3293:                break;
        !          3294:        case WI_DEBUG_CHAN:
        !          3295:                param0 = letoh16(wreq->wi_val[0]);
        !          3296:                break;
        !          3297:        case WI_DEBUG_DELAYSUPP:
        !          3298:                sc->wi_debug.wi_delaysupp = 1;
        !          3299:                break;
        !          3300:        case WI_DEBUG_TXSUPP:
        !          3301:                sc->wi_debug.wi_txsupp = 1;
        !          3302:                break;
        !          3303:        case WI_DEBUG_MONITOR:
        !          3304:                sc->wi_debug.wi_monitor = 1;
        !          3305:                break;
        !          3306:        case WI_DEBUG_LEDTEST:
        !          3307:                param0 = letoh16(wreq->wi_val[0]);
        !          3308:                param1 = letoh16(wreq->wi_val[1]);
        !          3309:                sc->wi_debug.wi_ledtest = 1;
        !          3310:                sc->wi_debug.wi_ledtest_param0 = param0;
        !          3311:                sc->wi_debug.wi_ledtest_param1 = param1;
        !          3312:                break;
        !          3313:        case WI_DEBUG_CONTTX:
        !          3314:                param0 = letoh16(wreq->wi_val[0]);
        !          3315:                sc->wi_debug.wi_conttx = 1;
        !          3316:                sc->wi_debug.wi_conttx_param0 = param0;
        !          3317:                break;
        !          3318:        case WI_DEBUG_STOPTEST:
        !          3319:                sc->wi_debug.wi_delaysupp = 0;
        !          3320:                sc->wi_debug.wi_txsupp = 0;
        !          3321:                sc->wi_debug.wi_monitor = 0;
        !          3322:                sc->wi_debug.wi_ledtest = 0;
        !          3323:                sc->wi_debug.wi_ledtest_param0 = 0;
        !          3324:                sc->wi_debug.wi_ledtest_param1 = 0;
        !          3325:                sc->wi_debug.wi_conttx = 0;
        !          3326:                sc->wi_debug.wi_conttx_param0 = 0;
        !          3327:                sc->wi_debug.wi_contrx = 0;
        !          3328:                sc->wi_debug.wi_sigstate = 0;
        !          3329:                sc->wi_debug.wi_sigstate_param0 = 0;
        !          3330:                break;
        !          3331:        case WI_DEBUG_CONTRX:
        !          3332:                sc->wi_debug.wi_contrx = 1;
        !          3333:                break;
        !          3334:        case WI_DEBUG_SIGSTATE:
        !          3335:                param0 = letoh16(wreq->wi_val[0]);
        !          3336:                sc->wi_debug.wi_sigstate = 1;
        !          3337:                sc->wi_debug.wi_sigstate_param0 = param0;
        !          3338:                break;
        !          3339:        case WI_DEBUG_CONFBITS:
        !          3340:                param0 = letoh16(wreq->wi_val[0]);
        !          3341:                param1 = letoh16(wreq->wi_val[1]);
        !          3342:                sc->wi_debug.wi_confbits = param0;
        !          3343:                sc->wi_debug.wi_confbits_param0 = param1;
        !          3344:                break;
        !          3345:        default:
        !          3346:                error = EIO;
        !          3347:                break;
        !          3348:        }
        !          3349:
        !          3350:        if (error)
        !          3351:                return (error);
        !          3352:
        !          3353:        cmd = WI_CMD_DEBUG | (wreq->wi_type << 8);
        !          3354:        error = wi_cmd(sc, cmd, param0, param1, 0);
        !          3355:
        !          3356:        return (error);
        !          3357: }

CVSweb