root/dev/usb/if_wi_usb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wi_usb_match
  2. wi_usb_attach
  3. wi_usb_detach
  4. wi_send_packet
  5. wi_cmd_usb
  6. wi_read_record_usb
  7. wi_write_record_usb
  8. wi_alloc_nicmem_usb
  9. wi_write_data_usb
  10. wi_read_data_usb
  11. wi_usb_stop
  12. wi_usb_do_transmit_sync
  13. wi_usb_txeof
  14. wi_usb_txeof_frm
  15. wi_usb_rx_list_init
  16. wi_usb_tx_list_init
  17. wi_usb_open_pipes
  18. wi_get_fid_usb
  19. wi_usb_activate
  20. wi_dump_data
  21. wi_usb_rxeof
  22. wi_usb_intr
  23. wi_usb_cmdresp
  24. wi_usb_rridresp
  25. wi_usb_wridresp
  26. wi_usb_infofrm
  27. wi_usb_txfrm
  28. wi_usb_rxfrm
  29. wi_usb_start_thread
  30. wi_start_usb
  31. wi_init_usb
  32. wi_inquire_usb
  33. wi_watchdog_usb
  34. wi_ioctl_usb
  35. wi_usb_thread
  36. wi_usb_tx_lock_try
  37. wi_usb_tx_lock
  38. wi_usb_tx_unlock
  39. wi_usb_ctl_lock
  40. wi_usb_ctl_unlock

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

/* [<][>][^][v][top][bottom][index][help] */