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

Annotation of sys/dev/usb/if_wi_usb.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_wi_usb.c,v 1.42 2007/06/14 10:11:15 mbalmer Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2003 Dale Rahn. All rights reserved.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  * 1. Redistributions of source code must retain the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  *
        !            15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            16:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            17:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            18:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            19:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            20:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            21:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            22:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            23:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            24:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            25:  *
        !            26:  * Effort sponsored in part by the Defense Advanced Research Projects
        !            27:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
        !            28:  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
        !            29:  */
        !            30: #include "bpfilter.h"
        !            31:
        !            32: #include <sys/param.h>
        !            33: #include <sys/systm.h>
        !            34: #include <sys/sockio.h>
        !            35: #include <sys/mbuf.h>
        !            36: #include <sys/malloc.h>
        !            37: #include <sys/kernel.h>
        !            38: #include <sys/proc.h>
        !            39: #include <sys/socket.h>
        !            40: #include <sys/device.h>
        !            41: #include <sys/kthread.h>
        !            42: #include <sys/tree.h>
        !            43:
        !            44: #include <net/if.h>
        !            45: #include <net/if_dl.h>
        !            46: #include <net/if_media.h>
        !            47: #include <net/if_types.h>
        !            48:
        !            49: #ifdef INET
        !            50: #include <netinet/in.h>
        !            51: #include <netinet/in_systm.h>
        !            52: #include <netinet/in_var.h>
        !            53: #include <netinet/ip.h>
        !            54: #include <netinet/if_ether.h>
        !            55: #endif
        !            56:
        !            57: #include <dev/usb/usb.h>
        !            58: #include <dev/usb/usbdi.h>
        !            59: #include <dev/usb/usbdi_util.h>
        !            60: #include <dev/usb/usbdevs.h>
        !            61:
        !            62: #define ROUNDUP64(x) (((x)+63) & ~63)
        !            63:
        !            64: #include <net80211/ieee80211_var.h>
        !            65: #include <net80211/ieee80211_ioctl.h>
        !            66:
        !            67: #if NBPFILTER > 0
        !            68: #include <net/bpf.h>
        !            69: #endif
        !            70:
        !            71: #include <machine/bus.h>
        !            72:
        !            73: #include <dev/rndvar.h>
        !            74:
        !            75: #include <dev/ic/if_wireg.h>
        !            76: #include <dev/ic/if_wi_ieee.h>
        !            77: #include <dev/ic/if_wivar.h>
        !            78:
        !            79: #include <dev/usb/if_wi_usb.h>
        !            80:
        !            81: int wi_usb_do_transmit_sync(struct wi_usb_softc *wsc, struct wi_usb_chain *c,
        !            82:     void *ident);
        !            83: void wi_usb_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
        !            84:     usbd_status status);
        !            85: void wi_usb_txeof_frm(usbd_xfer_handle xfer, usbd_private_handle priv,
        !            86:     usbd_status status);
        !            87: void wi_usb_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv,
        !            88:     usbd_status status);
        !            89: void wi_usb_intr(usbd_xfer_handle xfer, usbd_private_handle priv,
        !            90:     usbd_status status);
        !            91: void wi_usb_stop(struct wi_usb_softc *usc);
        !            92: int wi_usb_tx_list_init(struct wi_usb_softc *usc);
        !            93: int wi_usb_rx_list_init(struct wi_usb_softc *usc);
        !            94: int wi_usb_open_pipes(struct wi_usb_softc *usc);
        !            95: void wi_usb_cmdresp(struct wi_usb_chain *c);
        !            96: void wi_usb_rridresp(struct wi_usb_chain *c);
        !            97: void wi_usb_wridresp(struct wi_usb_chain *c);
        !            98: void wi_usb_infofrm(struct wi_usb_chain *c, int len);
        !            99: int wi_send_packet(struct wi_usb_softc *sc, int id);
        !           100: void wi_usb_rxfrm(struct wi_usb_softc *usc, wi_usb_usbin *uin, int total_len);
        !           101: void wi_usb_txfrm(struct wi_usb_softc *usc, wi_usb_usbin *uin, int total_len);
        !           102: void wi_usb_start_thread(void *);
        !           103:
        !           104: int wi_usb_tx_lock_try(struct wi_usb_softc *sc);
        !           105: void wi_usb_tx_lock(struct wi_usb_softc *usc);
        !           106: void wi_usb_tx_unlock(struct wi_usb_softc *usc);
        !           107: void wi_usb_ctl_lock(struct wi_usb_softc *usc);
        !           108: void wi_usb_ctl_unlock(struct wi_usb_softc *usc);
        !           109:
        !           110: void wi_dump_data(void *buffer, int len);
        !           111:
        !           112: void wi_usb_thread(void *arg);
        !           113:
        !           114: #ifdef WI_USB_DEBUG
        !           115: #define DPRINTF(x)      do { if (wi_usbdebug) printf x; } while (0)
        !           116: #define DPRINTFN(n,x)   do { if (wi_usbdebug >= (n)) printf x; } while (0)
        !           117: int     wi_usbdebug = 1;
        !           118: #else
        !           119: #define DPRINTF(x)
        !           120: #define DPRINTFN(n,x)
        !           121: #endif
        !           122:
        !           123: struct wi_usb_thread_info {
        !           124:        int status;
        !           125:        int dying;
        !           126:        int idle;
        !           127: };
        !           128:
        !           129: /* thread status flags */
        !           130: #define WI_START       0x01
        !           131: #define WI_DYING       0x02
        !           132: #define WI_INQUIRE     0x04
        !           133: #define WI_WATCHDOG    0x08
        !           134:
        !           135:
        !           136: struct wi_usb_softc {
        !           137:        struct wi_softc         sc_wi;
        !           138: #define wi_usb_dev sc_wi.sc_dev
        !           139:
        !           140:        struct timeout          wi_usb_stat_ch;
        !           141:
        !           142:        usbd_device_handle      wi_usb_udev;
        !           143:        usbd_interface_handle   wi_usb_iface;
        !           144:        u_int16_t               wi_usb_vendor;
        !           145:        u_int16_t               wi_usb_product;
        !           146:        int                     wi_usb_ed[WI_USB_ENDPT_MAX];
        !           147:        usbd_pipe_handle        wi_usb_ep[WI_USB_ENDPT_MAX];
        !           148:
        !           149:        struct wi_usb_chain     wi_usb_tx_chain[WI_USB_TX_LIST_CNT];
        !           150:        struct wi_usb_chain     wi_usb_rx_chain[WI_USB_RX_LIST_CNT];
        !           151:
        !           152:        int                     wi_usb_refcnt;
        !           153:        char                    wi_usb_dying;
        !           154:        char                    wi_usb_attached;
        !           155:        int                     wi_usb_intr_errs;
        !           156:        struct timeval          wi_usb_rx_notice;
        !           157:
        !           158:        int                     wi_usb_pollpending;
        !           159:
        !           160:        wi_usb_usbin            wi_usb_ibuf;
        !           161:        int                     wi_usb_tx_prod;
        !           162:        int                     wi_usb_tx_cons;
        !           163:        int                     wi_usb_tx_cnt;
        !           164:        int                     wi_usb_rx_prod;
        !           165:
        !           166:        struct wi_ltv_gen       *ridltv;
        !           167:        int                     ridresperr;
        !           168:
        !           169:        int                     cmdresp;
        !           170:        int                     cmdresperr;
        !           171:        int                     txresp;
        !           172:        int                     txresperr;
        !           173:
        !           174:        /* nummem (tx/mgmt) */
        !           175:        int                     wi_usb_nummem;
        !           176: #define MAX_WI_NMEM 3
        !           177:        void                    *wi_usb_txmem[MAX_WI_NMEM];
        !           178:        int                     wi_usb_txmemsize[MAX_WI_NMEM];
        !           179:        void                    *wi_usb_rxmem;
        !           180:        int                     wi_usb_rxmemsize;
        !           181:
        !           182:        void                    *wi_info;
        !           183:        void                    *wi_rxframe;
        !           184:
        !           185:        /* prevent multiple outstanding USB requests */
        !           186:        int                     wi_lock;
        !           187:        int                     wi_lockwait;
        !           188:
        !           189:        /* prevent multiple command requests */
        !           190:        int                     wi_ctllock;
        !           191:        int                     wi_ctllockwait;
        !           192:        struct proc             *wi_curproc;
        !           193:
        !           194:        /* kthread */
        !           195:        struct wi_usb_thread_info       *wi_thread_info;
        !           196:        int                     wi_resetonce;
        !           197: };
        !           198:
        !           199: struct wi_funcs wi_func_usb = {
        !           200:         wi_cmd_usb,
        !           201:         wi_read_record_usb,
        !           202:         wi_write_record_usb,
        !           203:         wi_alloc_nicmem_usb,
        !           204:         wi_read_data_usb,
        !           205:         wi_write_data_usb,
        !           206:         wi_get_fid_usb,
        !           207:         wi_init_usb,
        !           208:
        !           209:         wi_start_usb,
        !           210:         wi_ioctl_usb,
        !           211:         wi_watchdog_usb,
        !           212:         wi_inquire_usb,
        !           213: };
        !           214:
        !           215: /*
        !           216:  * Various supported device vendors/products.
        !           217:  */
        !           218: const struct wi_usb_type {
        !           219:        struct usb_devno        wi_usb_device;
        !           220:        u_int16_t       wi_usb_flags;
        !           221:        /* XXX */
        !           222: } wi_usb_devs[] = {
        !           223:        {{ USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_111 }, 0 },
        !           224:        {{ USB_VENDOR_ACERW, USB_PRODUCT_ACERW_WARPLINK }, 0 },
        !           225:        {{ USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_FREELAN }, 0 },
        !           226:        {{ USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_PRISM_25 }, 0 },
        !           227:        {{ USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_PRISM_25A }, 0 },
        !           228:        {{ USB_VENDOR_ADAPTEC, USB_PRODUCT_ADAPTEC_AWN8020 }, 0 },
        !           229:        {{ USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_WLAN }, 0 },
        !           230:        {{ USB_VENDOR_ASUSTEK, USB_PRODUCT_ASUSTEK_WL140 }, 0 },
        !           231:        {{ USB_VENDOR_AVERATEC, USB_PRODUCT_AVERATEC_USBWLAN }, 0 },
        !           232:        {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_W100 }, 0 },
        !           233:        {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_W200 }, 0 },
        !           234:        {{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_WLANUSB }, 0 },
        !           235:        {{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_WLUSB_11_KEY }, 0 },
        !           236:        {{ USB_VENDOR_DELL, USB_PRODUCT_DELL_TM1180 }, 0 },
        !           237:        {{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWL120F }, 0 },
        !           238:        {{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWL122 }, 0 },
        !           239:        {{ USB_VENDOR_INTEL, USB_PRODUCT_INTEL_I2011B }, 0 },
        !           240:        {{ USB_VENDOR_INTERSIL, USB_PRODUCT_INTERSIL_PRISM_2X }, 0 },
        !           241:        {{ USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBWNB11 }, 0 },
        !           242:        {{ USB_VENDOR_JVC, USB_PRODUCT_JVC_MP_XP7250_WL }, 0 },
        !           243:        {{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_WUSB11_25 }, 0 },
        !           244:        {{ USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_WUSB12_11 }, 0 },
        !           245:        {{ USB_VENDOR_LINKSYS3, USB_PRODUCT_LINKSYS3_WUSB11V30 }, 0 },
        !           246:        {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KB11 }, 0 },
        !           247:        {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KS11G }, 0 },
        !           248:        {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_S11 }, 0 },
        !           249:        {{ USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_MN510 }, 0 },
        !           250:        {{ USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_MA111NA }, 0 },
        !           251:        {{ USB_VENDOR_PHEENET, USB_PRODUCT_PHEENET_WL503IA }, 0 },
        !           252:        {{ USB_VENDOR_PHEENET, USB_PRODUCT_PHEENET_WM168B }, 0 },
        !           253:        {{ USB_VENDOR_PLANEX, USB_PRODUCT_PLANEX_GW_US11H }, 0 },
        !           254:        {{ USB_VENDOR_SIEMENS, USB_PRODUCT_SIEMENS_SPEEDSTREAM22 }, 0 },
        !           255:        {{ USB_VENDOR_SITECOM2, USB_PRODUCT_SITECOM2_WL022 }, 0 },
        !           256:        {{ USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_0193 }, 0 },
        !           257:        {{ USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_ZYAIR_B200 }, 0 },
        !           258:        {{ USB_VENDOR_USR, USB_PRODUCT_USR_USR1120 }, 0 },
        !           259:        {{ USB_VENDOR_VIEWSONIC, USB_PRODUCT_VIEWSONIC_AIRSYNC }, 0 },
        !           260:        {{ USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_XI725 }, 0 },
        !           261:        {{ USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_XI735 }, 0 }
        !           262: };
        !           263: #define wi_usb_lookup(v, p) ((struct wi_usb_type *)usb_lookup(wi_usb_devs, v, p))
        !           264:
        !           265: int wi_usb_match(struct device *, void *, void *);
        !           266: void wi_usb_attach(struct device *, struct device *, void *);
        !           267: int wi_usb_detach(struct device *, int);
        !           268: int wi_usb_activate(struct device *, enum devact);
        !           269:
        !           270: struct cfdriver wi_usb_cd = {
        !           271:        NULL, "wi_usb", DV_IFNET
        !           272: };
        !           273:
        !           274: const struct cfattach wi_usb_ca = {
        !           275:        sizeof(struct wi_usb_softc),
        !           276:        wi_usb_match,
        !           277:        wi_usb_attach,
        !           278:        wi_usb_detach,
        !           279:        wi_usb_activate,
        !           280: };
        !           281:
        !           282: int
        !           283: wi_usb_match(struct device *parent, void *match, void *aux)
        !           284: {
        !           285:        struct usb_attach_arg   *uaa = aux;
        !           286:
        !           287:        if (uaa->iface != NULL)
        !           288:                return (UMATCH_NONE);
        !           289:
        !           290:        return (wi_usb_lookup(uaa->vendor, uaa->product) != NULL ?
        !           291:                UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
        !           292: }
        !           293:
        !           294:
        !           295: /*
        !           296:  * Attach the interface. Allocate softc structures, do ifmedia
        !           297:  * setup and ethernet/BPF attach.
        !           298:  */
        !           299: void
        !           300: wi_usb_attach(struct device *parent, struct device *self, void *aux)
        !           301: {
        !           302:        struct wi_usb_softc     *sc = (struct wi_usb_softc *)self;
        !           303:        struct usb_attach_arg   *uaa = aux;
        !           304:        char                    *devinfop;
        !           305: /*     int                     s; */
        !           306:        usbd_device_handle      dev = uaa->device;
        !           307:        usbd_interface_handle   iface;
        !           308:        usbd_status             err;
        !           309:        usb_interface_descriptor_t      *id;
        !           310:        usb_endpoint_descriptor_t       *ed;
        !           311:        int                      i;
        !           312:
        !           313:        DPRINTFN(5,(" : wi_usb_attach: sc=%p", sc));
        !           314:
        !           315:        err = usbd_set_config_no(dev, WI_USB_CONFIG_NO, 1);
        !           316:        if (err) {
        !           317:                printf("%s: setting config no failed\n",
        !           318:                    sc->wi_usb_dev.dv_xname);
        !           319:                return;
        !           320:        }
        !           321:
        !           322:        devinfop = usbd_devinfo_alloc(dev, 0);
        !           323:        printf("\n%s: %s\n", sc->wi_usb_dev.dv_xname, devinfop);
        !           324:        usbd_devinfo_free(devinfop);
        !           325:
        !           326:        /* XXX - any tasks? */
        !           327:
        !           328:        err = usbd_device2interface_handle(dev, WI_USB_IFACE_IDX, &iface);
        !           329:        if (err) {
        !           330:                printf("%s: getting interface handle failed\n",
        !           331:                    sc->wi_usb_dev.dv_xname);
        !           332:                return;
        !           333:        }
        !           334:
        !           335:        /* XXX - flags? */
        !           336:
        !           337:        sc->wi_usb_udev = dev;
        !           338:        sc->wi_usb_iface = iface;
        !           339:        sc->wi_usb_product = uaa->product;
        !           340:        sc->wi_usb_vendor = uaa->vendor;
        !           341:
        !           342:        sc->sc_wi.wi_usb_cdata = sc;
        !           343:        sc->sc_wi.wi_flags |= WI_FLAGS_BUS_USB;
        !           344:
        !           345:        sc->wi_lock = 0;
        !           346:        sc->wi_lockwait = 0;
        !           347:        sc->wi_resetonce = 0;
        !           348:
        !           349:        id = usbd_get_interface_descriptor(iface);
        !           350:
        !           351:        /* Find endpoints. */
        !           352:        for (i = 0; i < id->bNumEndpoints; i++) {
        !           353:                ed = usbd_interface2endpoint_descriptor(iface, i);
        !           354:                if (ed == NULL) {
        !           355:                        printf("%s: couldn't get endpoint descriptor %d\n",
        !           356:                            sc->wi_usb_dev.dv_xname, i);
        !           357:                        return;
        !           358:                }
        !           359:                if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
        !           360:                    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
        !           361:                        sc->wi_usb_ed[WI_USB_ENDPT_RX] = ed->bEndpointAddress;
        !           362:                } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
        !           363:                           UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
        !           364:                        sc->wi_usb_ed[WI_USB_ENDPT_TX] = ed->bEndpointAddress;
        !           365:                } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
        !           366:                           UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
        !           367:                        sc->wi_usb_ed[WI_USB_ENDPT_INTR] = ed->bEndpointAddress;
        !           368:                }
        !           369:        }
        !           370:
        !           371:        sc->wi_usb_nummem = 0;
        !           372:
        !           373:        /* attach wi device */
        !           374:
        !           375:        if (wi_usb_rx_list_init(sc)) {
        !           376:                printf("%s: rx list init failed\n",
        !           377:                    sc->wi_usb_dev.dv_xname);
        !           378:                return;
        !           379:        }
        !           380:        if (wi_usb_tx_list_init(sc)) {
        !           381:                printf("%s: tx list init failed\n",
        !           382:                    sc->wi_usb_dev.dv_xname);
        !           383:                return;
        !           384:        }
        !           385:
        !           386:        if (wi_usb_open_pipes(sc)){
        !           387:                printf("%s: open pipes failed\n",
        !           388:                    sc->wi_usb_dev.dv_xname);
        !           389:                return;
        !           390:        }
        !           391:
        !           392:        sc->wi_usb_attached = 1;
        !           393:
        !           394:        kthread_create_deferred(wi_usb_start_thread, sc);
        !           395:
        !           396:        usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->wi_usb_udev,
        !           397:                           &sc->wi_usb_dev);
        !           398: }
        !           399:
        !           400: int
        !           401: wi_usb_detach(struct device *self, int flags)
        !           402: {
        !           403:        struct wi_usb_softc     *sc = (struct wi_usb_softc *)self;
        !           404:        struct ifnet            *ifp = WI_GET_IFP(sc);
        !           405:        struct wi_softc         *wsc = &sc->sc_wi;
        !           406:        int s;
        !           407:        int err;
        !           408:
        !           409:        sc->wi_usb_dying = 1;
        !           410:        if (sc->wi_thread_info != NULL) {
        !           411:                sc->wi_thread_info->dying = 1;
        !           412:
        !           413:                sc->wi_thread_info->status |= WI_DYING;
        !           414:                if (sc->wi_thread_info->idle)
        !           415:                        wakeup(sc->wi_thread_info);
        !           416:        }
        !           417:
        !           418:        if (!sc->wi_usb_attached) {
        !           419:                /* Detached before attach finished, so just bail out. */
        !           420:                return (0);
        !           421:        }
        !           422:        /* tasks? */
        !           423:
        !           424:        s = splusb();
        !           425:        /* detatch wi */
        !           426:
        !           427:        if (!(wsc->wi_flags & WI_FLAGS_ATTACHED)) {
        !           428:                printf("%s: already detached\n", sc->wi_usb_dev.dv_xname);
        !           429:                splx(s);
        !           430:                return (0);
        !           431:        }
        !           432:
        !           433:        wi_detach(&sc->sc_wi);
        !           434:
        !           435:        wsc->wi_flags = 0;
        !           436:
        !           437:        ether_ifdetach(ifp);
        !           438:        if_detach(ifp);
        !           439:
        !           440:        sc->wi_usb_attached = 0;
        !           441:
        !           442:        if (--sc->wi_usb_refcnt >= 0) {
        !           443:                /* Wait for processes to go away. */
        !           444:                usb_detach_wait(&sc->wi_usb_dev);
        !           445:        }
        !           446:
        !           447:        while (sc->wi_usb_nummem) {
        !           448:                sc->wi_usb_nummem--;
        !           449:                if (sc->wi_usb_txmem[sc->wi_usb_nummem] != NULL)
        !           450:                        free(sc->wi_usb_txmem[sc->wi_usb_nummem], M_DEVBUF);
        !           451:                sc->wi_usb_txmem[sc->wi_usb_nummem] = NULL;
        !           452:        }
        !           453:
        !           454:        if (sc->wi_usb_ep[WI_USB_ENDPT_INTR] != NULL) {
        !           455:                err = usbd_abort_pipe(sc->wi_usb_ep[WI_USB_ENDPT_INTR]);
        !           456:                if (err) {
        !           457:                        printf("%s: abort intr pipe failed: %s\n",
        !           458:                            sc->wi_usb_dev.dv_xname, usbd_errstr(err));
        !           459:                }
        !           460:                err = usbd_close_pipe(sc->wi_usb_ep[WI_USB_ENDPT_INTR]);
        !           461:                if (err) {
        !           462:                        printf("%s: close intr pipe failed: %s\n",
        !           463:                            sc->wi_usb_dev.dv_xname, usbd_errstr(err));
        !           464:                }
        !           465:                sc->wi_usb_ep[WI_USB_ENDPT_INTR] = NULL;
        !           466:        }
        !           467:        if (sc->wi_usb_ep[WI_USB_ENDPT_TX] != NULL) {
        !           468:                usbd_abort_pipe(sc->wi_usb_ep[WI_USB_ENDPT_TX]);
        !           469:                if (err) {
        !           470:                        printf("%s: abort tx pipe failed: %s\n",
        !           471:                            sc->wi_usb_dev.dv_xname, usbd_errstr(err));
        !           472:                }
        !           473:                err = usbd_close_pipe(sc->wi_usb_ep[WI_USB_ENDPT_TX]);
        !           474:                if (err) {
        !           475:                        printf("%s: close tx pipe failed: %s\n",
        !           476:                            sc->wi_usb_dev.dv_xname, usbd_errstr(err));
        !           477:                }
        !           478:                sc->wi_usb_ep[WI_USB_ENDPT_TX] = NULL;
        !           479:        }
        !           480:        if (sc->wi_usb_ep[WI_USB_ENDPT_RX] != NULL) {
        !           481:                usbd_abort_pipe(sc->wi_usb_ep[WI_USB_ENDPT_RX]);
        !           482:                if (err) {
        !           483:                        printf("%s: abort rx pipe failed: %s\n",
        !           484:                            sc->wi_usb_dev.dv_xname, usbd_errstr(err));
        !           485:                }
        !           486:                err = usbd_close_pipe(sc->wi_usb_ep[WI_USB_ENDPT_RX]);
        !           487:                if (err) {
        !           488:                        printf("%s: close rx pipe failed: %s\n",
        !           489:                            sc->wi_usb_dev.dv_xname, usbd_errstr(err));
        !           490:                }
        !           491:                sc->wi_usb_ep[WI_USB_ENDPT_RX] = NULL;
        !           492:        }
        !           493:
        !           494:        splx(s);
        !           495:
        !           496:        usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->wi_usb_udev,
        !           497:            &sc->wi_usb_dev);
        !           498:        return (0);
        !           499: }
        !           500:
        !           501: int
        !           502: wi_send_packet(struct wi_usb_softc *sc, int id)
        !           503: {
        !           504:        struct wi_usb_chain     *c;
        !           505:        struct wi_frame         *wibuf;
        !           506:        int                     total_len, rnd_len;
        !           507:        int                     err;
        !           508:
        !           509:        c = &sc->wi_usb_tx_chain[0];
        !           510:
        !           511:        DPRINTFN(10,("%s: %s: id=%x\n",
        !           512:            sc->wi_usb_dev.dv_xname, __func__, id));
        !           513:
        !           514:        /* assemble packet from write_data buffer */
        !           515:        if (id == 0 || id == 1) {
        !           516:                /* tx_lock acquired before wi_start() */
        !           517:                wibuf = sc->wi_usb_txmem[id];
        !           518:
        !           519:                total_len = sizeof (struct wi_frame) +
        !           520:                    letoh16(wibuf->wi_dat_len);
        !           521:                rnd_len = ROUNDUP64(total_len);
        !           522:                if ((total_len > sc->wi_usb_txmemsize[id]) ||
        !           523:                   (rnd_len > WI_USB_BUFSZ )){
        !           524:                        printf("invalid packet len: %x memsz %x max %x\n",
        !           525:                            total_len, sc->wi_usb_txmemsize[id], WI_USB_BUFSZ);
        !           526:                        total_len = sc->wi_usb_txmemsize[id];
        !           527:
        !           528:                        err = EIO;
        !           529:                        goto err_ret;
        !           530:                }
        !           531:
        !           532:                sc->txresp = WI_CMD_TX;
        !           533:                sc->txresperr = 0;
        !           534:
        !           535:                bcopy(wibuf, c->wi_usb_buf, total_len);
        !           536:
        !           537:                bzero(((char *)c->wi_usb_buf)+total_len,
        !           538:                    rnd_len - total_len);
        !           539:
        !           540:                /* zero old packet for next TX */
        !           541:                bzero(wibuf, total_len);
        !           542:
        !           543:                total_len = rnd_len;
        !           544:
        !           545:                DPRINTFN(5,("%s: %s: id=%x len=%x\n",
        !           546:                    sc->wi_usb_dev.dv_xname, __func__, id, total_len));
        !           547:
        !           548:                usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX],
        !           549:                    c, c->wi_usb_buf, rnd_len,
        !           550:                    USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
        !           551:                    WI_USB_TX_TIMEOUT, wi_usb_txeof_frm);
        !           552:
        !           553:                err = usbd_transfer(c->wi_usb_xfer);
        !           554:                if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION) {
        !           555:                        printf("%s: %s: error=%s\n",
        !           556:                            sc->wi_usb_dev.dv_xname, __func__,
        !           557:                            usbd_errstr(err));
        !           558:                        /* Stop the interface from process context. */
        !           559:                        wi_usb_stop(sc);
        !           560:                        err = EIO;
        !           561:                } else {
        !           562:                        err = 0;
        !           563:                }
        !           564:
        !           565:                DPRINTFN(5,("%s: %s: exit err=%x\n",
        !           566:                    sc->wi_usb_dev.dv_xname, __func__, err));
        !           567: err_ret:
        !           568:                return err;
        !           569:        }
        !           570:        printf("%s:%s: invalid packet id sent %x\n",
        !           571:            sc->wi_usb_dev.dv_xname, __func__, id);
        !           572:        return 0;
        !           573: }
        !           574:
        !           575: int
        !           576: wi_cmd_usb(struct wi_softc *wsc, int cmd, int val0, int val1, int val2)
        !           577: {
        !           578:        struct wi_usb_chain     *c;
        !           579:        struct wi_usb_softc     *sc = wsc->wi_usb_cdata;
        !           580:        struct wi_cmdreq        *pcmd;
        !           581:        int                     total_len, rnd_len;
        !           582:        int                     err;
        !           583:
        !           584:        DPRINTFN(5,("%s: %s: enter cmd=%x %x %x %x\n",
        !           585:            sc->wi_usb_dev.dv_xname, __func__, cmd, val0, val1, val2));
        !           586:
        !           587:        if ((cmd & WI_CMD_CODE_MASK) == WI_CMD_TX) {
        !           588:                return wi_send_packet(sc, val0);
        !           589:        }
        !           590:
        !           591:
        !           592:        if ((cmd & WI_CMD_CODE_MASK) == WI_CMD_INI) {
        !           593:                /* free alloc_nicmem regions */
        !           594:                while (sc->wi_usb_nummem) {
        !           595:                        sc->wi_usb_nummem--;
        !           596:                        free(sc->wi_usb_txmem[sc->wi_usb_nummem], M_DEVBUF);
        !           597:                        sc->wi_usb_txmem[sc->wi_usb_nummem] = NULL;
        !           598:                }
        !           599:
        !           600: #if 0
        !           601:                /* if this is the first time, init, otherwise do not?? */
        !           602:                if (sc->wi_resetonce) {
        !           603:                        return 0;
        !           604:                } else
        !           605:                        sc->wi_resetonce = 1;
        !           606: #endif
        !           607:        }
        !           608:
        !           609:        wi_usb_ctl_lock(sc);
        !           610:
        !           611:        wi_usb_tx_lock(sc);
        !           612:
        !           613:        c = &sc->wi_usb_tx_chain[0];
        !           614:        pcmd = c->wi_usb_buf;
        !           615:
        !           616:
        !           617:        total_len = sizeof (struct wi_cmdreq);
        !           618:        rnd_len = ROUNDUP64(total_len);
        !           619:        if (rnd_len > WI_USB_BUFSZ) {
        !           620:                printf("read_record buf size err %x %x\n",
        !           621:                    rnd_len, WI_USB_BUFSZ);
        !           622:                err = EIO;
        !           623:                goto err_ret;
        !           624:        }
        !           625:
        !           626:        sc->cmdresp = cmd;
        !           627:        sc->cmdresperr = 0;
        !           628:
        !           629:        pcmd->type = htole16(WI_USB_CMDREQ);
        !           630:        pcmd->cmd  = htole16(cmd);
        !           631:        pcmd->param0  = htole16(val0);
        !           632:        pcmd->param1  = htole16(val1);
        !           633:        pcmd->param2  = htole16(val2);
        !           634:
        !           635:        bzero(((char*)pcmd)+total_len, rnd_len - total_len);
        !           636:
        !           637:        total_len = rnd_len;
        !           638:
        !           639:        usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX],
        !           640:            c, c->wi_usb_buf, rnd_len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
        !           641:            WI_USB_TX_TIMEOUT, wi_usb_txeof);
        !           642:
        !           643:        err = wi_usb_do_transmit_sync(sc, c, &sc->cmdresperr);
        !           644:
        !           645:        if (err == 0)
        !           646:                err = sc->cmdresperr;
        !           647:
        !           648:        sc->cmdresperr = 0;
        !           649:
        !           650: err_ret:
        !           651:        wi_usb_tx_unlock(sc);
        !           652:
        !           653:        wi_usb_ctl_unlock(sc);
        !           654:
        !           655:        DPRINTFN(5,("%s: %s: exit err=%x\n",
        !           656:            sc->wi_usb_dev.dv_xname, __func__, err));
        !           657:        return err;
        !           658: }
        !           659:
        !           660:
        !           661: int
        !           662: wi_read_record_usb(struct wi_softc *wsc, struct wi_ltv_gen *ltv)
        !           663: {
        !           664:        struct wi_usb_chain     *c;
        !           665:        struct wi_usb_softc     *sc = wsc->wi_usb_cdata;
        !           666:        struct wi_rridreq       *prid;
        !           667:        int                     total_len, rnd_len;
        !           668:        int                     err;
        !           669:        struct wi_ltv_gen       *oltv, p2ltv;
        !           670:
        !           671:        DPRINTFN(5,("%s: %s: enter rid=%x\n",
        !           672:            sc->wi_usb_dev.dv_xname, __func__, ltv->wi_type));
        !           673:
        !           674:        /* Do we need to deal with these here, as in _io version?
        !           675:         * WI_RID_ENCRYPTION -> WI_RID_P2_ENCRYPTION
        !           676:         * WI_RID_TX_CRYPT_KEY -> WI_RID_P2_TX_CRYPT_KEY
        !           677:         */
        !           678:        if (wsc->sc_firmware_type != WI_LUCENT) {
        !           679:                oltv = ltv;
        !           680:                switch (ltv->wi_type) {
        !           681:                case WI_RID_ENCRYPTION:
        !           682:                        p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
        !           683:                        p2ltv.wi_len = 2;
        !           684:                        ltv = &p2ltv;
        !           685:                        break;
        !           686:                case WI_RID_TX_CRYPT_KEY:
        !           687:                        if (ltv->wi_val > WI_NLTV_KEYS)
        !           688:                                return (EINVAL);
        !           689:                        p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
        !           690:                        p2ltv.wi_len = 2;
        !           691:                        ltv = &p2ltv;
        !           692:                        break;
        !           693:                }
        !           694:        }
        !           695:
        !           696:        wi_usb_tx_lock(sc);
        !           697:
        !           698:        c = &sc->wi_usb_tx_chain[0];
        !           699:        prid = c->wi_usb_buf;
        !           700:
        !           701:        total_len = sizeof(struct wi_rridreq);
        !           702:        rnd_len = ROUNDUP64(total_len);
        !           703:
        !           704:        if (rnd_len > WI_USB_BUFSZ) {
        !           705:                printf("read_record buf size err %x %x\n",
        !           706:                    rnd_len, WI_USB_BUFSZ);
        !           707:                wi_usb_tx_unlock(sc);
        !           708:                return EIO;
        !           709:        }
        !           710:
        !           711:        sc->ridltv = ltv;
        !           712:        sc->ridresperr = 0;
        !           713:
        !           714:        prid->type = htole16(WI_USB_RRIDREQ);
        !           715:        prid->frmlen = htole16(2);      /* variable size? */
        !           716:        prid->rid  = htole16(ltv->wi_type);
        !           717:
        !           718:        bzero(((char*)prid)+total_len, rnd_len - total_len);
        !           719:
        !           720:        usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX],
        !           721:            c, c->wi_usb_buf, rnd_len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
        !           722:            WI_USB_TX_TIMEOUT, wi_usb_txeof);
        !           723:
        !           724:        DPRINTFN(10,("%s: %s: total_len=%x, wilen %d\n",
        !           725:            sc->wi_usb_dev.dv_xname, __func__, total_len, ltv->wi_len));
        !           726:
        !           727:        err = wi_usb_do_transmit_sync(sc, c, &sc->ridresperr);
        !           728:
        !           729:        /* Do we need to deal with these here, as in _io version?
        !           730:         *
        !           731:         * WI_RID_TX_RATE
        !           732:         * WI_RID_CUR_TX_RATE
        !           733:         * WI_RID_ENCRYPTION
        !           734:         * WI_RID_TX_CRYPT_KEY
        !           735:         * WI_RID_CNFAUTHMODE
        !           736:         */
        !           737:        if (ltv->wi_type == WI_RID_PORTTYPE && wsc->wi_ptype == WI_PORTTYPE_IBSS
        !           738:            && ltv->wi_val == wsc->wi_ibss_port) {
        !           739:                /*
        !           740:                 * Convert vendor IBSS port type to WI_PORTTYPE_IBSS.
        !           741:                 * Since Lucent uses port type 1 for BSS *and* IBSS we
        !           742:                 * have to rely on wi_ptype to distinguish this for us.
        !           743:                 */
        !           744:                ltv->wi_val = htole16(WI_PORTTYPE_IBSS);
        !           745:        } else if (wsc->sc_firmware_type != WI_LUCENT) {
        !           746:                int v;
        !           747:
        !           748:                switch (oltv->wi_type) {
        !           749:                case WI_RID_TX_RATE:
        !           750:                case WI_RID_CUR_TX_RATE:
        !           751:                        switch (letoh16(ltv->wi_val)) {
        !           752:                        case 1: v = 1; break;
        !           753:                        case 2: v = 2; break;
        !           754:                        case 3: v = 6; break;
        !           755:                        case 4: v = 5; break;
        !           756:                        case 7: v = 7; break;
        !           757:                        case 8: v = 11; break;
        !           758:                        case 15: v = 3; break;
        !           759:                        default: v = 0x100 + letoh16(ltv->wi_val); break;
        !           760:                        }
        !           761:                        oltv->wi_val = htole16(v);
        !           762:                        break;
        !           763:                case WI_RID_ENCRYPTION:
        !           764:                        oltv->wi_len = 2;
        !           765:                        if (ltv->wi_val & htole16(0x01))
        !           766:                                oltv->wi_val = htole16(1);
        !           767:                        else
        !           768:                                oltv->wi_val = htole16(0);
        !           769:                        break;
        !           770:                case WI_RID_TX_CRYPT_KEY:
        !           771:                case WI_RID_CNFAUTHMODE:
        !           772:                        oltv->wi_len = 2;
        !           773:                        oltv->wi_val = ltv->wi_val;
        !           774:                        break;
        !           775:                }
        !           776:        }
        !           777:
        !           778:        if (err == 0)
        !           779:                err = sc->ridresperr;
        !           780:
        !           781:        sc->ridresperr = 0;
        !           782:
        !           783:        wi_usb_tx_unlock(sc);
        !           784:
        !           785:        DPRINTFN(5,("%s: %s: exit err=%x\n",
        !           786:            sc->wi_usb_dev.dv_xname, __func__, err));
        !           787:        return err;
        !           788: }
        !           789:
        !           790: int
        !           791: wi_write_record_usb(struct wi_softc *wsc, struct wi_ltv_gen *ltv)
        !           792: {
        !           793:        struct wi_usb_chain     *c;
        !           794:        struct wi_usb_softc     *sc = wsc->wi_usb_cdata;
        !           795:        struct wi_wridreq       *prid;
        !           796:        int                     total_len, rnd_len;
        !           797:        int                     err;
        !           798:        struct wi_ltv_gen       p2ltv;
        !           799:        u_int16_t               val = 0;
        !           800:        int                     i;
        !           801:
        !           802:        DPRINTFN(5,("%s: %s: enter rid=%x wi_len %d copying %x\n",
        !           803:            sc->wi_usb_dev.dv_xname, __func__, ltv->wi_type, ltv->wi_len,
        !           804:            (ltv->wi_len-1)*2 ));
        !           805:
        !           806:        /* Do we need to deal with these here, as in _io version?
        !           807:         * WI_PORTTYPE_IBSS -> WI_RID_PORTTYPE
        !           808:         * RID_TX_RATE munging
        !           809:         * RID_ENCRYPTION
        !           810:         * WI_RID_TX_CRYPT_KEY
        !           811:         * WI_RID_DEFLT_CRYPT_KEYS
        !           812:         */
        !           813:        if (ltv->wi_type == WI_RID_PORTTYPE &&
        !           814:            letoh16(ltv->wi_val) == WI_PORTTYPE_IBSS) {
        !           815:                /* Convert WI_PORTTYPE_IBSS to vendor IBSS port type. */
        !           816:                p2ltv.wi_type = WI_RID_PORTTYPE;
        !           817:                p2ltv.wi_len = 2;
        !           818:                p2ltv.wi_val = wsc->wi_ibss_port;
        !           819:                ltv = &p2ltv;
        !           820:        } else if (wsc->sc_firmware_type != WI_LUCENT) {
        !           821:                int v;
        !           822:
        !           823:                switch (ltv->wi_type) {
        !           824:                case WI_RID_TX_RATE:
        !           825:                        p2ltv.wi_type = WI_RID_TX_RATE;
        !           826:                        p2ltv.wi_len = 2;
        !           827:                        switch (letoh16(ltv->wi_val)) {
        !           828:                        case 1: v = 1; break;
        !           829:                        case 2: v = 2; break;
        !           830:                        case 3: v = 15; break;
        !           831:                        case 5: v = 4; break;
        !           832:                        case 6: v = 3; break;
        !           833:                        case 7: v = 7; break;
        !           834:                        case 11: v = 8; break;
        !           835:                        default: return EINVAL;
        !           836:                        }
        !           837:                        p2ltv.wi_val = htole16(v);
        !           838:                        ltv = &p2ltv;
        !           839:                        break;
        !           840:                case WI_RID_ENCRYPTION:
        !           841:                        p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
        !           842:                        p2ltv.wi_len = 2;
        !           843:                        if (ltv->wi_val & htole16(0x01)) {
        !           844:                                val = PRIVACY_INVOKED;
        !           845:                                /*
        !           846:                                 * If using shared key WEP we must set the
        !           847:                                 * EXCLUDE_UNENCRYPTED bit.  Symbol cards
        !           848:                                 * need this bit set even when not using
        !           849:                                 * shared key. We can't just test for
        !           850:                                 * IEEE80211_AUTH_SHARED since Symbol cards
        !           851:                                 * have 2 shared key modes.
        !           852:                                 */
        !           853:                                if (wsc->wi_authtype != IEEE80211_AUTH_OPEN ||
        !           854:                                    wsc->sc_firmware_type == WI_SYMBOL)
        !           855:                                        val |= EXCLUDE_UNENCRYPTED;
        !           856:
        !           857:                                switch (wsc->wi_crypto_algorithm) {
        !           858:                                case WI_CRYPTO_FIRMWARE_WEP:
        !           859:                                        /*
        !           860:                                         * TX encryption is broken in
        !           861:                                         * Host AP mode.
        !           862:                                         */
        !           863:                                        if (wsc->wi_ptype == WI_PORTTYPE_HOSTAP)
        !           864:                                                val |= HOST_ENCRYPT;
        !           865:                                        break;
        !           866:                                case WI_CRYPTO_SOFTWARE_WEP:
        !           867:                                        val |= HOST_ENCRYPT|HOST_DECRYPT;
        !           868:                                        break;
        !           869:                                }
        !           870:                                p2ltv.wi_val = htole16(val);
        !           871:                        } else
        !           872:                                p2ltv.wi_val = htole16(HOST_ENCRYPT | HOST_DECRYPT);
        !           873:                        ltv = &p2ltv;
        !           874:                        break;
        !           875:                case WI_RID_TX_CRYPT_KEY:
        !           876:                        if (ltv->wi_val > WI_NLTV_KEYS)
        !           877:                                return (EINVAL);
        !           878:                        p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
        !           879:                        p2ltv.wi_len = 2;
        !           880:                        p2ltv.wi_val = ltv->wi_val;
        !           881:                        ltv = &p2ltv;
        !           882:                        break;
        !           883:                case WI_RID_DEFLT_CRYPT_KEYS: {
        !           884:                                int error;
        !           885:                                int keylen;
        !           886:                                struct wi_ltv_str ws;
        !           887:                                struct wi_ltv_keys *wk;
        !           888:
        !           889:                                wk = (struct wi_ltv_keys *)ltv;
        !           890:                                keylen = wk->wi_keys[wsc->wi_tx_key].wi_keylen;
        !           891:                                keylen = letoh16(keylen);
        !           892:
        !           893:                                for (i = 0; i < 4; i++) {
        !           894:                                        bzero(&ws, sizeof(ws));
        !           895:                                        ws.wi_len = (keylen > 5) ? 8 : 4;
        !           896:                                        ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
        !           897:                                        bcopy(&wk->wi_keys[i].wi_keydat,
        !           898:                                            ws.wi_str, keylen);
        !           899:                                        error = wi_write_record_usb(wsc,
        !           900:                                            (struct wi_ltv_gen *)&ws);
        !           901:                                        if (error)
        !           902:                                                return (error);
        !           903:                                }
        !           904:                        }
        !           905:                        return (0);
        !           906:                }
        !           907:        }
        !           908:
        !           909:        wi_usb_tx_lock(sc);
        !           910:
        !           911:        c = &sc->wi_usb_tx_chain[0];
        !           912:
        !           913:        prid = c->wi_usb_buf;
        !           914:
        !           915:        total_len = sizeof(prid->type) + sizeof(prid->frmlen) +
        !           916:            sizeof(prid->rid) + (ltv->wi_len-1)*2;
        !           917:        rnd_len = ROUNDUP64(total_len);
        !           918:        if (rnd_len > WI_USB_BUFSZ) {
        !           919:                printf("write_record buf size err %x %x\n",
        !           920:                    rnd_len, WI_USB_BUFSZ);
        !           921:                wi_usb_tx_unlock(sc);
        !           922:                return EIO;
        !           923:        }
        !           924:
        !           925:        prid->type = htole16(WI_USB_WRIDREQ);
        !           926:        prid->frmlen = htole16(ltv->wi_len);
        !           927:        prid->rid  = htole16(ltv->wi_type);
        !           928:        if (ltv->wi_len > 1)
        !           929:                bcopy((u_int8_t *)&ltv->wi_val, (u_int8_t *)&prid->data[0],
        !           930:                    (ltv->wi_len-1)*2);
        !           931:
        !           932:        bzero(((char*)prid)+total_len, rnd_len - total_len);
        !           933:
        !           934:        usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_TX],
        !           935:            c, c->wi_usb_buf, rnd_len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
        !           936:            WI_USB_TX_TIMEOUT, wi_usb_txeof);
        !           937:
        !           938:        err = wi_usb_do_transmit_sync(sc, c, &sc->ridresperr);
        !           939:
        !           940:        if (err == 0)
        !           941:                err = sc->ridresperr;
        !           942:
        !           943:        sc->ridresperr = 0;
        !           944:
        !           945:        wi_usb_tx_unlock(sc);
        !           946:
        !           947:        DPRINTFN(5,("%s: %s: exit err=%x\n",
        !           948:            sc->wi_usb_dev.dv_xname, __func__, err));
        !           949:        return err;
        !           950: }
        !           951:
        !           952: /*
        !           953:  * This is an ugly compat portion to emulate the I/O which writes
        !           954:  * a packet or management information
        !           955:  * The data is copied into local memory for the requested
        !           956:  * 'id' then on the wi_cmd WI_CMD_TX, the id argument
        !           957:  * will identify which buffer to use
        !           958:  */
        !           959: int
        !           960: wi_alloc_nicmem_usb(struct wi_softc *wsc, int len, int *id)
        !           961: {
        !           962:        int nmem;
        !           963:        struct wi_usb_softc     *sc = wsc->wi_usb_cdata;
        !           964:
        !           965:        DPRINTFN(10,("%s: %s: enter len=%x\n",
        !           966:            sc->wi_usb_dev.dv_xname, __func__, len));
        !           967:
        !           968:        /*
        !           969:         * NOTE THIS IS A USB DEVICE WHICH WILL LIKELY HAVE MANY
        !           970:         * CONNECTS/DISCONNECTS, FREE THIS MEMORY XXX XXX XXX !!! !!!
        !           971:         */
        !           972:        nmem = sc->wi_usb_nummem++;
        !           973:
        !           974:        if (nmem >= MAX_WI_NMEM) {
        !           975:                sc->wi_usb_nummem--;
        !           976:                return ENOMEM;
        !           977:        }
        !           978:
        !           979:        sc->wi_usb_txmem[nmem] = malloc(len, M_DEVBUF, M_WAITOK);
        !           980:        if (sc->wi_usb_txmem[nmem] == NULL) {
        !           981:                sc->wi_usb_nummem--;
        !           982:                return ENOMEM;
        !           983:        }
        !           984:        sc->wi_usb_txmemsize[nmem] = len;
        !           985:
        !           986:        *id = nmem;
        !           987:        return 0;
        !           988: }
        !           989:
        !           990: /*
        !           991:  * this is crazy, we skip the first 16 bits of the buf so that it
        !           992:  * can be used as the 'type' of the usb transfer.
        !           993:  */
        !           994:
        !           995:
        !           996: int
        !           997: wi_write_data_usb(struct wi_softc *wsc, int id, int off, caddr_t buf, int len)
        !           998: {
        !           999:        u_int8_t        *ptr;
        !          1000:        struct wi_usb_softc     *sc = wsc->wi_usb_cdata;
        !          1001:
        !          1002:        DPRINTFN(10,("%s: %s: id %x off %x len %d\n",
        !          1003:            sc->wi_usb_dev.dv_xname, __func__, id, off, len));
        !          1004:
        !          1005:        if (id < 0 && id >= sc->wi_usb_nummem)
        !          1006:                return EIO;
        !          1007:
        !          1008:        ptr = (u_int8_t *)(sc->wi_usb_txmem[id]) + off;
        !          1009:
        !          1010:        if (len + off > sc->wi_usb_txmemsize[id])
        !          1011:                return EIO;
        !          1012:        DPRINTFN(10,("%s: %s: completed \n",
        !          1013:            sc->wi_usb_dev.dv_xname, __func__));
        !          1014:
        !          1015:        bcopy(buf, ptr, len);
        !          1016:        return 0;
        !          1017: }
        !          1018:
        !          1019: /*
        !          1020:  * On the prism I/O, this read_data points to the hardware buffer
        !          1021:  * which contains the
        !          1022:  */
        !          1023: int
        !          1024: wi_read_data_usb(struct wi_softc *wsc, int id, int off, caddr_t buf, int len)
        !          1025: {
        !          1026:        u_int8_t        *ptr;
        !          1027:        struct wi_usb_softc     *sc = wsc->wi_usb_cdata;
        !          1028:
        !          1029:        DPRINTFN(10,("%s: %s: id %x off %x len %d\n",
        !          1030:            sc->wi_usb_dev.dv_xname, __func__, id, off, len));
        !          1031:
        !          1032:        if (id == 0x1001 && sc->wi_info != NULL)
        !          1033:                ptr = (u_int8_t *)sc->wi_info + off;
        !          1034:        else if (id == 0x1000 && sc->wi_rxframe != NULL)
        !          1035:                ptr = (u_int8_t *)sc->wi_rxframe + off;
        !          1036:        else if (id >= 0 && id < sc->wi_usb_nummem) {
        !          1037:
        !          1038:                if (sc->wi_usb_txmem[id] == NULL)
        !          1039:                        return EIO;
        !          1040:                if (len + off > sc->wi_usb_txmemsize[id])
        !          1041:                        return EIO;
        !          1042:
        !          1043:                ptr = (u_int8_t *)(sc->wi_usb_txmem[id]) + off;
        !          1044:        } else
        !          1045:                return EIO;
        !          1046:
        !          1047:        if (id < sc->wi_usb_nummem) {
        !          1048:                ptr = (u_int8_t *)(sc->wi_usb_txmem[id]) + off;
        !          1049:
        !          1050:                if (len + off > sc->wi_usb_txmemsize[id])
        !          1051:                        return EIO;
        !          1052:        }
        !          1053:
        !          1054:        bcopy(ptr, buf, len);
        !          1055:        return 0;
        !          1056: }
        !          1057:
        !          1058: void
        !          1059: wi_usb_stop(struct wi_usb_softc *sc)
        !          1060: {
        !          1061:        DPRINTFN(1,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname,__func__));
        !          1062:        /* XXX */
        !          1063:
        !          1064:        /* Stop transfers */
        !          1065: }
        !          1066:
        !          1067: int
        !          1068: wi_usb_do_transmit_sync(struct wi_usb_softc *sc, struct wi_usb_chain *c,
        !          1069:     void *ident)
        !          1070: {
        !          1071:        usbd_status             err;
        !          1072:
        !          1073:        DPRINTFN(10,("%s: %s:\n",
        !          1074:            sc->wi_usb_dev.dv_xname, __func__));
        !          1075:
        !          1076:        sc->wi_usb_refcnt++;
        !          1077:        err = usbd_transfer(c->wi_usb_xfer);
        !          1078:        if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION) {
        !          1079:                printf("%s: %s error=%s\n",
        !          1080:                    sc->wi_usb_dev.dv_xname, __func__,
        !          1081:                    usbd_errstr(err));
        !          1082:                /* Stop the interface from process context. */
        !          1083:                wi_usb_stop(sc);
        !          1084:                err = EIO;
        !          1085:                goto done;
        !          1086:        }
        !          1087:        err = tsleep(ident, PRIBIO, "wiTXsync", hz*1);
        !          1088:        if (err) {
        !          1089:                DPRINTFN(1,("%s: %s: err %x\n",
        !          1090:                    sc->wi_usb_dev.dv_xname, __func__, err));
        !          1091:                err = ETIMEDOUT;
        !          1092:        }
        !          1093: done:
        !          1094:        if (--sc->wi_usb_refcnt < 0)
        !          1095:                usb_detach_wakeup(&sc->wi_usb_dev);
        !          1096:        return err;
        !          1097: }
        !          1098:
        !          1099:
        !          1100: /*
        !          1101:  * A command/rrid/wrid  was sent to the chip. It's safe for us to clean up
        !          1102:  * the list buffers.
        !          1103:  */
        !          1104:
        !          1105: void
        !          1106: wi_usb_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
        !          1107:     usbd_status status)
        !          1108: {
        !          1109:        struct wi_usb_chain     *c = priv;
        !          1110:        struct wi_usb_softc     *sc = c->wi_usb_sc;
        !          1111:
        !          1112:        int                     s;
        !          1113:
        !          1114:        if (sc->wi_usb_dying)
        !          1115:                return;
        !          1116:
        !          1117:        s = splnet();
        !          1118:
        !          1119:        DPRINTFN(10,("%s: %s: enter status=%d\n", sc->wi_usb_dev.dv_xname,
        !          1120:                    __func__, status));
        !          1121:
        !          1122:        if (status != USBD_NORMAL_COMPLETION) {
        !          1123:                if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
        !          1124:                        splx(s);
        !          1125:                        return;
        !          1126:                }
        !          1127:                printf("%s: usb error on tx: %s\n", sc->wi_usb_dev.dv_xname,
        !          1128:                    usbd_errstr(status));
        !          1129:                if (status == USBD_STALLED) {
        !          1130:                        sc->wi_usb_refcnt++;
        !          1131:                        usbd_clear_endpoint_stall_async(
        !          1132:                            sc->wi_usb_ep[WI_USB_ENDPT_TX]);
        !          1133:                        if (--sc->wi_usb_refcnt < 0)
        !          1134:                                usb_detach_wakeup(&sc->wi_usb_dev);
        !          1135:                }
        !          1136:                splx(s);
        !          1137:                return;
        !          1138:        }
        !          1139:
        !          1140:        splx(s);
        !          1141: }
        !          1142:
        !          1143: /*
        !          1144:  * A packet was sent to the chip. It's safe for us to clean up
        !          1145:  * the list buffers.
        !          1146:  */
        !          1147:
        !          1148: void
        !          1149: wi_usb_txeof_frm(usbd_xfer_handle xfer, usbd_private_handle priv,
        !          1150:     usbd_status status)
        !          1151: {
        !          1152:        struct wi_usb_chain     *c = priv;
        !          1153:        struct wi_usb_softc     *sc = c->wi_usb_sc;
        !          1154:        struct wi_softc         *wsc = &sc->sc_wi;
        !          1155:        struct ifnet            *ifp = &wsc->sc_ic.ic_if;
        !          1156:
        !          1157:        int                     s;
        !          1158:        int                     err = 0;
        !          1159:
        !          1160:        if (sc->wi_usb_dying)
        !          1161:                return;
        !          1162:
        !          1163:        s = splnet();
        !          1164:
        !          1165:        DPRINTFN(10,("%s: %s: enter status=%d\n", sc->wi_usb_dev.dv_xname,
        !          1166:                    __func__, status));
        !          1167:
        !          1168:        if (status != USBD_NORMAL_COMPLETION) {
        !          1169:                if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
        !          1170:                        splx(s);
        !          1171:                        return;
        !          1172:                }
        !          1173:                printf("%s: usb error on tx: %s\n", sc->wi_usb_dev.dv_xname,
        !          1174:                    usbd_errstr(status));
        !          1175:                if (status == USBD_STALLED) {
        !          1176:                        sc->wi_usb_refcnt++;
        !          1177:                        usbd_clear_endpoint_stall_async(
        !          1178:                            sc->wi_usb_ep[WI_USB_ENDPT_TX]);
        !          1179:                        if (--sc->wi_usb_refcnt < 0)
        !          1180:                                usb_detach_wakeup(&sc->wi_usb_dev);
        !          1181:                }
        !          1182:                splx(s);
        !          1183:                return;
        !          1184:        }
        !          1185:
        !          1186:        if (status)
        !          1187:                err = WI_EV_TX_EXC;
        !          1188:
        !          1189:        wi_txeof(wsc, err);
        !          1190:
        !          1191:        wi_usb_tx_unlock(sc);
        !          1192:
        !          1193:        if (!IFQ_IS_EMPTY(&ifp->if_snd))
        !          1194:                wi_start_usb(ifp);
        !          1195:
        !          1196:        splx(s);
        !          1197: }
        !          1198:
        !          1199: int
        !          1200: wi_usb_rx_list_init(struct wi_usb_softc *sc)
        !          1201: {
        !          1202:        struct wi_usb_chain     *c;
        !          1203:        int                     i;
        !          1204:
        !          1205:        DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__));
        !          1206:
        !          1207:        for (i = 0; i < WI_USB_RX_LIST_CNT; i++) {
        !          1208:                c = &sc->wi_usb_rx_chain[i];
        !          1209:                c->wi_usb_sc = sc;
        !          1210:                c->wi_usb_idx = i;
        !          1211:                if (c->wi_usb_xfer != NULL) {
        !          1212:                        printf("UGH RX\n");
        !          1213:                }
        !          1214:                if (c->wi_usb_xfer == NULL) {
        !          1215:                        c->wi_usb_xfer = usbd_alloc_xfer(sc->wi_usb_udev);
        !          1216:                        if (c->wi_usb_xfer == NULL)
        !          1217:                                return (ENOBUFS);
        !          1218:                        c->wi_usb_buf = usbd_alloc_buffer(c->wi_usb_xfer,
        !          1219:                            WI_USB_BUFSZ);
        !          1220:                        if (c->wi_usb_buf == NULL)
        !          1221:                                return (ENOBUFS); /* XXX free xfer */
        !          1222:                }
        !          1223:        }
        !          1224:
        !          1225:        return (0);
        !          1226: }
        !          1227:
        !          1228: int
        !          1229: wi_usb_tx_list_init(struct wi_usb_softc *sc)
        !          1230: {
        !          1231:        struct wi_usb_chain     *c;
        !          1232:        int                     i;
        !          1233:
        !          1234:        DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__));
        !          1235:
        !          1236:        for (i = 0; i < WI_USB_TX_LIST_CNT; i++) {
        !          1237:                c = &sc->wi_usb_tx_chain[i];
        !          1238:                c->wi_usb_sc = sc;
        !          1239:                c->wi_usb_idx = i;
        !          1240:                c->wi_usb_mbuf = NULL;
        !          1241:                if (c->wi_usb_xfer != NULL) {
        !          1242:                        printf("UGH TX\n");
        !          1243:                }
        !          1244:                if (c->wi_usb_xfer == NULL) {
        !          1245:                        c->wi_usb_xfer = usbd_alloc_xfer(sc->wi_usb_udev);
        !          1246:                        if (c->wi_usb_xfer == NULL)
        !          1247:                                return (ENOBUFS);
        !          1248:                        c->wi_usb_buf = usbd_alloc_buffer(c->wi_usb_xfer,
        !          1249:                            WI_USB_BUFSZ);
        !          1250:                        if (c->wi_usb_buf == NULL)
        !          1251:                                return (ENOBUFS);
        !          1252:                }
        !          1253:        }
        !          1254:
        !          1255:        return (0);
        !          1256: }
        !          1257:
        !          1258: int
        !          1259: wi_usb_open_pipes(struct wi_usb_softc *sc)
        !          1260: {
        !          1261:        usbd_status             err;
        !          1262:        int                     error = 0;
        !          1263:        struct wi_usb_chain     *c;
        !          1264:        int                     i;
        !          1265:
        !          1266:        DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname,__func__));
        !          1267:
        !          1268:        sc->wi_usb_refcnt++;
        !          1269:
        !          1270:        /* Open RX and TX pipes. */
        !          1271:        err = usbd_open_pipe(sc->wi_usb_iface, sc->wi_usb_ed[WI_USB_ENDPT_RX],
        !          1272:            USBD_EXCLUSIVE_USE, &sc->wi_usb_ep[WI_USB_ENDPT_RX]);
        !          1273:        if (err) {
        !          1274:                printf("%s: open rx pipe failed: %s\n",
        !          1275:                    sc->wi_usb_dev.dv_xname, usbd_errstr(err));
        !          1276:                error = EIO;
        !          1277:                goto done;
        !          1278:        }
        !          1279:
        !          1280:        err = usbd_open_pipe(sc->wi_usb_iface, sc->wi_usb_ed[WI_USB_ENDPT_TX],
        !          1281:            USBD_EXCLUSIVE_USE, &sc->wi_usb_ep[WI_USB_ENDPT_TX]);
        !          1282:        if (err) {
        !          1283:                printf("%s: open tx pipe failed: %s\n",
        !          1284:                    sc->wi_usb_dev.dv_xname, usbd_errstr(err));
        !          1285:                error = EIO;
        !          1286:                goto done;
        !          1287:        }
        !          1288:
        !          1289:        /* is this used? */
        !          1290:        err = usbd_open_pipe_intr(sc->wi_usb_iface,
        !          1291:            sc->wi_usb_ed[WI_USB_ENDPT_INTR], USBD_EXCLUSIVE_USE,
        !          1292:            &sc->wi_usb_ep[WI_USB_ENDPT_INTR], sc, &sc->wi_usb_ibuf,
        !          1293:            WI_USB_INTR_PKTLEN, wi_usb_intr, WI_USB_INTR_INTERVAL);
        !          1294:        if (err) {
        !          1295:                printf("%s: open intr pipe failed: %s\n",
        !          1296:                    sc->wi_usb_dev.dv_xname, usbd_errstr(err));
        !          1297:                error = EIO;
        !          1298:                goto done;
        !          1299:        }
        !          1300:
        !          1301:        /* Start up the receive pipe. */
        !          1302:        for (i = 0; i < WI_USB_RX_LIST_CNT; i++) {
        !          1303:                c = &sc->wi_usb_rx_chain[i];
        !          1304:                usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_RX],
        !          1305:                    c, c->wi_usb_buf, WI_USB_BUFSZ,
        !          1306:                    USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
        !          1307:                    wi_usb_rxeof);
        !          1308:                DPRINTFN(10,("%s: %s: start read\n", sc->wi_usb_dev.dv_xname,
        !          1309:                            __func__));
        !          1310:                usbd_transfer(c->wi_usb_xfer);
        !          1311:        }
        !          1312:
        !          1313: done:
        !          1314:        if (--sc->wi_usb_refcnt < 0)
        !          1315:                usb_detach_wakeup(&sc->wi_usb_dev);
        !          1316:
        !          1317:        return (error);
        !          1318: }
        !          1319:
        !          1320: /*
        !          1321:  * This is a bit of a kludge, however wi_rxeof and wi_update_stats
        !          1322:  * call wi_get_fid to determine where the data associated with
        !          1323:  * the transaction is located, the returned id is then used to
        !          1324:  * wi_read_data the information out.
        !          1325:  *
        !          1326:  * This code returns which 'fid' should be used. The results are only valid
        !          1327:  * during a wi_usb_rxeof because the data is received packet is 'held'
        !          1328:  * an a variable for reading by wi_read_data_usb for that period.
        !          1329:  *
        !          1330:  * for magic numbers this uses  0x1000, 0x1001 for rx/info
        !          1331:  */
        !          1332:
        !          1333: int
        !          1334: wi_get_fid_usb(struct wi_softc *sc, int fid)
        !          1335: {
        !          1336:        switch (fid) {
        !          1337:        case WI_RX_FID:
        !          1338:                return 0x1000;
        !          1339:        case WI_INFO_FID:
        !          1340:                return 0x1001;
        !          1341:        default:
        !          1342:                return 0x1111;
        !          1343:        }
        !          1344:
        !          1345: }
        !          1346:
        !          1347: int
        !          1348: wi_usb_activate(struct device *self, enum devact act)
        !          1349: {
        !          1350:        struct wi_usb_softc *sc = (struct wi_usb_softc *)self;
        !          1351:
        !          1352:        DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__));
        !          1353:
        !          1354:        switch (act) {
        !          1355:        case DVACT_ACTIVATE:
        !          1356:                break;
        !          1357:
        !          1358:        case DVACT_DEACTIVATE:
        !          1359:                sc->wi_usb_dying = 1;
        !          1360:                sc->wi_thread_info->dying = 1;
        !          1361:                break;
        !          1362:        }
        !          1363:        return (0);
        !          1364: }
        !          1365:
        !          1366: #if 0
        !          1367: void
        !          1368: wi_dump_data(void *buffer, int len)
        !          1369: {
        !          1370:        int i;
        !          1371:        for (i = 0; i < len; i++) {
        !          1372:                if (((i) % 16) == 0)
        !          1373:                        printf("\n %02x:", i);
        !          1374:                printf(" %02x",
        !          1375:                    ((uint8_t *)(buffer))[i]);
        !          1376:
        !          1377:        }
        !          1378:        printf("\n");
        !          1379:
        !          1380: }
        !          1381: #endif
        !          1382:
        !          1383: /*
        !          1384:  * A frame has been received.
        !          1385:  */
        !          1386: void
        !          1387: wi_usb_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
        !          1388: {
        !          1389:        struct wi_usb_chain     *c = priv;
        !          1390:        struct wi_usb_softc     *sc = c->wi_usb_sc;
        !          1391:        wi_usb_usbin            *uin;
        !          1392:        int                     total_len = 0;
        !          1393:        u_int16_t               rtype;
        !          1394:
        !          1395:        if (sc->wi_usb_dying)
        !          1396:                return;
        !          1397:
        !          1398:        DPRINTFN(10,("%s: %s: enter status=%d\n", sc->wi_usb_dev.dv_xname,
        !          1399:                    __func__, status));
        !          1400:
        !          1401:
        !          1402:        if (status != USBD_NORMAL_COMPLETION) {
        !          1403:                if (status == USBD_NOT_STARTED || status == USBD_IOERROR
        !          1404:                    || status == USBD_CANCELLED) {
        !          1405:                        printf("%s: %u usb errors on rx: %s\n",
        !          1406:                            sc->wi_usb_dev.dv_xname, 1,
        !          1407:                            /* sc->wi_usb_rx_errs, */
        !          1408:                            usbd_errstr(status));
        !          1409:                        return;
        !          1410:                }
        !          1411: #if 0
        !          1412:                sc->wi_usb_rx_errs++;
        !          1413:                if (usbd_ratecheck(&sc->wi_usb_rx_notice)) {
        !          1414:                        printf("%s: %u usb errors on rx: %s\n",
        !          1415:                            sc->wi_usb_dev.dv_xname, sc->wi_usb_rx_errs,
        !          1416:                            usbd_errstr(status));
        !          1417:                        sc->wi_usb_rx_errs = 0;
        !          1418:                }
        !          1419: #endif
        !          1420:                if (status == USBD_STALLED) {
        !          1421:                        sc->wi_usb_refcnt++;
        !          1422:                        usbd_clear_endpoint_stall_async(
        !          1423:                            sc->wi_usb_ep[WI_USB_ENDPT_RX]);
        !          1424:                        if (--sc->wi_usb_refcnt < 0)
        !          1425:                                usb_detach_wakeup(&sc->wi_usb_dev);
        !          1426:                }
        !          1427:                goto done;
        !          1428:        }
        !          1429:
        !          1430:        usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
        !          1431:
        !          1432:        if (total_len < 6) /* short XXX */
        !          1433:                goto done;
        !          1434:
        !          1435:        uin = (wi_usb_usbin *)(c->wi_usb_buf);
        !          1436:
        !          1437:        rtype = letoh16(uin->type);
        !          1438:
        !          1439:
        !          1440: #if 0
        !          1441:        wi_dump_data(c->wi_usb_buf, total_len);
        !          1442: #endif
        !          1443:
        !          1444:        if (WI_USB_ISRXFRM(rtype)) {
        !          1445:                wi_usb_rxfrm(sc, uin, total_len);
        !          1446:                goto done;
        !          1447:        }
        !          1448:        if (WI_USB_ISTXFRM(rtype)) {
        !          1449:                DPRINTFN(2,("%s: %s: txfrm type %x\n",
        !          1450:                    sc->wi_usb_dev.dv_xname, __func__, rtype));
        !          1451:                wi_usb_txfrm(sc, uin, total_len);
        !          1452:                goto done;
        !          1453:        }
        !          1454:
        !          1455:        switch (rtype) {
        !          1456:        case WI_USB_INFOFRM:
        !          1457:                /* info packet, INFO_FID hmm */
        !          1458:                DPRINTFN(10,("%s: %s: infofrm type %x\n",
        !          1459:                    sc->wi_usb_dev.dv_xname, __func__, rtype));
        !          1460:                wi_usb_infofrm(c, total_len);
        !          1461:                break;
        !          1462:        case WI_USB_CMDRESP:
        !          1463:                wi_usb_cmdresp(c);
        !          1464:                break;
        !          1465:        case WI_USB_WRIDRESP:
        !          1466:                wi_usb_wridresp(c);
        !          1467:                break;
        !          1468:        case WI_USB_RRIDRESP:
        !          1469:                wi_usb_rridresp(c);
        !          1470:                break;
        !          1471:        case WI_USB_WMEMRESP:
        !          1472:                /* Not currently used */
        !          1473:                DPRINTFN(2,("%s: %s: wmemresp type %x\n",
        !          1474:                    sc->wi_usb_dev.dv_xname, __func__, rtype));
        !          1475:                break;
        !          1476:        case WI_USB_RMEMRESP:
        !          1477:                /* Not currently used */
        !          1478:                DPRINTFN(2,("%s: %s: rmemresp type %x\n",
        !          1479:                    sc->wi_usb_dev.dv_xname, __func__, rtype));
        !          1480:                break;
        !          1481:        case WI_USB_BUFAVAIL:
        !          1482:                printf("wi_usb: received USB_BUFAVAIL packet\n"); /* XXX */
        !          1483:                break;
        !          1484:        case WI_USB_ERROR:
        !          1485:                printf("wi_usb: received USB_ERROR packet\n"); /* XXX */
        !          1486:                break;
        !          1487: #if 0
        !          1488:        default:
        !          1489:                printf("wi_usb: received Unknown packet 0x%x len %x\n",
        !          1490:                    rtype, total_len);
        !          1491:                wi_dump_data(c->wi_usb_buf, total_len);
        !          1492: #endif
        !          1493:        }
        !          1494:
        !          1495:  done:
        !          1496:        /* Setup new transfer. */
        !          1497:        usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_RX],
        !          1498:            c, c->wi_usb_buf, WI_USB_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
        !          1499:            USBD_NO_TIMEOUT, wi_usb_rxeof);
        !          1500:        sc->wi_usb_refcnt++;
        !          1501:        usbd_transfer(c->wi_usb_xfer);
        !          1502:        if (--sc->wi_usb_refcnt < 0)
        !          1503:                usb_detach_wakeup(&sc->wi_usb_dev);
        !          1504:
        !          1505:        DPRINTFN(10,("%s: %s: start rx\n", sc->wi_usb_dev.dv_xname,
        !          1506:                    __func__));
        !          1507: }
        !          1508:
        !          1509: void
        !          1510: wi_usb_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
        !          1511: {
        !          1512:        struct wi_usb_softc     *sc = priv;
        !          1513:
        !          1514:        DPRINTFN(2,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__));
        !          1515:
        !          1516:        if (sc->wi_usb_dying)
        !          1517:                return;
        !          1518:
        !          1519:        if (status != USBD_NORMAL_COMPLETION) {
        !          1520:                if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
        !          1521:                        return;
        !          1522:
        !          1523:                if (status == USBD_STALLED) {
        !          1524:                        sc->wi_usb_refcnt++;
        !          1525:                        usbd_clear_endpoint_stall_async(
        !          1526:                            sc->wi_usb_ep[WI_USB_ENDPT_RX]);
        !          1527:                        if (--sc->wi_usb_refcnt < 0)
        !          1528:                                usb_detach_wakeup(&sc->wi_usb_dev);
        !          1529:                }
        !          1530:                return;
        !          1531:        }
        !          1532:        /* XXX oerrors or collisions? */
        !          1533: }
        !          1534: void
        !          1535: wi_usb_cmdresp(struct wi_usb_chain *c)
        !          1536: {
        !          1537:        struct wi_cmdresp *presp = (struct wi_cmdresp *)(c->wi_usb_buf);
        !          1538:        u_int16_t status = letoh16(presp->status);
        !          1539:        struct wi_usb_softc     *sc = c->wi_usb_sc;
        !          1540:        uint16_t type;
        !          1541:        uint16_t cmdresperr;
        !          1542:
        !          1543:        type = htole16(presp->type);
        !          1544:        cmdresperr = letoh16(presp->resp0);
        !          1545:        DPRINTFN(10,("%s: %s: enter type=%x, status=%x, cmdresp=%x, "
        !          1546:            "resp=%x,%x,%x\n",
        !          1547:            sc->wi_usb_dev.dv_xname, __func__, type, status, sc->cmdresp,
        !          1548:            cmdresperr, letoh16(presp->resp1),
        !          1549:            letoh16(presp->resp2)));
        !          1550:
        !          1551:        /* XXX */
        !          1552:        if (sc->cmdresp != (status & WI_STAT_CMD_CODE)) {
        !          1553:                DPRINTFN(1,("%s: cmd ty %x st %x cmd %x failed %x\n",
        !          1554:                    sc->wi_usb_dev.dv_xname,
        !          1555:                        type, status, sc->cmdresp, cmdresperr));
        !          1556:                return;
        !          1557:        }
        !          1558:
        !          1559:        sc->cmdresperr = (status & WI_STAT_CMD_RESULT) >> 8;
        !          1560:
        !          1561:        sc->cmdresp = 0; /* good value for idle == INI ?? XXX  */
        !          1562:
        !          1563:        wakeup(&sc->cmdresperr);
        !          1564: }
        !          1565: void
        !          1566: wi_usb_rridresp(struct wi_usb_chain *c)
        !          1567: {
        !          1568:        struct wi_rridresp *presp = (struct wi_rridresp *)(c->wi_usb_buf);
        !          1569:        u_int16_t frmlen = letoh16(presp->frmlen);
        !          1570:        struct wi_usb_softc     *sc = c->wi_usb_sc;
        !          1571:        struct wi_ltv_gen *ltv;
        !          1572:        uint16_t rid;
        !          1573:
        !          1574:        rid = letoh16(presp->rid);
        !          1575:        ltv =  sc->ridltv;
        !          1576:
        !          1577:        if (ltv == 0) {
        !          1578:                DPRINTFN(5,("%s: %s: enter ltv = 0 rid=%x len %d\n",
        !          1579:                    sc->wi_usb_dev.dv_xname, __func__, rid,
        !          1580:                    frmlen));
        !          1581:                return;
        !          1582:        }
        !          1583:
        !          1584:        DPRINTFN(5,("%s: %s: enter rid=%x expecting %x len %d exptlen %d\n",
        !          1585:            sc->wi_usb_dev.dv_xname, __func__, rid, ltv->wi_type,
        !          1586:            frmlen, ltv->wi_len));
        !          1587:
        !          1588:        rid = letoh16(presp->rid);
        !          1589:
        !          1590:        if (rid != ltv->wi_type) {
        !          1591:                sc->ridresperr = EIO;
        !          1592:                return;
        !          1593:        }
        !          1594:
        !          1595:        if (frmlen > ltv->wi_len) {
        !          1596:                sc->ridresperr = ENOSPC;
        !          1597:                sc->ridltv = 0;
        !          1598:                wakeup(&sc->ridresperr);
        !          1599:                return;
        !          1600:        }
        !          1601:
        !          1602:        ltv->wi_len = frmlen;
        !          1603:
        !          1604:        DPRINTFN(10,("%s: %s: copying %d frmlen %d\n",
        !          1605:            sc->wi_usb_dev.dv_xname, __func__, (ltv->wi_len-1)*2,
        !          1606:            frmlen));
        !          1607:
        !          1608:        if (ltv->wi_len > 1)
        !          1609:                bcopy(&presp->data[0], (u_int8_t *)&ltv->wi_val,
        !          1610:                    (ltv->wi_len-1)*2);
        !          1611:
        !          1612:        sc->ridresperr = 0;
        !          1613:        sc->ridltv = 0;
        !          1614:        wakeup(&sc->ridresperr);
        !          1615:
        !          1616: }
        !          1617:
        !          1618: void
        !          1619: wi_usb_wridresp(struct wi_usb_chain *c)
        !          1620: {
        !          1621:        struct wi_wridresp *presp = (struct wi_wridresp *)(c->wi_usb_buf);
        !          1622:        struct wi_usb_softc     *sc = c->wi_usb_sc;
        !          1623:        uint16_t status;
        !          1624:
        !          1625:        status = letoh16(presp->status);
        !          1626:
        !          1627:        DPRINTFN(10,("%s: %s: enter status=%x\n",
        !          1628:            sc->wi_usb_dev.dv_xname, __func__, status));
        !          1629:
        !          1630:        sc->ridresperr = (status & WI_STAT_CMD_RESULT) >> 8;
        !          1631:        sc->ridltv = 0;
        !          1632:        wakeup(&sc->ridresperr);
        !          1633: }
        !          1634:
        !          1635: void
        !          1636: wi_usb_infofrm(struct wi_usb_chain *c, int len)
        !          1637: {
        !          1638:        struct wi_usb_softc     *sc = c->wi_usb_sc;
        !          1639:
        !          1640:        DPRINTFN(10,("%s: %s: enter\n",
        !          1641:            sc->wi_usb_dev.dv_xname, __func__));
        !          1642:
        !          1643:        sc->wi_info = ((char *)c->wi_usb_buf) + 2;
        !          1644:        wi_update_stats(&sc->sc_wi);
        !          1645:        sc->wi_info = NULL;
        !          1646: }
        !          1647:
        !          1648: void
        !          1649: wi_usb_txfrm(struct wi_usb_softc *sc, wi_usb_usbin *uin, int total_len)
        !          1650: {
        !          1651:        u_int16_t               status;
        !          1652:        int                     s;
        !          1653:        struct wi_softc         *wsc = &sc->sc_wi;
        !          1654:        struct ifnet            *ifp = &wsc->sc_ic.ic_if;
        !          1655:
        !          1656:        s = splnet();
        !          1657:        status = letoh16(uin->type); /* XXX -- type == status */
        !          1658:
        !          1659:
        !          1660:        DPRINTFN(2,("%s: %s: enter status=%d\n",
        !          1661:            sc->wi_usb_dev.dv_xname, __func__, status));
        !          1662:
        !          1663:        if (sc->txresp == WI_CMD_TX) {
        !          1664:                sc->txresperr=status;
        !          1665:                sc->txresp = 0;
        !          1666:                wakeup(&sc->txresperr);
        !          1667:        } else {
        !          1668:                if (status != 0) /* XXX */
        !          1669:                        wi_watchdog_usb(ifp);
        !          1670:        DPRINTFN(1,("%s: %s: txresp not expected status=%d \n",
        !          1671:            sc->wi_usb_dev.dv_xname, __func__, status));
        !          1672:        }
        !          1673:
        !          1674:        splx(s);
        !          1675: }
        !          1676: void
        !          1677: wi_usb_rxfrm(struct wi_usb_softc *sc, wi_usb_usbin *uin, int total_len)
        !          1678: {
        !          1679:        int s;
        !          1680:
        !          1681:        DPRINTFN(5,("%s: %s: enter len=%d\n",
        !          1682:            sc->wi_usb_dev.dv_xname, __func__, total_len));
        !          1683:
        !          1684:        s = splnet();
        !          1685:
        !          1686:        sc->wi_rxframe = (void *)uin;
        !          1687:
        !          1688:        wi_rxeof(&sc->sc_wi);
        !          1689:
        !          1690:        sc->wi_rxframe = NULL;
        !          1691:
        !          1692:        splx(s);
        !          1693:
        !          1694: }
        !          1695:
        !          1696:
        !          1697: void
        !          1698: wi_usb_start_thread(void *arg)
        !          1699: {
        !          1700:        struct wi_usb_softc     *sc = arg;
        !          1701:        kthread_create (wi_usb_thread, arg, NULL, sc->wi_usb_dev.dv_xname);
        !          1702: }
        !          1703:
        !          1704: void
        !          1705: wi_start_usb(struct ifnet *ifp)
        !          1706: {
        !          1707:        struct wi_softc         *wsc;
        !          1708:        struct wi_usb_softc     *sc;
        !          1709:        int s;
        !          1710:
        !          1711:        wsc = ifp->if_softc;
        !          1712:        sc  = wsc->wi_usb_cdata;
        !          1713:
        !          1714:        s = splnet();
        !          1715:
        !          1716:        DPRINTFN(5,("%s: %s:\n",
        !          1717:            sc->wi_usb_dev.dv_xname, __func__));
        !          1718:
        !          1719:        if (wi_usb_tx_lock_try(sc)) {
        !          1720:                /* lock acquired do start now */
        !          1721:                wi_func_io.f_start(ifp);
        !          1722:        } else {
        !          1723:                sc->wi_thread_info->status |= WI_START;
        !          1724:                if (sc->wi_thread_info->idle)
        !          1725:                        wakeup(sc->wi_thread_info);
        !          1726:        }
        !          1727:
        !          1728:        splx(s);
        !          1729: }
        !          1730:
        !          1731: /*
        !          1732:  * inquire is called from interrupt context (timeout)
        !          1733:  * It is not possible to sleep in interrupt context so it is necessary
        !          1734:  * to signal the kernel thread to perform the action.
        !          1735:  */
        !          1736: void
        !          1737: wi_init_usb(struct wi_softc *wsc)
        !          1738: {
        !          1739:        DPRINTFN(5,("%s: %s:\n", WI_PRT_ARG(wsc), __func__));
        !          1740:
        !          1741:        wi_usb_ctl_lock(wsc->wi_usb_cdata);
        !          1742:        wi_func_io.f_init(wsc);
        !          1743:        wi_usb_ctl_unlock(wsc->wi_usb_cdata);
        !          1744: }
        !          1745:
        !          1746:
        !          1747: /*
        !          1748:  * inquire is called from interrupt context (timeout)
        !          1749:  * It is not possible to sleep in interrupt context so it is necessary
        !          1750:  * to signal the kernel thread to perform the action.
        !          1751:  */
        !          1752: void
        !          1753: wi_inquire_usb(void *xsc)
        !          1754: {
        !          1755:        struct wi_softc         *wsc = xsc;
        !          1756:        struct wi_usb_softc     *sc = wsc->wi_usb_cdata;
        !          1757:        int s;
        !          1758:
        !          1759:
        !          1760:        s = splnet();
        !          1761:
        !          1762:        DPRINTFN(2,("%s: %s:\n",
        !          1763:            sc->wi_usb_dev.dv_xname, __func__));
        !          1764:
        !          1765:        sc->wi_thread_info->status |= WI_INQUIRE;
        !          1766:
        !          1767:        if (sc->wi_thread_info->idle)
        !          1768:                wakeup(sc->wi_thread_info);
        !          1769:        splx(s);
        !          1770: }
        !          1771:
        !          1772: /*
        !          1773:  * Watchdog is normally called from interrupt context (timeout)
        !          1774:  * It is not possible to sleep in interrupt context so it is necessary
        !          1775:  * to signal the kernel thread to perform the action.
        !          1776:  */
        !          1777: void
        !          1778: wi_watchdog_usb(struct ifnet *ifp)
        !          1779: {
        !          1780:        struct wi_softc         *wsc;
        !          1781:        struct wi_usb_softc     *sc;
        !          1782:        int s;
        !          1783:
        !          1784:        wsc = ifp->if_softc;
        !          1785:        sc = wsc->wi_usb_cdata;
        !          1786:
        !          1787:        s = splnet();
        !          1788:
        !          1789:        DPRINTFN(5,("%s: %s: ifp %x\n",
        !          1790:            sc->wi_usb_dev.dv_xname, __func__, ifp));
        !          1791:
        !          1792:        sc->wi_thread_info->status |= WI_WATCHDOG;
        !          1793:
        !          1794:        if (sc->wi_thread_info->idle)
        !          1795:                wakeup(sc->wi_thread_info);
        !          1796:        splx(s);
        !          1797: }
        !          1798:
        !          1799: /*
        !          1800:  * ioctl will always be called from a user context,
        !          1801:  * therefore it is possible to sleep in the calling context
        !          1802:  * acquire the lock and call the real ioctl fucntion directly
        !          1803:  */
        !          1804: int
        !          1805: wi_ioctl_usb(struct ifnet *ifp, u_long command, caddr_t data)
        !          1806: {
        !          1807:        struct wi_softc         *wsc;
        !          1808:        int err;
        !          1809:
        !          1810:        wsc = ifp->if_softc;
        !          1811:
        !          1812:        wi_usb_ctl_lock(wsc->wi_usb_cdata);
        !          1813:        err = wi_func_io.f_ioctl(ifp, command, data);
        !          1814:        wi_usb_ctl_unlock(wsc->wi_usb_cdata);
        !          1815:        return err;
        !          1816: }
        !          1817:
        !          1818: void
        !          1819: wi_usb_thread(void *arg)
        !          1820: {
        !          1821:        struct wi_usb_softc *sc = arg;
        !          1822:        struct wi_usb_thread_info *wi_thread_info;
        !          1823:        int s;
        !          1824:
        !          1825:        wi_thread_info = malloc(sizeof(*wi_thread_info), M_DEVBUF, M_WAITOK);
        !          1826:
        !          1827:        /*
        !          1828:         * is there a remote possibility that the device could
        !          1829:         * be removed before the kernel thread starts up?
        !          1830:         */
        !          1831:
        !          1832:        sc->wi_usb_refcnt++;
        !          1833:
        !          1834:        sc->wi_thread_info = wi_thread_info;
        !          1835:        wi_thread_info->dying = 0;
        !          1836:        wi_thread_info->status = 0;
        !          1837:
        !          1838:        wi_usb_ctl_lock(sc);
        !          1839:
        !          1840:        wi_attach(&sc->sc_wi, &wi_func_usb);
        !          1841:
        !          1842:        wi_usb_ctl_unlock(sc);
        !          1843:
        !          1844:        for(;;) {
        !          1845:                if (wi_thread_info->dying) {
        !          1846:                        if (--sc->wi_usb_refcnt < 0)
        !          1847:                                usb_detach_wakeup(&sc->wi_usb_dev);
        !          1848:                        kthread_exit(0);
        !          1849:                }
        !          1850:
        !          1851:                DPRINTFN(5,("%s: %s: dying %x status %x\n",
        !          1852:                    sc->wi_usb_dev.dv_xname, __func__,
        !          1853:                        wi_thread_info->dying, wi_thread_info->status));
        !          1854:
        !          1855:                wi_usb_ctl_lock(sc);
        !          1856:
        !          1857:                DPRINTFN(5,("%s: %s: starting %x\n",
        !          1858:                    sc->wi_usb_dev.dv_xname, __func__,
        !          1859:                    wi_thread_info->status));
        !          1860:
        !          1861:                s = splusb();
        !          1862:                if (wi_thread_info->status & WI_START) {
        !          1863:                        wi_thread_info->status &= ~WI_START;
        !          1864:                        wi_usb_tx_lock(sc);
        !          1865:                        wi_func_io.f_start(&sc->sc_wi.sc_ic.ic_if);
        !          1866:                        /*
        !          1867:                         * tx_unlock is explicitly missing here
        !          1868:                         * it is done in txeof_frm
        !          1869:                         */
        !          1870:                } else if (wi_thread_info->status & WI_INQUIRE) {
        !          1871:                        wi_thread_info->status &= ~WI_INQUIRE;
        !          1872:                        wi_func_io.f_inquire(&sc->sc_wi);
        !          1873:                } else if (wi_thread_info->status & WI_WATCHDOG) {
        !          1874:                        wi_thread_info->status &= ~WI_WATCHDOG;
        !          1875:                        wi_func_io.f_watchdog( &sc->sc_wi.sc_ic.ic_if);
        !          1876:                }
        !          1877:                splx(s);
        !          1878:
        !          1879:                DPRINTFN(5,("%s: %s: ending %x\n",
        !          1880:                    sc->wi_usb_dev.dv_xname, __func__,
        !          1881:                    wi_thread_info->status));
        !          1882:                wi_usb_ctl_unlock(sc);
        !          1883:
        !          1884:                if (wi_thread_info->status == 0) {
        !          1885:                        s = splnet();
        !          1886:                        wi_thread_info->idle = 1;
        !          1887:                        tsleep(wi_thread_info, PRIBIO, "wiIDL", 0);
        !          1888:                        wi_thread_info->idle = 0;
        !          1889:                        splx(s);
        !          1890:                }
        !          1891:        }
        !          1892: }
        !          1893:
        !          1894: int
        !          1895: wi_usb_tx_lock_try(struct wi_usb_softc *sc)
        !          1896: {
        !          1897:        int s;
        !          1898:
        !          1899:        s = splnet();
        !          1900:
        !          1901:        DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__));
        !          1902:
        !          1903:        if (sc->wi_lock != 0) {
        !          1904:                return 0; /* failed to aquire lock */
        !          1905:        }
        !          1906:
        !          1907:        sc->wi_lock = 1;
        !          1908:
        !          1909:        splx(s);
        !          1910:
        !          1911:        return 1;
        !          1912: }
        !          1913: void
        !          1914: wi_usb_tx_lock(struct wi_usb_softc *sc)
        !          1915: {
        !          1916:        int s;
        !          1917:
        !          1918:        s = splnet();
        !          1919:
        !          1920:        again:
        !          1921:        DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__));
        !          1922:
        !          1923:        if (sc->wi_lock != 0) {
        !          1924:                sc->wi_lockwait++;
        !          1925:                DPRINTFN(10,("%s: %s: busy %d\n", sc->wi_usb_dev.dv_xname,
        !          1926:                __func__, sc->wi_lockwait ));
        !          1927:                tsleep(&sc->wi_lock, PRIBIO, "witxl", 0);
        !          1928:        }
        !          1929:
        !          1930:        if (sc->wi_lock != 0)
        !          1931:                goto again;
        !          1932:        sc->wi_lock = 1;
        !          1933:
        !          1934:        splx(s);
        !          1935:
        !          1936:        return;
        !          1937:
        !          1938: }
        !          1939:
        !          1940: void
        !          1941: wi_usb_tx_unlock(struct wi_usb_softc *sc)
        !          1942: {
        !          1943:        int s;
        !          1944:        s = splnet();
        !          1945:
        !          1946:        sc->wi_lock = 0;
        !          1947:
        !          1948:        DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__));
        !          1949:
        !          1950:        if (sc->wi_lockwait) {
        !          1951:                DPRINTFN(10,("%s: %s: waking\n",
        !          1952:                    sc->wi_usb_dev.dv_xname, __func__));
        !          1953:                sc->wi_lockwait = 0;
        !          1954:                wakeup(&sc->wi_lock);
        !          1955:        }
        !          1956:
        !          1957:        splx(s);
        !          1958: }
        !          1959:
        !          1960: void
        !          1961: wi_usb_ctl_lock(struct wi_usb_softc *sc)
        !          1962: {
        !          1963:        int s;
        !          1964:
        !          1965:        s = splnet();
        !          1966:
        !          1967:        again:
        !          1968:        DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname,
        !          1969:            __func__));
        !          1970:
        !          1971:        if (sc->wi_ctllock != 0) {
        !          1972:                if (curproc == sc->wi_curproc) {
        !          1973:                        /* allow recursion */
        !          1974:                        sc->wi_ctllock++;
        !          1975:                        splx(s);
        !          1976:                        return;
        !          1977:                }
        !          1978:                sc->wi_ctllockwait++;
        !          1979:                DPRINTFN(10,("%s: %s: busy %d\n", sc->wi_usb_dev.dv_xname,
        !          1980:                __func__, sc->wi_ctllockwait ));
        !          1981:                tsleep(&sc->wi_ctllock, PRIBIO, "wiusbthr", 0);
        !          1982:        }
        !          1983:
        !          1984:        if (sc->wi_ctllock != 0)
        !          1985:                goto again;
        !          1986:        sc->wi_ctllock++;
        !          1987:        sc->wi_curproc = curproc;
        !          1988:
        !          1989:        splx(s);
        !          1990:
        !          1991:        return;
        !          1992:
        !          1993: }
        !          1994:
        !          1995: void
        !          1996: wi_usb_ctl_unlock(struct wi_usb_softc *sc)
        !          1997: {
        !          1998:        int s;
        !          1999:
        !          2000:        s = splnet();
        !          2001:
        !          2002:        sc->wi_ctllock--;
        !          2003:
        !          2004:        DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname, __func__));
        !          2005:
        !          2006:        if (sc->wi_ctllock == 0 && sc->wi_ctllockwait) {
        !          2007:                DPRINTFN(10,("%s: %s: waking\n",
        !          2008:                    sc->wi_usb_dev.dv_xname, __func__));
        !          2009:                sc->wi_ctllockwait = 0;
        !          2010:                sc->wi_curproc = 0;
        !          2011:                wakeup(&sc->wi_ctllock);
        !          2012:        }
        !          2013:
        !          2014:        splx(s);
        !          2015: }

CVSweb