LCOV - code coverage report
Current view: top level - dev/usb - if_wi_usb.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 777 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 38 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13