if_ndis_usb.c revision 257176
1142399Swpaul/*- 2142399Swpaul * Copyright (c) 2005 3142415Swpaul * Bill Paul <wpaul@windriver.com>. All rights reserved. 4142399Swpaul * 5142399Swpaul * Redistribution and use in source and binary forms, with or without 6142399Swpaul * modification, are permitted provided that the following conditions 7142399Swpaul * are met: 8142399Swpaul * 1. Redistributions of source code must retain the above copyright 9142399Swpaul * notice, this list of conditions and the following disclaimer. 10142399Swpaul * 2. Redistributions in binary form must reproduce the above copyright 11142399Swpaul * notice, this list of conditions and the following disclaimer in the 12142399Swpaul * documentation and/or other materials provided with the distribution. 13142399Swpaul * 3. All advertising materials mentioning features or use of this software 14142399Swpaul * must display the following acknowledgement: 15142399Swpaul * This product includes software developed by Bill Paul. 16142399Swpaul * 4. Neither the name of the author nor the names of any co-contributors 17142399Swpaul * may be used to endorse or promote products derived from this software 18142399Swpaul * without specific prior written permission. 19142399Swpaul * 20142399Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21142399Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22142399Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23142399Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24142399Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25142399Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26142399Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27142399Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28142399Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29142399Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30142399Swpaul * THE POSSIBILITY OF SUCH DAMAGE. 31142399Swpaul */ 32142399Swpaul 33142399Swpaul#include <sys/cdefs.h> 34142399Swpaul__FBSDID("$FreeBSD: head/sys/dev/if_ndis/if_ndis_usb.c 257176 2013-10-26 17:58:36Z glebius $"); 35142399Swpaul 36142399Swpaul#include <sys/param.h> 37142399Swpaul#include <sys/systm.h> 38142399Swpaul#include <sys/sockio.h> 39145485Swpaul#include <sys/module.h> 40142399Swpaul#include <sys/malloc.h> 41142399Swpaul#include <sys/kernel.h> 42142399Swpaul#include <sys/socket.h> 43142399Swpaul#include <sys/sysctl.h> 44142399Swpaul 45142399Swpaul#include <net/if.h> 46257176Sglebius#include <net/if_var.h> 47142399Swpaul#include <net/if_arp.h> 48142399Swpaul#include <net/ethernet.h> 49142399Swpaul#include <net/if_dl.h> 50142399Swpaul#include <net/if_media.h> 51142399Swpaul 52142399Swpaul#include <net/bpf.h> 53142399Swpaul 54142399Swpaul#include <sys/bus.h> 55142399Swpaul#include <machine/bus.h> 56189488Sweongyo#include <dev/usb/usb.h> 57194677Sthompsa#include <dev/usb/usbdi.h> 58142399Swpaul 59142399Swpaul#include <net80211/ieee80211_var.h> 60142399Swpaul 61142399Swpaul#include <compat/ndis/pe_var.h> 62145485Swpaul#include <compat/ndis/cfg_var.h> 63142399Swpaul#include <compat/ndis/resource_var.h> 64142399Swpaul#include <compat/ndis/ntoskrnl_var.h> 65142399Swpaul#include <compat/ndis/ndis_var.h> 66186507Sweongyo#include <compat/ndis/usbd_var.h> 67142399Swpaul#include <dev/if_ndis/if_ndisvar.h> 68142399Swpaul 69186507SweongyoSYSCTL_NODE(_hw, OID_AUTO, ndisusb, CTLFLAG_RD, 0, "NDIS USB driver parameters"); 70186507Sweongyo 71142399SwpaulMODULE_DEPEND(ndis, usb, 1, 1, 1); 72142399Swpaul 73170934Simpstatic device_probe_t ndisusb_match; 74170934Simpstatic device_attach_t ndisusb_attach; 75186507Sweongyostatic device_detach_t ndisusb_detach; 76170934Simpstatic bus_get_resource_list_t ndis_get_resource_list; 77142399Swpaul 78142399Swpaulextern int ndisdrv_modevent (module_t, int, void *); 79142399Swpaulextern int ndis_attach (device_t); 80142399Swpaulextern int ndis_shutdown (device_t); 81142399Swpaulextern int ndis_detach (device_t); 82142399Swpaulextern int ndis_suspend (device_t); 83142399Swpaulextern int ndis_resume (device_t); 84142399Swpaul 85142399Swpaulextern unsigned char drv_data[]; 86142399Swpaul 87162102Smjacobstatic device_method_t ndis_methods[] = { 88142399Swpaul /* Device interface */ 89142399Swpaul DEVMETHOD(device_probe, ndisusb_match), 90142399Swpaul DEVMETHOD(device_attach, ndisusb_attach), 91186507Sweongyo DEVMETHOD(device_detach, ndisusb_detach), 92142399Swpaul DEVMETHOD(device_shutdown, ndis_shutdown), 93142399Swpaul 94142399Swpaul /* bus interface */ 95142399Swpaul DEVMETHOD(bus_get_resource_list, ndis_get_resource_list), 96142399Swpaul 97227843Smarius DEVMETHOD_END 98142399Swpaul}; 99142399Swpaul 100162102Smjacobstatic driver_t ndis_driver = { 101142399Swpaul "ndis", 102142399Swpaul ndis_methods, 103142399Swpaul sizeof(struct ndis_softc) 104142399Swpaul}; 105142399Swpaul 106162102Smjacobstatic devclass_t ndis_devclass; 107142399Swpaul 108142399SwpaulDRIVER_MODULE(ndis, uhub, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); 109142399Swpaul 110170934Simpstatic int 111186507Sweongyondisusb_devcompare(interface_type bustype, struct ndis_usb_type *t, device_t dev) 112186507Sweongyo{ 113192984Sthompsa struct usb_attach_arg *uaa; 114186507Sweongyo 115186507Sweongyo if (bustype != PNPBus) 116186507Sweongyo return (FALSE); 117186507Sweongyo 118186507Sweongyo uaa = device_get_ivars(dev); 119186507Sweongyo 120186507Sweongyo while (t->ndis_name != NULL) { 121189488Sweongyo if ((uaa->info.idVendor == t->ndis_vid) && 122189488Sweongyo (uaa->info.idProduct == t->ndis_did)) { 123186507Sweongyo device_set_desc(dev, t->ndis_name); 124186507Sweongyo return (TRUE); 125186507Sweongyo } 126186507Sweongyo t++; 127186507Sweongyo } 128186507Sweongyo 129186507Sweongyo return (FALSE); 130186507Sweongyo} 131186507Sweongyo 132186507Sweongyostatic int 133170934Simpndisusb_match(device_t self) 134142399Swpaul{ 135186507Sweongyo struct drvdb_ent *db; 136192984Sthompsa struct usb_attach_arg *uaa = device_get_ivars(self); 137142399Swpaul 138192505Sthompsa if (uaa->usb_mode != USB_MODE_HOST) 139189488Sweongyo return (ENXIO); 140189488Sweongyo if (uaa->info.bConfigIndex != NDISUSB_CONFIG_NO) 141189488Sweongyo return (ENXIO); 142189488Sweongyo if (uaa->info.bIfaceIndex != NDISUSB_IFACE_INDEX) 143189488Sweongyo return (ENXIO); 144189488Sweongyo 145142804Swpaul if (windrv_lookup(0, "USB Bus") == NULL) 146189488Sweongyo return (ENXIO); 147142399Swpaul 148186507Sweongyo db = windrv_match((matchfuncptr)ndisusb_devcompare, self); 149186507Sweongyo if (db == NULL) 150189488Sweongyo return (ENXIO); 151193742Sthompsa uaa->driver_ivar = db; 152186507Sweongyo 153189488Sweongyo return (0); 154142399Swpaul} 155142399Swpaul 156170934Simpstatic int 157170934Simpndisusb_attach(device_t self) 158142399Swpaul{ 159189488Sweongyo const struct drvdb_ent *db; 160170934Simp struct ndisusb_softc *dummy = device_get_softc(self); 161192984Sthompsa struct usb_attach_arg *uaa = device_get_ivars(self); 162142399Swpaul struct ndis_softc *sc; 163186507Sweongyo struct ndis_usb_type *t; 164142408Swpaul driver_object *drv; 165186507Sweongyo int devidx = 0; 166142399Swpaul 167200824Sthompsa device_set_usb_desc(self); 168193742Sthompsa db = uaa->driver_ivar; 169142399Swpaul sc = (struct ndis_softc *)dummy; 170142399Swpaul sc->ndis_dev = self; 171189719Sweongyo mtx_init(&sc->ndisusb_mtx, "NDIS USB", MTX_NETWORK_LOCK, MTX_DEF); 172186507Sweongyo sc->ndis_dobj = db->windrv_object; 173186507Sweongyo sc->ndis_regvals = db->windrv_regvals; 174186507Sweongyo sc->ndis_iftype = PNPBus; 175189488Sweongyo sc->ndisusb_dev = uaa->device; 176142399Swpaul 177142408Swpaul /* Create PDO for this device instance */ 178142408Swpaul 179142804Swpaul drv = windrv_lookup(0, "USB Bus"); 180142408Swpaul windrv_create_pdo(drv, self); 181142408Swpaul 182186507Sweongyo /* Figure out exactly which device we matched. */ 183186507Sweongyo 184186507Sweongyo t = db->windrv_devlist; 185186507Sweongyo 186186507Sweongyo while (t->ndis_name != NULL) { 187189488Sweongyo if ((uaa->info.idVendor == t->ndis_vid) && 188189488Sweongyo (uaa->info.idProduct == t->ndis_did)) { 189186507Sweongyo sc->ndis_devidx = devidx; 190186507Sweongyo break; 191186507Sweongyo } 192186507Sweongyo t++; 193186507Sweongyo devidx++; 194186507Sweongyo } 195186507Sweongyo 196142399Swpaul if (ndis_attach(self) != 0) 197198786Srpaulo return (ENXIO); 198142399Swpaul 199198786Srpaulo return (0); 200142399Swpaul} 201142399Swpaul 202186507Sweongyostatic int 203186507Sweongyondisusb_detach(device_t self) 204186507Sweongyo{ 205186507Sweongyo int i; 206186507Sweongyo struct ndis_softc *sc = device_get_softc(self); 207201758Smbr struct ndisusb_ep *ne; 208186507Sweongyo 209186507Sweongyo sc->ndisusb_status |= NDISUSB_STATUS_DETACH; 210186507Sweongyo 211189719Sweongyo ndis_pnpevent_nic(self, NDIS_PNP_EVENT_SURPRISE_REMOVED); 212189719Sweongyo 213189950Sweongyo if (sc->ndisusb_status & NDISUSB_STATUS_SETUP_EP) { 214194228Sthompsa usbd_transfer_unsetup(sc->ndisusb_dread_ep.ne_xfer, 1); 215194228Sthompsa usbd_transfer_unsetup(sc->ndisusb_dwrite_ep.ne_xfer, 1); 216189950Sweongyo } 217186507Sweongyo for (i = 0; i < NDISUSB_ENDPT_MAX; i++) { 218189488Sweongyo ne = &sc->ndisusb_ep[i]; 219194228Sthompsa usbd_transfer_unsetup(ne->ne_xfer, 1); 220186507Sweongyo } 221186507Sweongyo 222189719Sweongyo (void)ndis_detach(self); 223186507Sweongyo 224189719Sweongyo mtx_destroy(&sc->ndisusb_mtx); 225189719Sweongyo return (0); 226186507Sweongyo} 227186507Sweongyo 228142399Swpaulstatic struct resource_list * 229170934Simpndis_get_resource_list(device_t dev, device_t child) 230142399Swpaul{ 231142399Swpaul struct ndis_softc *sc; 232142399Swpaul 233142399Swpaul sc = device_get_softc(dev); 234142399Swpaul return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); 235142399Swpaul} 236