if_ndis_usb.c revision 189719
1184989Srafan/*- 266963Speter * Copyright (c) 2005 3176187Srafan * Bill Paul <wpaul@windriver.com>. All rights reserved. 466963Speter * 566963Speter * Redistribution and use in source and binary forms, with or without 666963Speter * modification, are permitted provided that the following conditions 766963Speter * are met: 866963Speter * 1. Redistributions of source code must retain the above copyright 966963Speter * notice, this list of conditions and the following disclaimer. 1066963Speter * 2. Redistributions in binary form must reproduce the above copyright 1166963Speter * notice, this list of conditions and the following disclaimer in the 1266963Speter * documentation and/or other materials provided with the distribution. 1366963Speter * 3. All advertising materials mentioning features or use of this software 1466963Speter * must display the following acknowledgement: 1566963Speter * This product includes software developed by Bill Paul. 1666963Speter * 4. Neither the name of the author nor the names of any co-contributors 1766963Speter * may be used to endorse or promote products derived from this software 1866963Speter * without specific prior written permission. 1966963Speter * 2066963Speter * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2166963Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2266963Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2366963Speter * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 2466963Speter * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2566963Speter * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2666963Speter * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2766963Speter * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2866963Speter * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2966963Speter * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3066963Speter * THE POSSIBILITY OF SUCH DAMAGE. 3166963Speter */ 3266963Speter 3366963Speter#include <sys/cdefs.h> 3466963Speter__FBSDID("$FreeBSD: head/sys/dev/if_ndis/if_ndis_usb.c 189719 2009-03-12 02:51:55Z weongyo $"); 3566963Speter 3666963Speter#include <sys/param.h> 3766963Speter#include <sys/systm.h> 3897049Speter#include <sys/sockio.h> 3997049Speter#include <sys/module.h> 4066963Speter#include <sys/malloc.h> 4166963Speter#include <sys/kernel.h> 4266963Speter#include <sys/socket.h> 4366963Speter#include <sys/sysctl.h> 4466963Speter 4566963Speter#include <net/if.h> 46166124Srafan#include <net/if_arp.h> 47166124Srafan#include <net/ethernet.h> 4866963Speter#include <net/if_dl.h> 49176187Srafan#include <net/if_media.h> 50176187Srafan 5166963Speter#include <net/bpf.h> 5266963Speter 5366963Speter#include <sys/bus.h> 54166124Srafan#include <machine/bus.h> 5566963Speter#include <dev/usb/usb.h> 56166124Srafan#include <dev/usb/usb_core.h> 57166124Srafan 5866963Speter#include <net80211/ieee80211_var.h> 5966963Speter 6066963Speter#include <compat/ndis/pe_var.h> 61166124Srafan#include <compat/ndis/cfg_var.h> 6297049Speter#include <compat/ndis/resource_var.h> 63184989Srafan#include <compat/ndis/ntoskrnl_var.h> 64176187Srafan#include <compat/ndis/ndis_var.h> 6566963Speter#include <compat/ndis/usbd_var.h> 6666963Speter#include <dev/if_ndis/if_ndisvar.h> 67166124Srafan 68166124SrafanSYSCTL_NODE(_hw, OID_AUTO, ndisusb, CTLFLAG_RD, 0, "NDIS USB driver parameters"); 6966963Speter 7066963SpeterMODULE_DEPEND(ndis, usb, 1, 1, 1); 7166963Speter 72174993Srafanstatic device_probe_t ndisusb_match; 7366963Speterstatic device_attach_t ndisusb_attach; 7466963Speterstatic device_detach_t ndisusb_detach; 75166124Srafanstatic bus_get_resource_list_t ndis_get_resource_list; 76166124Srafan 7766963Speterextern int ndisdrv_modevent (module_t, int, void *); 7866963Speterextern int ndis_attach (device_t); 7966963Speterextern int ndis_shutdown (device_t); 8066963Speterextern int ndis_detach (device_t); 8166963Speterextern int ndis_suspend (device_t); 82166124Srafanextern int ndis_resume (device_t); 8366963Speter 8466963Speterextern unsigned char drv_data[]; 8566963Speter 8666963Speterstatic device_method_t ndis_methods[] = { 8766963Speter /* Device interface */ 88166124Srafan DEVMETHOD(device_probe, ndisusb_match), 89166124Srafan DEVMETHOD(device_attach, ndisusb_attach), 90166124Srafan DEVMETHOD(device_detach, ndisusb_detach), 91184989Srafan DEVMETHOD(device_shutdown, ndis_shutdown), 92184989Srafan 93166124Srafan /* bus interface */ 9466963Speter DEVMETHOD(bus_print_child, bus_generic_print_child), 9566963Speter DEVMETHOD(bus_driver_added, bus_generic_driver_added), 96166124Srafan DEVMETHOD(bus_get_resource_list, ndis_get_resource_list), 97166124Srafan 9866963Speter { 0, 0 } 9966963Speter}; 10066963Speter 10166963Speterstatic driver_t ndis_driver = { 10266963Speter "ndis", 103166124Srafan ndis_methods, 104166124Srafan sizeof(struct ndis_softc) 105166124Srafan}; 10666963Speter 10766963Speterstatic devclass_t ndis_devclass; 10866963Speter 10966963SpeterDRIVER_MODULE(ndis, uhub, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); 11066963Speter 111166124Srafanstatic int 112166124Srafanndisusb_devcompare(interface_type bustype, struct ndis_usb_type *t, device_t dev) 11366963Speter{ 11466963Speter struct usb2_attach_arg *uaa; 11566963Speter 116166124Srafan if (bustype != PNPBus) 11766963Speter return (FALSE); 11866963Speter 11966963Speter uaa = device_get_ivars(dev); 12066963Speter 121166124Srafan while (t->ndis_name != NULL) { 122166124Srafan if ((uaa->info.idVendor == t->ndis_vid) && 12366963Speter (uaa->info.idProduct == t->ndis_did)) { 12466963Speter device_set_desc(dev, t->ndis_name); 12566963Speter return (TRUE); 12666963Speter } 12766963Speter t++; 12866963Speter } 12966963Speter 13066963Speter return (FALSE); 13166963Speter} 13266963Speter 13366963Speterstatic int 13466963Speterndisusb_match(device_t self) 13566963Speter{ 13666963Speter struct drvdb_ent *db; 13766963Speter struct usb2_attach_arg *uaa = device_get_ivars(self); 138166124Srafan 13966963Speter if (uaa->usb2_mode != USB_MODE_HOST) 14066963Speter return (ENXIO); 141166124Srafan if (uaa->info.bConfigIndex != NDISUSB_CONFIG_NO) 142166124Srafan return (ENXIO); 143166124Srafan if (uaa->info.bIfaceIndex != NDISUSB_IFACE_INDEX) 144166124Srafan return (ENXIO); 145166124Srafan 14666963Speter if (windrv_lookup(0, "USB Bus") == NULL) 14766963Speter return (ENXIO); 148166124Srafan 14966963Speter db = windrv_match((matchfuncptr)ndisusb_devcompare, self); 15097049Speter if (db == NULL) 15166963Speter return (ENXIO); 15266963Speter uaa->driver_info = db; 15366963Speter 15466963Speter return (0); 15566963Speter} 15666963Speter 15766963Speterstatic int 158184989Srafanndisusb_attach(device_t self) 159184989Srafan{ 160166124Srafan const struct drvdb_ent *db; 161166124Srafan struct ndisusb_softc *dummy = device_get_softc(self); 162166124Srafan struct usb2_attach_arg *uaa = device_get_ivars(self); 163166124Srafan struct ndis_softc *sc; 16466963Speter struct ndis_usb_type *t; 16566963Speter driver_object *drv; 16697049Speter int devidx = 0; 16766963Speter 168174993Srafan db = uaa->driver_info; 16966963Speter sc = (struct ndis_softc *)dummy; 170166124Srafan sc->ndis_dev = self; 17166963Speter mtx_init(&sc->ndisusb_mtx, "NDIS USB", MTX_NETWORK_LOCK, MTX_DEF); 17266963Speter sc->ndis_dobj = db->windrv_object; 17397049Speter sc->ndis_regvals = db->windrv_regvals; 17466963Speter sc->ndis_iftype = PNPBus; 17566963Speter sc->ndisusb_dev = uaa->device; 17666963Speter 17766963Speter /* Create PDO for this device instance */ 17866963Speter 17966963Speter drv = windrv_lookup(0, "USB Bus"); 18066963Speter windrv_create_pdo(drv, self); 18166963Speter 18266963Speter /* Figure out exactly which device we matched. */ 18366963Speter 18497049Speter t = db->windrv_devlist; 18597049Speter 18666963Speter while (t->ndis_name != NULL) { 18766963Speter if ((uaa->info.idVendor == t->ndis_vid) && 18866963Speter (uaa->info.idProduct == t->ndis_did)) { 18966963Speter sc->ndis_devidx = devidx; 19066963Speter break; 19166963Speter } 192166124Srafan t++; 19366963Speter devidx++; 194166124Srafan } 19566963Speter 19666963Speter if (ndis_attach(self) != 0) 19766963Speter return ENXIO; 19866963Speter 199174993Srafan return 0; 20066963Speter} 20166963Speter 20266963Speterstatic int 20366963Speterndisusb_detach(device_t self) 204166124Srafan{ 20597049Speter int i; 206184989Srafan struct ndis_softc *sc = device_get_softc(self); 20766963Speter struct ndisusb_ep *ne;; 20866963Speter 209 sc->ndisusb_status |= NDISUSB_STATUS_DETACH; 210 211 ndis_pnpevent_nic(self, NDIS_PNP_EVENT_SURPRISE_REMOVED); 212 213 for (i = 0; i < NDISUSB_ENDPT_MAX; i++) { 214 ne = &sc->ndisusb_ep[i]; 215 usb2_transfer_unsetup(ne->ne_xfer, 1); 216 } 217 218 (void)ndis_detach(self); 219 220 mtx_destroy(&sc->ndisusb_mtx); 221 return (0); 222} 223 224static struct resource_list * 225ndis_get_resource_list(device_t dev, device_t child) 226{ 227 struct ndis_softc *sc; 228 229 sc = device_get_softc(dev); 230 return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); 231} 232