3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
32 * $FreeBSD: head/sys/dev/if_ndis/if_ndis_usb.c 257176 2013-10-26 17:58:36Z glebius $
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/sockio.h>
38 #include <sys/module.h>
39 #include <sys/malloc.h>
40 #include <sys/kernel.h>
41 #include <sys/socket.h>
42 #include <sys/sysctl.h>
45 #include <net/if_var.h>
46 #include <net/if_arp.h>
47 #include <net/ethernet.h>
48 #include <net/if_dl.h>
49 #include <net/if_media.h>
54 #if defined(__DragonFly__)
55 #include <bus/u4b/usb.h>
56 #include <bus/u4b/usbdi.h>
58 #include <machine/bus.h>
59 #include <dev/usb/usb.h>
60 #include <dev/usb/usbdi.h>
63 #if defined(__DragonFly__)
64 #include <netproto/802_11/ieee80211_var.h>
66 #include <net80211/ieee80211_var.h>
69 #if defined(__DragonFly__)
70 #include <emulation/ndis/pe_var.h>
71 #include <emulation/ndis/cfg_var.h>
72 #include <emulation/ndis/resource_var.h>
73 #include <emulation/ndis/ntoskrnl_var.h>
74 #include <emulation/ndis/ndis_var.h>
75 #include <emulation/ndis/u4bd_var.h>
76 #include <dev/netif/ndis/if_ndisvar.h>
78 #include <compat/ndis/pe_var.h>
79 #include <compat/ndis/cfg_var.h>
80 #include <compat/ndis/resource_var.h>
81 #include <compat/ndis/ntoskrnl_var.h>
82 #include <compat/ndis/ndis_var.h>
83 #include <compat/ndis/usbd_var.h>
84 #include <dev/if_ndis/if_ndisvar.h>
87 SYSCTL_NODE(_hw
, OID_AUTO
, ndisusb
, CTLFLAG_RD
, 0, "NDIS USB driver parameters");
89 MODULE_DEPEND(ndis
, usb
, 1, 1, 1);
91 static device_probe_t ndisusb_match
;
92 static device_attach_t ndisusb_attach
;
93 static device_detach_t ndisusb_detach
;
94 static bus_get_resource_list_t ndis_get_resource_list
;
96 extern int ndisdrv_modevent (module_t
, int, void *);
97 extern int ndis_attach (device_t
);
98 extern int ndis_shutdown (device_t
);
99 extern int ndis_detach (device_t
);
100 extern int ndis_suspend (device_t
);
101 extern int ndis_resume (device_t
);
103 extern unsigned char drv_data
[];
105 static device_method_t ndis_methods
[] = {
106 /* Device interface */
107 DEVMETHOD(device_probe
, ndisusb_match
),
108 DEVMETHOD(device_attach
, ndisusb_attach
),
109 DEVMETHOD(device_detach
, ndisusb_detach
),
110 DEVMETHOD(device_shutdown
, ndis_shutdown
),
113 DEVMETHOD(bus_get_resource_list
, ndis_get_resource_list
),
118 static driver_t ndis_driver
= {
121 sizeof(struct ndis_softc
)
124 static devclass_t ndis_devclass
;
126 DRIVER_MODULE(if_ndis
, uhub
, ndis_driver
, ndis_devclass
, ndisdrv_modevent
,
130 ndisusb_devcompare(interface_type bustype
, struct ndis_usb_type
*t
, device_t dev
)
132 struct usb_attach_arg
*uaa
;
134 if (bustype
!= PNPBus
)
137 uaa
= device_get_ivars(dev
);
139 while (t
->ndis_name
!= NULL
) {
140 if ((uaa
->info
.idVendor
== t
->ndis_vid
) &&
141 (uaa
->info
.idProduct
== t
->ndis_did
)) {
142 device_set_desc(dev
, t
->ndis_name
);
152 ndisusb_match(device_t self
)
154 struct drvdb_ent
*db
;
155 struct usb_attach_arg
*uaa
= device_get_ivars(self
);
157 if (uaa
->usb_mode
!= USB_MODE_HOST
)
159 if (uaa
->info
.bConfigIndex
!= NDISUSB_CONFIG_NO
)
161 if (uaa
->info
.bIfaceIndex
!= NDISUSB_IFACE_INDEX
)
164 if (windrv_lookup(0, "USB Bus") == NULL
)
167 db
= windrv_match((matchfuncptr
)ndisusb_devcompare
, self
);
170 uaa
->driver_ivar
= db
;
176 ndisusb_attach(device_t self
)
178 const struct drvdb_ent
*db
;
179 struct ndisusb_softc
*dummy
= device_get_softc(self
);
180 struct usb_attach_arg
*uaa
= device_get_ivars(self
);
181 struct ndis_softc
*sc
;
182 struct ndis_usb_type
*t
;
186 device_set_usb_desc(self
);
187 db
= uaa
->driver_ivar
;
188 sc
= (struct ndis_softc
*)dummy
;
190 #if defined(__DragonFly__)
191 lockinit(&sc
->ndisusb_lock
, "NDIS USB", 0, LK_CANRECURSE
);
193 mtx_init(&sc
->ndisusb_mtx
, "NDIS USB", MTX_NETWORK_LOCK
, MTX_DEF
);
195 sc
->ndis_dobj
= db
->windrv_object
;
196 sc
->ndis_regvals
= db
->windrv_regvals
;
197 sc
->ndis_iftype
= PNPBus
;
198 sc
->ndisusb_dev
= uaa
->device
;
200 /* Create PDO for this device instance */
202 drv
= windrv_lookup(0, "USB Bus");
203 windrv_create_pdo(drv
, self
);
205 /* Figure out exactly which device we matched. */
207 t
= db
->windrv_devlist
;
209 while (t
->ndis_name
!= NULL
) {
210 if ((uaa
->info
.idVendor
== t
->ndis_vid
) &&
211 (uaa
->info
.idProduct
== t
->ndis_did
)) {
212 sc
->ndis_devidx
= devidx
;
219 if (ndis_attach(self
) != 0)
226 ndisusb_detach(device_t self
)
229 struct ndis_softc
*sc
= device_get_softc(self
);
230 struct ndisusb_ep
*ne
;
232 sc
->ndisusb_status
|= NDISUSB_STATUS_DETACH
;
234 ndis_pnpevent_nic(self
, NDIS_PNP_EVENT_SURPRISE_REMOVED
);
236 if (sc
->ndisusb_status
& NDISUSB_STATUS_SETUP_EP
) {
237 usbd_transfer_unsetup(sc
->ndisusb_dread_ep
.ne_xfer
, 1);
238 usbd_transfer_unsetup(sc
->ndisusb_dwrite_ep
.ne_xfer
, 1);
240 for (i
= 0; i
< NDISUSB_ENDPT_MAX
; i
++) {
241 ne
= &sc
->ndisusb_ep
[i
];
242 usbd_transfer_unsetup(ne
->ne_xfer
, 1);
245 (void)ndis_detach(self
);
247 #if defined(__DragonFly__)
248 lockuninit(&sc
->ndisusb_lock
);
250 mtx_destroy(&sc
->ndisusb_mtx
);
255 static struct resource_list
*
256 ndis_get_resource_list(device_t dev
, device_t child
)
258 struct ndis_softc
*sc
;
260 sc
= device_get_softc(dev
);
261 return (BUS_GET_RESOURCE_LIST(device_get_parent(sc
->ndis_dev
), dev
));