[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

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