if_ndis_usb.c revision 189488
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 189488 2009-03-07 07:26:22Z weongyo $"); 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> 46142399Swpaul#include <net/if_arp.h> 47142399Swpaul#include <net/ethernet.h> 48142399Swpaul#include <net/if_dl.h> 49142399Swpaul#include <net/if_media.h> 50142399Swpaul 51142399Swpaul#include <net/bpf.h> 52142399Swpaul 53142399Swpaul#include <sys/bus.h> 54142399Swpaul#include <machine/bus.h> 55189488Sweongyo#include <dev/usb/usb.h> 56189488Sweongyo#include <dev/usb/usb_core.h> 57142399Swpaul 58142399Swpaul#include <net80211/ieee80211_var.h> 59142399Swpaul 60142399Swpaul#include <compat/ndis/pe_var.h> 61145485Swpaul#include <compat/ndis/cfg_var.h> 62142399Swpaul#include <compat/ndis/resource_var.h> 63142399Swpaul#include <compat/ndis/ntoskrnl_var.h> 64142399Swpaul#include <compat/ndis/ndis_var.h> 65186507Sweongyo#include <compat/ndis/usbd_var.h> 66142399Swpaul#include <dev/if_ndis/if_ndisvar.h> 67142399Swpaul 68186507SweongyoSYSCTL_NODE(_hw, OID_AUTO, ndisusb, CTLFLAG_RD, 0, "NDIS USB driver parameters"); 69186507Sweongyo 70142399SwpaulMODULE_DEPEND(ndis, usb, 1, 1, 1); 71142399Swpaul 72170934Simpstatic device_probe_t ndisusb_match; 73170934Simpstatic device_attach_t ndisusb_attach; 74186507Sweongyostatic device_detach_t ndisusb_detach; 75170934Simpstatic bus_get_resource_list_t ndis_get_resource_list; 76142399Swpaul 77142399Swpaulextern int ndisdrv_modevent (module_t, int, void *); 78142399Swpaulextern int ndis_attach (device_t); 79142399Swpaulextern int ndis_shutdown (device_t); 80142399Swpaulextern int ndis_detach (device_t); 81142399Swpaulextern int ndis_suspend (device_t); 82142399Swpaulextern int ndis_resume (device_t); 83142399Swpaul 84142399Swpaulextern unsigned char drv_data[]; 85142399Swpaul 86162102Smjacobstatic device_method_t ndis_methods[] = { 87142399Swpaul /* Device interface */ 88142399Swpaul DEVMETHOD(device_probe, ndisusb_match), 89142399Swpaul DEVMETHOD(device_attach, ndisusb_attach), 90186507Sweongyo DEVMETHOD(device_detach, ndisusb_detach), 91142399Swpaul DEVMETHOD(device_shutdown, ndis_shutdown), 92142399Swpaul 93142399Swpaul /* bus interface */ 94142399Swpaul DEVMETHOD(bus_print_child, bus_generic_print_child), 95142399Swpaul DEVMETHOD(bus_driver_added, bus_generic_driver_added), 96142399Swpaul DEVMETHOD(bus_get_resource_list, ndis_get_resource_list), 97142399Swpaul 98142399Swpaul { 0, 0 } 99142399Swpaul}; 100142399Swpaul 101162102Smjacobstatic driver_t ndis_driver = { 102142399Swpaul "ndis", 103142399Swpaul ndis_methods, 104142399Swpaul sizeof(struct ndis_softc) 105142399Swpaul}; 106142399Swpaul 107162102Smjacobstatic devclass_t ndis_devclass; 108142399Swpaul 109142399SwpaulDRIVER_MODULE(ndis, uhub, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); 110142399Swpaul 111170934Simpstatic int 112186507Sweongyondisusb_devcompare(interface_type bustype, struct ndis_usb_type *t, device_t dev) 113186507Sweongyo{ 114189488Sweongyo struct usb2_attach_arg *uaa; 115186507Sweongyo 116186507Sweongyo if (bustype != PNPBus) 117186507Sweongyo return (FALSE); 118186507Sweongyo 119186507Sweongyo uaa = device_get_ivars(dev); 120186507Sweongyo 121186507Sweongyo while (t->ndis_name != NULL) { 122189488Sweongyo if ((uaa->info.idVendor == t->ndis_vid) && 123189488Sweongyo (uaa->info.idProduct == t->ndis_did)) { 124186507Sweongyo device_set_desc(dev, t->ndis_name); 125186507Sweongyo return (TRUE); 126186507Sweongyo } 127186507Sweongyo t++; 128186507Sweongyo } 129186507Sweongyo 130186507Sweongyo return (FALSE); 131186507Sweongyo} 132186507Sweongyo 133186507Sweongyostatic int 134170934Simpndisusb_match(device_t self) 135142399Swpaul{ 136186507Sweongyo struct drvdb_ent *db; 137189488Sweongyo struct usb2_attach_arg *uaa = device_get_ivars(self); 138142399Swpaul 139189488Sweongyo if (uaa->usb2_mode != USB_MODE_HOST) 140189488Sweongyo return (ENXIO); 141189488Sweongyo if (uaa->info.bConfigIndex != NDISUSB_CONFIG_NO) 142189488Sweongyo return (ENXIO); 143189488Sweongyo if (uaa->info.bIfaceIndex != NDISUSB_IFACE_INDEX) 144189488Sweongyo return (ENXIO); 145189488Sweongyo 146142804Swpaul if (windrv_lookup(0, "USB Bus") == NULL) 147189488Sweongyo return (ENXIO); 148142399Swpaul 149186507Sweongyo db = windrv_match((matchfuncptr)ndisusb_devcompare, self); 150186507Sweongyo if (db == NULL) 151189488Sweongyo return (ENXIO); 152189488Sweongyo uaa->driver_info = db; 153186507Sweongyo 154189488Sweongyo return (0); 155142399Swpaul} 156142399Swpaul 157170934Simpstatic int 158170934Simpndisusb_attach(device_t self) 159142399Swpaul{ 160189488Sweongyo const struct drvdb_ent *db; 161170934Simp struct ndisusb_softc *dummy = device_get_softc(self); 162189488Sweongyo struct usb2_attach_arg *uaa = device_get_ivars(self); 163142399Swpaul struct ndis_softc *sc; 164186507Sweongyo struct ndis_usb_type *t; 165142408Swpaul driver_object *drv; 166186507Sweongyo int devidx = 0; 167142399Swpaul 168189488Sweongyo db = uaa->driver_info; 169142399Swpaul sc = (struct ndis_softc *)dummy; 170142399Swpaul sc->ndis_dev = self; 171186507Sweongyo sc->ndis_dobj = db->windrv_object; 172186507Sweongyo sc->ndis_regvals = db->windrv_regvals; 173186507Sweongyo sc->ndis_iftype = PNPBus; 174189488Sweongyo sc->ndisusb_dev = uaa->device; 175142399Swpaul 176142408Swpaul /* Create PDO for this device instance */ 177142408Swpaul 178142804Swpaul drv = windrv_lookup(0, "USB Bus"); 179142408Swpaul windrv_create_pdo(drv, self); 180142408Swpaul 181186507Sweongyo /* Figure out exactly which device we matched. */ 182186507Sweongyo 183186507Sweongyo t = db->windrv_devlist; 184186507Sweongyo 185186507Sweongyo while (t->ndis_name != NULL) { 186189488Sweongyo if ((uaa->info.idVendor == t->ndis_vid) && 187189488Sweongyo (uaa->info.idProduct == t->ndis_did)) { 188186507Sweongyo sc->ndis_devidx = devidx; 189186507Sweongyo break; 190186507Sweongyo } 191186507Sweongyo t++; 192186507Sweongyo devidx++; 193186507Sweongyo } 194186507Sweongyo 195142399Swpaul if (ndis_attach(self) != 0) 196170612Simp return ENXIO; 197142399Swpaul 198170612Simp return 0; 199142399Swpaul} 200142399Swpaul 201186507Sweongyostatic int 202186507Sweongyondisusb_detach(device_t self) 203186507Sweongyo{ 204186507Sweongyo int i; 205186507Sweongyo struct ndis_softc *sc = device_get_softc(self); 206189488Sweongyo struct ndisusb_ep *ne;; 207186507Sweongyo 208186507Sweongyo sc->ndisusb_status |= NDISUSB_STATUS_DETACH; 209186507Sweongyo 210186507Sweongyo for (i = 0; i < NDISUSB_ENDPT_MAX; i++) { 211189488Sweongyo ne = &sc->ndisusb_ep[i]; 212189488Sweongyo usb2_transfer_unsetup(ne->ne_xfer, 1); 213186507Sweongyo } 214186507Sweongyo 215186507Sweongyo ndis_pnpevent_nic(self, NDIS_PNP_EVENT_SURPRISE_REMOVED); 216186507Sweongyo 217186507Sweongyo return ndis_detach(self); 218186507Sweongyo} 219186507Sweongyo 220142399Swpaulstatic struct resource_list * 221170934Simpndis_get_resource_list(device_t dev, device_t child) 222142399Swpaul{ 223142399Swpaul struct ndis_softc *sc; 224142399Swpaul 225142399Swpaul sc = device_get_softc(dev); 226142399Swpaul return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); 227142399Swpaul} 228