[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

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