if_ndis_usb.c revision 227843
11558Srgrimes/*- 21558Srgrimes * Copyright (c) 2005 31558Srgrimes * Bill Paul <wpaul@windriver.com>. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 13128085Sbde * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by Bill Paul. 161558Srgrimes * 4. Neither the name of the author nor the names of any co-contributors 171558Srgrimes * may be used to endorse or promote products derived from this software 181558Srgrimes * without specific prior written permission. 191558Srgrimes * 201558Srgrimes * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 211558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 241558Srgrimes * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 251558Srgrimes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 261558Srgrimes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 271558Srgrimes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 281558Srgrimes * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 291558Srgrimes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 301558Srgrimes * THE POSSIBILITY OF SUCH DAMAGE. 3136997Scharnier */ 3223672Speter 3336997Scharnier#include <sys/cdefs.h> 3436997Scharnier__FBSDID("$FreeBSD: head/sys/dev/if_ndis/if_ndis_usb.c 227843 2011-11-22 21:28:20Z marius $"); 3550476Speter 361558Srgrimes#include <sys/param.h> 371558Srgrimes#include <sys/systm.h> 381558Srgrimes#include <sys/sockio.h> 391558Srgrimes#include <sys/module.h> 401558Srgrimes#include <sys/malloc.h> 411558Srgrimes#include <sys/kernel.h> 421558Srgrimes#include <sys/socket.h> 431558Srgrimes#include <sys/sysctl.h> 441558Srgrimes 451558Srgrimes#include <net/if.h> 4619239Sfenner#include <net/if_arp.h> 4719239Sfenner#include <net/ethernet.h> 4836115Sfenner#include <net/if_dl.h> 491558Srgrimes#include <net/if_media.h> 501558Srgrimes 511558Srgrimes#include <net/bpf.h> 521558Srgrimes 531558Srgrimes#include <sys/bus.h> 541558Srgrimes#include <machine/bus.h> 551558Srgrimes#include <dev/usb/usb.h> 56103949Smike#include <dev/usb/usbdi.h> 5759216Simp 581558Srgrimes#include <net80211/ieee80211_var.h> 591558Srgrimes 601558Srgrimes#include <compat/ndis/pe_var.h> 611558Srgrimes#include <compat/ndis/cfg_var.h> 621558Srgrimes#include <compat/ndis/resource_var.h> 631558Srgrimes#include <compat/ndis/ntoskrnl_var.h> 641558Srgrimes#include <compat/ndis/ndis_var.h> 651558Srgrimes#include <compat/ndis/usbd_var.h> 661558Srgrimes#include <dev/if_ndis/if_ndisvar.h> 671558Srgrimes 681558SrgrimesSYSCTL_NODE(_hw, OID_AUTO, ndisusb, CTLFLAG_RD, 0, "NDIS USB driver parameters"); 691558Srgrimes 701558SrgrimesMODULE_DEPEND(ndis, usb, 1, 1, 1); 711558Srgrimes 7292837Simpstatic device_probe_t ndisusb_match; 7392837Simpstatic device_attach_t ndisusb_attach; 7492837Simpstatic device_detach_t ndisusb_detach; 7592837Simpstatic bus_get_resource_list_t ndis_get_resource_list; 7692837Simp 7792837Simpextern int ndisdrv_modevent (module_t, int, void *); 7892837Simpextern int ndis_attach (device_t); 791558Srgrimesextern int ndis_shutdown (device_t); 8019300Sfennerextern int ndis_detach (device_t); 811558Srgrimesextern int ndis_suspend (device_t); 821558Srgrimesextern int ndis_resume (device_t); 831558Srgrimes 8492837Simpextern unsigned char drv_data[]; 851558Srgrimes 861558Srgrimesstatic device_method_t ndis_methods[] = { 8792837Simp /* Device interface */ 8892837Simp DEVMETHOD(device_probe, ndisusb_match), 8992837Simp DEVMETHOD(device_attach, ndisusb_attach), 901558Srgrimes DEVMETHOD(device_detach, ndisusb_detach), 911558Srgrimes DEVMETHOD(device_shutdown, ndis_shutdown), 921558Srgrimes 931558Srgrimes /* bus interface */ 941558Srgrimes DEVMETHOD(bus_get_resource_list, ndis_get_resource_list), 951558Srgrimes 961558Srgrimes DEVMETHOD_END 971558Srgrimes}; 9892837Simp 991558Srgrimesstatic driver_t ndis_driver = { 10019300Sfenner "ndis", 10119300Sfenner ndis_methods, 10219300Sfenner sizeof(struct ndis_softc) 10319300Sfenner}; 1041558Srgrimes 10519300Sfennerstatic devclass_t ndis_devclass; 10619300Sfenner 10719300SfennerDRIVER_MODULE(ndis, uhub, ndis_driver, ndis_devclass, ndisdrv_modevent, 0); 10819300Sfenner 10919300Sfennerstatic int 11019300Sfennerndisusb_devcompare(interface_type bustype, struct ndis_usb_type *t, device_t dev) 11119300Sfenner{ 11219300Sfenner struct usb_attach_arg *uaa; 11319300Sfenner 11419300Sfenner if (bustype != PNPBus) 11519300Sfenner return (FALSE); 11619300Sfenner 11719300Sfenner uaa = device_get_ivars(dev); 11819300Sfenner 11919300Sfenner while (t->ndis_name != NULL) { 12019300Sfenner if ((uaa->info.idVendor == t->ndis_vid) && 12119300Sfenner (uaa->info.idProduct == t->ndis_did)) { 1221558Srgrimes device_set_desc(dev, t->ndis_name); 1231558Srgrimes return (TRUE); 1241558Srgrimes } 12592837Simp t++; 1261558Srgrimes } 12786473Siedowse 12886473Siedowse return (FALSE); 1291558Srgrimes} 1301558Srgrimes 1311558Srgrimesstatic int 1321558Srgrimesndisusb_match(device_t self) 13319239Sfenner{ 13436115Sfenner struct drvdb_ent *db; 1351558Srgrimes struct usb_attach_arg *uaa = device_get_ivars(self); 1361558Srgrimes 137114452Smarkm if (uaa->usb_mode != USB_MODE_HOST) 1381558Srgrimes return (ENXIO); 139114452Smarkm if (uaa->info.bConfigIndex != NDISUSB_CONFIG_NO) 14037635Sjkoshy return (ENXIO); 1411558Srgrimes if (uaa->info.bIfaceIndex != NDISUSB_IFACE_INDEX) 1421558Srgrimes return (ENXIO); 1431558Srgrimes 14419300Sfenner if (windrv_lookup(0, "USB Bus") == NULL) 14537635Sjkoshy return (ENXIO); 1461558Srgrimes 1471558Srgrimes db = windrv_match((matchfuncptr)ndisusb_devcompare, self); 14823672Speter if (db == NULL) 1491558Srgrimes return (ENXIO); 1501558Srgrimes uaa->driver_ivar = db; 1511558Srgrimes 15237635Sjkoshy return (0); 1531558Srgrimes} 1541558Srgrimes 1551558Srgrimesstatic int 15612377Sjoergndisusb_attach(device_t self) 15712377Sjoerg{ 158122669Sjohan const struct drvdb_ent *db; 159114452Smarkm struct ndisusb_softc *dummy = device_get_softc(self); 160114452Smarkm struct usb_attach_arg *uaa = device_get_ivars(self); 16119300Sfenner struct ndis_softc *sc; 16219300Sfenner struct ndis_usb_type *t; 16319239Sfenner driver_object *drv; 16419300Sfenner int devidx = 0; 16519317Sfenner 1661558Srgrimes device_set_usb_desc(self); 1671558Srgrimes db = uaa->driver_ivar; 1681558Srgrimes sc = (struct ndis_softc *)dummy; 1691558Srgrimes sc->ndis_dev = self; 1701558Srgrimes mtx_init(&sc->ndisusb_mtx, "NDIS USB", MTX_NETWORK_LOCK, MTX_DEF); 1711558Srgrimes sc->ndis_dobj = db->windrv_object; 1721558Srgrimes sc->ndis_regvals = db->windrv_regvals; 1731558Srgrimes sc->ndis_iftype = PNPBus; 1741558Srgrimes sc->ndisusb_dev = uaa->device; 17519239Sfenner 17619239Sfenner /* Create PDO for this device instance */ 17719239Sfenner 17819239Sfenner drv = windrv_lookup(0, "USB Bus"); 17936115Sfenner windrv_create_pdo(drv, self); 1801558Srgrimes 1811558Srgrimes /* Figure out exactly which device we matched. */ 1821558Srgrimes 1831558Srgrimes t = db->windrv_devlist; 1841558Srgrimes 18592837Simp while (t->ndis_name != NULL) { 1861558Srgrimes if ((uaa->info.idVendor == t->ndis_vid) && 18792837Simp (uaa->info.idProduct == t->ndis_did)) { 18886473Siedowse sc->ndis_devidx = devidx; 1891558Srgrimes break; 1901558Srgrimes } 1911558Srgrimes t++; 1921558Srgrimes devidx++; 19319300Sfenner } 1941558Srgrimes 1951558Srgrimes if (ndis_attach(self) != 0) 1961558Srgrimes return (ENXIO); 1971558Srgrimes 1981558Srgrimes return (0); 1991558Srgrimes} 2001558Srgrimes 20192837Simpstatic int 2021558Srgrimesndisusb_detach(device_t self) 2031558Srgrimes{ 2041558Srgrimes int i; 20521409Simp struct ndis_softc *sc = device_get_softc(self); 2061558Srgrimes struct ndisusb_ep *ne; 2071558Srgrimes 2081558Srgrimes sc->ndisusb_status |= NDISUSB_STATUS_DETACH; 2091558Srgrimes 2101558Srgrimes ndis_pnpevent_nic(self, NDIS_PNP_EVENT_SURPRISE_REMOVED); 21192837Simp 2121558Srgrimes if (sc->ndisusb_status & NDISUSB_STATUS_SETUP_EP) { 2131558Srgrimes usbd_transfer_unsetup(sc->ndisusb_dread_ep.ne_xfer, 1); 2141558Srgrimes usbd_transfer_unsetup(sc->ndisusb_dwrite_ep.ne_xfer, 1); 2151558Srgrimes } 2161558Srgrimes for (i = 0; i < NDISUSB_ENDPT_MAX; i++) { 2171558Srgrimes ne = &sc->ndisusb_ep[i]; 2181558Srgrimes usbd_transfer_unsetup(ne->ne_xfer, 1); 2191558Srgrimes } 2201558Srgrimes 22192837Simp (void)ndis_detach(self); 2221558Srgrimes 2231558Srgrimes mtx_destroy(&sc->ndisusb_mtx); 2241558Srgrimes return (0); 2251558Srgrimes} 22621409Simp 2271558Srgrimesstatic struct resource_list * 22839256Sgibbsndis_get_resource_list(device_t dev, device_t child) 22939256Sgibbs{ 23039256Sgibbs struct ndis_softc *sc; 2311558Srgrimes 2321558Srgrimes sc = device_get_softc(dev); 23339256Sgibbs return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); 23492837Simp} 2351558Srgrimes