consistent softc member name prefixdiff -r1.48.4.11 -r1.48.4.12 src/sys/dev/usb/if_url.c
(skrll)
--- src/sys/dev/usb/if_url.c 2016/12/05 10:55:18 1.48.4.11
+++ src/sys/dev/usb/if_url.c 2017/01/26 12:40:16 1.48.4.12
@@ -1,1323 +1,1319 @@ | @@ -1,1323 +1,1319 @@ | |||
1 | /* $NetBSD: if_url.c,v 1.48.4.11 2016/12/05 10:55:18 skrll Exp $ */ | 1 | /* $NetBSD: if_url.c,v 1.48.4.12 2017/01/26 12:40:16 skrll Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2001, 2002 | 4 | * Copyright (c) 2001, 2002 | |
5 | * Shingo WATANABE <nabe@nabechan.org>. All rights reserved. | 5 | * Shingo WATANABE <nabe@nabechan.org>. All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
15 | * 3. Neither the name of the author nor the names of any co-contributors | 15 | * 3. Neither the name of the author nor the names of any co-contributors | |
16 | * may be used to endorse or promote products derived from this software | 16 | * may be used to endorse or promote products derived from this software | |
17 | * without specific prior written permission. | 17 | * without specific prior written permission. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | 19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
29 | * SUCH DAMAGE. | 29 | * SUCH DAMAGE. | |
30 | * | 30 | * | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | /* | 33 | /* | |
34 | * The RTL8150L(Realtek USB to fast ethernet controller) spec can be found at | 34 | * The RTL8150L(Realtek USB to fast ethernet controller) spec can be found at | |
35 | * ftp://ftp.realtek.com.tw/lancard/data_sheet/8150/8150v14.pdf | 35 | * ftp://ftp.realtek.com.tw/lancard/data_sheet/8150/8150v14.pdf | |
36 | * ftp://152.104.125.40/lancard/data_sheet/8150/8150v14.pdf | 36 | * ftp://152.104.125.40/lancard/data_sheet/8150/8150v14.pdf | |
37 | */ | 37 | */ | |
38 | 38 | |||
39 | /* | 39 | /* | |
40 | * TODO: | 40 | * TODO: | |
41 | * Interrupt Endpoint support | 41 | * Interrupt Endpoint support | |
42 | * External PHYs | 42 | * External PHYs | |
43 | * powerhook() support? | 43 | * powerhook() support? | |
44 | */ | 44 | */ | |
45 | 45 | |||
46 | #include <sys/cdefs.h> | 46 | #include <sys/cdefs.h> | |
47 | __KERNEL_RCSID(0, "$NetBSD: if_url.c,v 1.48.4.11 2016/12/05 10:55:18 skrll Exp $"); | 47 | __KERNEL_RCSID(0, "$NetBSD: if_url.c,v 1.48.4.12 2017/01/26 12:40:16 skrll Exp $"); | |
48 | 48 | |||
49 | #ifdef _KERNEL_OPT | 49 | #ifdef _KERNEL_OPT | |
50 | #include "opt_inet.h" | 50 | #include "opt_inet.h" | |
51 | #include "opt_usb.h" | 51 | #include "opt_usb.h" | |
52 | #endif | 52 | #endif | |
53 | 53 | |||
54 | #include <sys/param.h> | 54 | #include <sys/param.h> | |
55 | #include <sys/systm.h> | 55 | #include <sys/systm.h> | |
56 | #include <sys/rwlock.h> | 56 | #include <sys/rwlock.h> | |
57 | #include <sys/mbuf.h> | 57 | #include <sys/mbuf.h> | |
58 | #include <sys/kernel.h> | 58 | #include <sys/kernel.h> | |
59 | #include <sys/socket.h> | 59 | #include <sys/socket.h> | |
60 | 60 | |||
61 | #include <sys/device.h> | 61 | #include <sys/device.h> | |
62 | #include <sys/rndsource.h> | 62 | #include <sys/rndsource.h> | |
63 | 63 | |||
64 | #include <net/if.h> | 64 | #include <net/if.h> | |
65 | #include <net/if_arp.h> | 65 | #include <net/if_arp.h> | |
66 | #include <net/if_dl.h> | 66 | #include <net/if_dl.h> | |
67 | #include <net/if_media.h> | 67 | #include <net/if_media.h> | |
68 | 68 | |||
69 | #include <net/bpf.h> | 69 | #include <net/bpf.h> | |
70 | 70 | |||
71 | #include <net/if_ether.h> | 71 | #include <net/if_ether.h> | |
72 | #ifdef INET | 72 | #ifdef INET | |
73 | #include <netinet/in.h> | 73 | #include <netinet/in.h> | |
74 | #include <netinet/if_inarp.h> | 74 | #include <netinet/if_inarp.h> | |
75 | #endif | 75 | #endif | |
76 | 76 | |||
77 | #include <dev/mii/mii.h> | 77 | #include <dev/mii/mii.h> | |
78 | #include <dev/mii/miivar.h> | 78 | #include <dev/mii/miivar.h> | |
79 | #include <dev/mii/urlphyreg.h> | 79 | #include <dev/mii/urlphyreg.h> | |
80 | 80 | |||
81 | #include <dev/usb/usb.h> | 81 | #include <dev/usb/usb.h> | |
82 | #include <dev/usb/usbdi.h> | 82 | #include <dev/usb/usbdi.h> | |
83 | #include <dev/usb/usbdi_util.h> | 83 | #include <dev/usb/usbdi_util.h> | |
84 | #include <dev/usb/usbdevs.h> | 84 | #include <dev/usb/usbdevs.h> | |
85 | 85 | |||
86 | #include <dev/usb/if_urlreg.h> | 86 | #include <dev/usb/if_urlreg.h> | |
87 | 87 | |||
88 | 88 | |||
89 | /* Function declarations */ | 89 | /* Function declarations */ | |
90 | int url_match(device_t, cfdata_t, void *); | 90 | int url_match(device_t, cfdata_t, void *); | |
91 | void url_attach(device_t, device_t, void *); | 91 | void url_attach(device_t, device_t, void *); | |
92 | int url_detach(device_t, int); | 92 | int url_detach(device_t, int); | |
93 | int url_activate(device_t, enum devact); | 93 | int url_activate(device_t, enum devact); | |
94 | extern struct cfdriver url_cd; | 94 | extern struct cfdriver url_cd; | |
95 | CFATTACH_DECL_NEW(url, sizeof(struct url_softc), url_match, url_attach, | 95 | CFATTACH_DECL_NEW(url, sizeof(struct url_softc), url_match, url_attach, | |
96 | url_detach, url_activate); | 96 | url_detach, url_activate); | |
97 | 97 | |||
98 | Static int url_openpipes(struct url_softc *); | 98 | Static int url_openpipes(struct url_softc *); | |
99 | Static int url_rx_list_init(struct url_softc *); | 99 | Static int url_rx_list_init(struct url_softc *); | |
100 | Static int url_tx_list_init(struct url_softc *); | 100 | Static int url_tx_list_init(struct url_softc *); | |
101 | Static int url_newbuf(struct url_softc *, struct url_chain *, struct mbuf *); | 101 | Static int url_newbuf(struct url_softc *, struct url_chain *, struct mbuf *); | |
102 | Static void url_start(struct ifnet *); | 102 | Static void url_start(struct ifnet *); | |
103 | Static int url_send(struct url_softc *, struct mbuf *, int); | 103 | Static int url_send(struct url_softc *, struct mbuf *, int); | |
104 | Static void url_txeof(struct usbd_xfer *, void *, usbd_status); | 104 | Static void url_txeof(struct usbd_xfer *, void *, usbd_status); | |
105 | Static void url_rxeof(struct usbd_xfer *, void *, usbd_status); | 105 | Static void url_rxeof(struct usbd_xfer *, void *, usbd_status); | |
106 | Static void url_tick(void *); | 106 | Static void url_tick(void *); | |
107 | Static void url_tick_task(void *); | 107 | Static void url_tick_task(void *); | |
108 | Static int url_ioctl(struct ifnet *, u_long, void *); | 108 | Static int url_ioctl(struct ifnet *, u_long, void *); | |
109 | Static void url_stop_task(struct url_softc *); | 109 | Static void url_stop_task(struct url_softc *); | |
110 | Static void url_stop(struct ifnet *, int); | 110 | Static void url_stop(struct ifnet *, int); | |
111 | Static void url_watchdog(struct ifnet *); | 111 | Static void url_watchdog(struct ifnet *); | |
112 | Static int url_ifmedia_change(struct ifnet *); | 112 | Static int url_ifmedia_change(struct ifnet *); | |
113 | Static void url_ifmedia_status(struct ifnet *, struct ifmediareq *); | 113 | Static void url_ifmedia_status(struct ifnet *, struct ifmediareq *); | |
114 | Static void url_lock_mii(struct url_softc *); | 114 | Static void url_lock_mii(struct url_softc *); | |
115 | Static void url_unlock_mii(struct url_softc *); | 115 | Static void url_unlock_mii(struct url_softc *); | |
116 | Static int url_int_miibus_readreg(device_t, int, int); | 116 | Static int url_int_miibus_readreg(device_t, int, int); | |
117 | Static void url_int_miibus_writereg(device_t, int, int, int); | 117 | Static void url_int_miibus_writereg(device_t, int, int, int); | |
118 | Static void url_miibus_statchg(struct ifnet *); | 118 | Static void url_miibus_statchg(struct ifnet *); | |
119 | Static int url_init(struct ifnet *); | 119 | Static int url_init(struct ifnet *); | |
120 | Static void url_setmulti(struct url_softc *); | 120 | Static void url_setmulti(struct url_softc *); | |
121 | Static void url_reset(struct url_softc *); | 121 | Static void url_reset(struct url_softc *); | |
122 | 122 | |||
123 | Static int url_csr_read_1(struct url_softc *, int); | 123 | Static int url_csr_read_1(struct url_softc *, int); | |
124 | Static int url_csr_read_2(struct url_softc *, int); | 124 | Static int url_csr_read_2(struct url_softc *, int); | |
125 | Static int url_csr_write_1(struct url_softc *, int, int); | 125 | Static int url_csr_write_1(struct url_softc *, int, int); | |
126 | Static int url_csr_write_2(struct url_softc *, int, int); | 126 | Static int url_csr_write_2(struct url_softc *, int, int); | |
127 | Static int url_csr_write_4(struct url_softc *, int, int); | 127 | Static int url_csr_write_4(struct url_softc *, int, int); | |
128 | Static int url_mem(struct url_softc *, int, int, void *, int); | 128 | Static int url_mem(struct url_softc *, int, int, void *, int); | |
129 | 129 | |||
130 | /* Macros */ | 130 | /* Macros */ | |
131 | #ifdef URL_DEBUG | 131 | #ifdef URL_DEBUG | |
132 | #define DPRINTF(x) if (urldebug) printf x | 132 | #define DPRINTF(x) if (urldebug) printf x | |
133 | #define DPRINTFN(n,x) if (urldebug >= (n)) printf x | 133 | #define DPRINTFN(n,x) if (urldebug >= (n)) printf x | |
134 | int urldebug = 0; | 134 | int urldebug = 0; | |
135 | #else | 135 | #else | |
136 | #define DPRINTF(x) | 136 | #define DPRINTF(x) | |
137 | #define DPRINTFN(n,x) | 137 | #define DPRINTFN(n,x) | |
138 | #endif | 138 | #endif | |
139 | 139 | |||
140 | #define URL_SETBIT(sc, reg, x) \ | 140 | #define URL_SETBIT(sc, reg, x) \ | |
141 | url_csr_write_1(sc, reg, url_csr_read_1(sc, reg) | (x)) | 141 | url_csr_write_1(sc, reg, url_csr_read_1(sc, reg) | (x)) | |
142 | 142 | |||
143 | #define URL_SETBIT2(sc, reg, x) \ | 143 | #define URL_SETBIT2(sc, reg, x) \ | |
144 | url_csr_write_2(sc, reg, url_csr_read_2(sc, reg) | (x)) | 144 | url_csr_write_2(sc, reg, url_csr_read_2(sc, reg) | (x)) | |
145 | 145 | |||
146 | #define URL_CLRBIT(sc, reg, x) \ | 146 | #define URL_CLRBIT(sc, reg, x) \ | |
147 | url_csr_write_1(sc, reg, url_csr_read_1(sc, reg) & ~(x)) | 147 | url_csr_write_1(sc, reg, url_csr_read_1(sc, reg) & ~(x)) | |
148 | 148 | |||
149 | #define URL_CLRBIT2(sc, reg, x) \ | 149 | #define URL_CLRBIT2(sc, reg, x) \ | |
150 | url_csr_write_2(sc, reg, url_csr_read_2(sc, reg) & ~(x)) | 150 | url_csr_write_2(sc, reg, url_csr_read_2(sc, reg) & ~(x)) | |
151 | 151 | |||
152 | static const struct url_type { | 152 | static const struct url_type { | |
153 | struct usb_devno url_dev; | 153 | struct usb_devno url_dev; | |
154 | uint16_t url_flags; | 154 | uint16_t url_flags; | |
155 | #define URL_EXT_PHY 0x0001 | 155 | #define URL_EXT_PHY 0x0001 | |
156 | } url_devs [] = { | 156 | } url_devs [] = { | |
157 | /* MELCO LUA-KTX */ | 157 | /* MELCO LUA-KTX */ | |
158 | {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAKTX }, 0}, | 158 | {{ USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAKTX }, 0}, | |
159 | /* Realtek RTL8150L Generic (GREEN HOUSE USBKR100) */ | 159 | /* Realtek RTL8150L Generic (GREEN HOUSE USBKR100) */ | |
160 | {{ USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8150L}, 0}, | 160 | {{ USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8150L}, 0}, | |
161 | /* Longshine LCS-8138TX */ | 161 | /* Longshine LCS-8138TX */ | |
162 | {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_LCS8138TX}, 0}, | 162 | {{ USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_LCS8138TX}, 0}, | |
163 | /* Micronet SP128AR */ | 163 | /* Micronet SP128AR */ | |
164 | {{ USB_VENDOR_MICRONET, USB_PRODUCT_MICRONET_SP128AR}, 0}, | 164 | {{ USB_VENDOR_MICRONET, USB_PRODUCT_MICRONET_SP128AR}, 0}, | |
165 | /* OQO model 01 */ | 165 | /* OQO model 01 */ | |
166 | {{ USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01}, 0}, | 166 | {{ USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01}, 0}, | |
167 | }; | 167 | }; | |
168 | #define url_lookup(v, p) ((const struct url_type *)usb_lookup(url_devs, v, p)) | 168 | #define url_lookup(v, p) ((const struct url_type *)usb_lookup(url_devs, v, p)) | |
169 | 169 | |||
170 | 170 | |||
171 | /* Probe */ | 171 | /* Probe */ | |
172 | int | 172 | int | |
173 | url_match(device_t parent, cfdata_t match, void *aux) | 173 | url_match(device_t parent, cfdata_t match, void *aux) | |
174 | { | 174 | { | |
175 | struct usb_attach_arg *uaa = aux; | 175 | struct usb_attach_arg *uaa = aux; | |
176 | 176 | |||
177 | return url_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ? | 177 | return url_lookup(uaa->uaa_vendor, uaa->uaa_product) != NULL ? | |
178 | UMATCH_VENDOR_PRODUCT : UMATCH_NONE; | 178 | UMATCH_VENDOR_PRODUCT : UMATCH_NONE; | |
179 | } | 179 | } | |
180 | /* Attach */ | 180 | /* Attach */ | |
181 | void | 181 | void | |
182 | url_attach(device_t parent, device_t self, void *aux) | 182 | url_attach(device_t parent, device_t self, void *aux) | |
183 | { | 183 | { | |
184 | struct url_softc *sc = device_private(self); | 184 | struct url_softc *sc = device_private(self); | |
185 | struct usb_attach_arg *uaa = aux; | 185 | struct usb_attach_arg *uaa = aux; | |
186 | struct usbd_device *dev = uaa->uaa_device; | 186 | struct usbd_device *dev = uaa->uaa_device; | |
187 | struct usbd_interface *iface; | 187 | struct usbd_interface *iface; | |
188 | usbd_status err; | 188 | usbd_status err; | |
189 | usb_interface_descriptor_t *id; | 189 | usb_interface_descriptor_t *id; | |
190 | usb_endpoint_descriptor_t *ed; | 190 | usb_endpoint_descriptor_t *ed; | |
191 | char *devinfop; | 191 | char *devinfop; | |
192 | struct ifnet *ifp; | 192 | struct ifnet *ifp; | |
193 | struct mii_data *mii; | 193 | struct mii_data *mii; | |
194 | u_char eaddr[ETHER_ADDR_LEN]; | 194 | u_char eaddr[ETHER_ADDR_LEN]; | |
195 | int i, s; | 195 | int i; | |
196 | 196 | |||
197 | sc->sc_dev = self; | 197 | sc->sc_dev = self; | |
198 | 198 | |||
199 | aprint_naive("\n"); | 199 | aprint_naive("\n"); | |
200 | aprint_normal("\n"); | 200 | aprint_normal("\n"); | |
201 | 201 | |||
202 | devinfop = usbd_devinfo_alloc(dev, 0); | 202 | devinfop = usbd_devinfo_alloc(dev, 0); | |
203 | aprint_normal_dev(self, "%s\n", devinfop); | 203 | aprint_normal_dev(self, "%s\n", devinfop); | |
204 | usbd_devinfo_free(devinfop); | 204 | usbd_devinfo_free(devinfop); | |
205 | 205 | |||
206 | /* Move the device into the configured state. */ | 206 | /* Move the device into the configured state. */ | |
207 | err = usbd_set_config_no(dev, URL_CONFIG_NO, 1); | 207 | err = usbd_set_config_no(dev, URL_CONFIG_NO, 1); | |
208 | if (err) { | 208 | if (err) { | |
209 | aprint_error_dev(self, "failed to set configuration" | 209 | aprint_error_dev(self, "failed to set configuration" | |
210 | ", err=%s\n", usbd_errstr(err)); | 210 | ", err=%s\n", usbd_errstr(err)); | |
211 | goto bad; | 211 | goto bad; | |
212 | } | 212 | } | |
213 | 213 | |||
214 | usb_init_task(&sc->sc_tick_task, url_tick_task, sc, 0); | 214 | usb_init_task(&sc->sc_tick_task, url_tick_task, sc, 0); | |
215 | rw_init(&sc->sc_mii_rwlock); | 215 | rw_init(&sc->sc_mii_rwlock); | |
216 | usb_init_task(&sc->sc_stop_task, (void (*)(void *))url_stop_task, sc, 0); | 216 | usb_init_task(&sc->sc_stop_task, (void (*)(void *))url_stop_task, sc, 0); | |
217 | 217 | |||
218 | /* get control interface */ | 218 | /* get control interface */ | |
219 | err = usbd_device2interface_handle(dev, URL_IFACE_INDEX, &iface); | 219 | err = usbd_device2interface_handle(dev, URL_IFACE_INDEX, &iface); | |
220 | if (err) { | 220 | if (err) { | |
221 | aprint_error_dev(self, "failed to get interface, err=%s\n", | 221 | aprint_error_dev(self, "failed to get interface, err=%s\n", | |
222 | usbd_errstr(err)); | 222 | usbd_errstr(err)); | |
223 | goto bad; | 223 | goto bad; | |
224 | } | 224 | } | |
225 | 225 | |||
226 | sc->sc_udev = dev; | 226 | sc->sc_udev = dev; | |
227 | sc->sc_ctl_iface = iface; | 227 | sc->sc_ctl_iface = iface; | |
228 | sc->sc_flags = url_lookup(uaa->uaa_vendor, uaa->uaa_product)->url_flags; | 228 | sc->sc_flags = url_lookup(uaa->uaa_vendor, uaa->uaa_product)->url_flags; | |
229 | 229 | |||
230 | /* get interface descriptor */ | 230 | /* get interface descriptor */ | |
231 | id = usbd_get_interface_descriptor(sc->sc_ctl_iface); | 231 | id = usbd_get_interface_descriptor(sc->sc_ctl_iface); | |
232 | 232 | |||
233 | /* find endpoints */ | 233 | /* find endpoints */ | |
234 | sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1; | 234 | sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1; | |
235 | for (i = 0; i < id->bNumEndpoints; i++) { | 235 | for (i = 0; i < id->bNumEndpoints; i++) { | |
236 | ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i); | 236 | ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i); | |
237 | if (ed == NULL) { | 237 | if (ed == NULL) { | |
238 | aprint_error_dev(self, | 238 | aprint_error_dev(self, | |
239 | "couldn't get endpoint %d\n", i); | 239 | "couldn't get endpoint %d\n", i); | |
240 | goto bad; | 240 | goto bad; | |
241 | } | 241 | } | |
242 | if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && | 242 | if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && | |
243 | UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) | 243 | UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) | |
244 | sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */ | 244 | sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */ | |
245 | else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && | 245 | else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && | |
246 | UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) | 246 | UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) | |
247 | sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */ | 247 | sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */ | |
248 | else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT && | 248 | else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT && | |
249 | UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) | 249 | UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) | |
250 | sc->sc_intrin_no = ed->bEndpointAddress; /* Status */ | 250 | sc->sc_intrin_no = ed->bEndpointAddress; /* Status */ | |
251 | } | 251 | } | |
252 | 252 | |||
253 | if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 || | 253 | if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 || | |
254 | sc->sc_intrin_no == -1) { | 254 | sc->sc_intrin_no == -1) { | |
255 | aprint_error_dev(self, "missing endpoint\n"); | 255 | aprint_error_dev(self, "missing endpoint\n"); | |
256 | goto bad; | 256 | goto bad; | |
257 | } | 257 | } | |
258 | 258 | |||
259 | s = splnet(); | |||
260 | ||||
261 | /* reset the adapter */ | 259 | /* reset the adapter */ | |
262 | url_reset(sc); | 260 | url_reset(sc); | |
263 | 261 | |||
264 | /* Get Ethernet Address */ | 262 | /* Get Ethernet Address */ | |
265 | err = url_mem(sc, URL_CMD_READMEM, URL_IDR0, (void *)eaddr, | 263 | err = url_mem(sc, URL_CMD_READMEM, URL_IDR0, (void *)eaddr, | |
266 | ETHER_ADDR_LEN); | 264 | ETHER_ADDR_LEN); | |
267 | if (err) { | 265 | if (err) { | |
268 | aprint_error_dev(self, "read MAC address failed\n"); | 266 | aprint_error_dev(self, "read MAC address failed\n"); | |
269 | splx(s); | |||
270 | goto bad; | 267 | goto bad; | |
271 | } | 268 | } | |
272 | 269 | |||
273 | /* Print Ethernet Address */ | 270 | /* Print Ethernet Address */ | |
274 | aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(eaddr)); | 271 | aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(eaddr)); | |
275 | 272 | |||
276 | /* initialize interface information */ | 273 | /* initialize interface information */ | |
277 | ifp = GET_IFP(sc); | 274 | ifp = GET_IFP(sc); | |
278 | ifp->if_softc = sc; | 275 | ifp->if_softc = sc; | |
279 | ifp->if_mtu = ETHERMTU; | 276 | ifp->if_mtu = ETHERMTU; | |
280 | strncpy(ifp->if_xname, device_xname(self), IFNAMSIZ); | 277 | strncpy(ifp->if_xname, device_xname(self), IFNAMSIZ); | |
281 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | 278 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | |
282 | ifp->if_start = url_start; | 279 | ifp->if_start = url_start; | |
283 | ifp->if_ioctl = url_ioctl; | 280 | ifp->if_ioctl = url_ioctl; | |
284 | ifp->if_watchdog = url_watchdog; | 281 | ifp->if_watchdog = url_watchdog; | |
285 | ifp->if_init = url_init; | 282 | ifp->if_init = url_init; | |
286 | ifp->if_stop = url_stop; | 283 | ifp->if_stop = url_stop; | |
287 | 284 | |||
288 | IFQ_SET_READY(&ifp->if_snd); | 285 | IFQ_SET_READY(&ifp->if_snd); | |
289 | 286 | |||
290 | /* | 287 | /* | |
291 | * Do ifmedia setup. | 288 | * Do ifmedia setup. | |
292 | */ | 289 | */ | |
293 | mii = &sc->sc_mii; | 290 | mii = &sc->sc_mii; | |
294 | mii->mii_ifp = ifp; | 291 | mii->mii_ifp = ifp; | |
295 | mii->mii_readreg = url_int_miibus_readreg; | 292 | mii->mii_readreg = url_int_miibus_readreg; | |
296 | mii->mii_writereg = url_int_miibus_writereg; | 293 | mii->mii_writereg = url_int_miibus_writereg; | |
297 | #if 0 | 294 | #if 0 | |
298 | if (sc->sc_flags & URL_EXT_PHY) { | 295 | if (sc->sc_flags & URL_EXT_PHY) { | |
299 | mii->mii_readreg = url_ext_miibus_readreg; | 296 | mii->mii_readreg = url_ext_miibus_readreg; | |
300 | mii->mii_writereg = url_ext_miibus_writereg; | 297 | mii->mii_writereg = url_ext_miibus_writereg; | |
301 | } | 298 | } | |
302 | #endif | 299 | #endif | |
303 | mii->mii_statchg = url_miibus_statchg; | 300 | mii->mii_statchg = url_miibus_statchg; | |
304 | mii->mii_flags = MIIF_AUTOTSLEEP; | 301 | mii->mii_flags = MIIF_AUTOTSLEEP; | |
305 | sc->sc_ec.ec_mii = mii; | 302 | sc->sc_ec.ec_mii = mii; | |
306 | ifmedia_init(&mii->mii_media, 0, | 303 | ifmedia_init(&mii->mii_media, 0, | |
307 | url_ifmedia_change, url_ifmedia_status); | 304 | url_ifmedia_change, url_ifmedia_status); | |
308 | mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); | 305 | mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); | |
309 | if (LIST_FIRST(&mii->mii_phys) == NULL) { | 306 | if (LIST_FIRST(&mii->mii_phys) == NULL) { | |
310 | ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); | 307 | ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); | |
311 | ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); | 308 | ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); | |
312 | } else | 309 | } else | |
313 | ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); | 310 | ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); | |
314 | 311 | |||
315 | /* attach the interface */ | 312 | /* attach the interface */ | |
316 | if_attach(ifp); | 313 | if_attach(ifp); | |
317 | ether_ifattach(ifp, eaddr); | 314 | ether_ifattach(ifp, eaddr); | |
318 | 315 | |||
319 | rnd_attach_source(&sc->rnd_source, device_xname(self), | 316 | rnd_attach_source(&sc->rnd_source, device_xname(self), | |
320 | RND_TYPE_NET, RND_FLAG_DEFAULT); | 317 | RND_TYPE_NET, RND_FLAG_DEFAULT); | |
321 | 318 | |||
322 | callout_init(&sc->sc_stat_ch, 0); | 319 | callout_init(&sc->sc_stat_ch, 0); | |
323 | sc->sc_attached = 1; | 320 | sc->sc_attached = 1; | |
324 | splx(s); | |||
325 | 321 | |||
326 | usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, sc->sc_dev); | 322 | usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, sc->sc_dev); | |
327 | 323 | |||
328 | return; | 324 | return; | |
329 | 325 | |||
330 | bad: | 326 | bad: | |
331 | sc->sc_dying = 1; | 327 | sc->sc_dying = 1; | |
332 | return; | 328 | return; | |
333 | } | 329 | } | |
334 | 330 | |||
335 | /* detach */ | 331 | /* detach */ | |
336 | int | 332 | int | |
337 | url_detach(device_t self, int flags) | 333 | url_detach(device_t self, int flags) | |
338 | { | 334 | { | |
339 | struct url_softc *sc = device_private(self); | 335 | struct url_softc *sc = device_private(self); | |
340 | struct ifnet *ifp = GET_IFP(sc); | 336 | struct ifnet *ifp = GET_IFP(sc); | |
341 | int s; | 337 | int s; | |
342 | 338 | |||
343 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 339 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
344 | 340 | |||
345 | /* Detached before attached finished */ | 341 | /* Detached before attached finished */ | |
346 | if (!sc->sc_attached) | 342 | if (!sc->sc_attached) | |
347 | return 0; | 343 | return 0; | |
348 | 344 | |||
349 | callout_stop(&sc->sc_stat_ch); | 345 | callout_stop(&sc->sc_stat_ch); | |
350 | 346 | |||
351 | /* Remove any pending tasks */ | 347 | /* Remove any pending tasks */ | |
352 | usb_rem_task(sc->sc_udev, &sc->sc_tick_task); | 348 | usb_rem_task(sc->sc_udev, &sc->sc_tick_task); | |
353 | usb_rem_task(sc->sc_udev, &sc->sc_stop_task); | 349 | usb_rem_task(sc->sc_udev, &sc->sc_stop_task); | |
354 | 350 | |||
355 | s = splusb(); | 351 | s = splusb(); | |
356 | 352 | |||
357 | if (--sc->sc_refcnt >= 0) { | 353 | if (--sc->sc_refcnt >= 0) { | |
358 | /* Wait for processes to go away */ | 354 | /* Wait for processes to go away */ | |
359 | usb_detach_waitold(sc->sc_dev); | 355 | usb_detach_waitold(sc->sc_dev); | |
360 | } | 356 | } | |
361 | 357 | |||
362 | if (ifp->if_flags & IFF_RUNNING) | 358 | if (ifp->if_flags & IFF_RUNNING) | |
363 | url_stop(GET_IFP(sc), 1); | 359 | url_stop(GET_IFP(sc), 1); | |
364 | 360 | |||
365 | rnd_detach_source(&sc->rnd_source); | 361 | rnd_detach_source(&sc->rnd_source); | |
366 | mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); | 362 | mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); | |
367 | ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY); | 363 | ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY); | |
368 | ether_ifdetach(ifp); | 364 | ether_ifdetach(ifp); | |
369 | if_detach(ifp); | 365 | if_detach(ifp); | |
370 | 366 | |||
371 | #ifdef DIAGNOSTIC | 367 | #ifdef DIAGNOSTIC | |
372 | if (sc->sc_pipe_tx != NULL) | 368 | if (sc->sc_pipe_tx != NULL) | |
373 | aprint_debug_dev(self, "detach has active tx endpoint.\n"); | 369 | aprint_debug_dev(self, "detach has active tx endpoint.\n"); | |
374 | if (sc->sc_pipe_rx != NULL) | 370 | if (sc->sc_pipe_rx != NULL) | |
375 | aprint_debug_dev(self, "detach has active rx endpoint.\n"); | 371 | aprint_debug_dev(self, "detach has active rx endpoint.\n"); | |
376 | if (sc->sc_pipe_intr != NULL) | 372 | if (sc->sc_pipe_intr != NULL) | |
377 | aprint_debug_dev(self, "detach has active intr endpoint.\n"); | 373 | aprint_debug_dev(self, "detach has active intr endpoint.\n"); | |
378 | #endif | 374 | #endif | |
379 | 375 | |||
380 | sc->sc_attached = 0; | 376 | sc->sc_attached = 0; | |
381 | 377 | |||
382 | splx(s); | 378 | splx(s); | |
383 | 379 | |||
384 | rw_destroy(&sc->sc_mii_rwlock); | 380 | rw_destroy(&sc->sc_mii_rwlock); | |
385 | usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); | 381 | usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); | |
386 | 382 | |||
387 | return 0; | 383 | return 0; | |
388 | } | 384 | } | |
389 | 385 | |||
390 | /* read/write memory */ | 386 | /* read/write memory */ | |
391 | Static int | 387 | Static int | |
392 | url_mem(struct url_softc *sc, int cmd, int offset, void *buf, int len) | 388 | url_mem(struct url_softc *sc, int cmd, int offset, void *buf, int len) | |
393 | { | 389 | { | |
394 | usb_device_request_t req; | 390 | usb_device_request_t req; | |
395 | usbd_status err; | 391 | usbd_status err; | |
396 | 392 | |||
397 | if (sc == NULL) | 393 | if (sc == NULL) | |
398 | return 0; | 394 | return 0; | |
399 | 395 | |||
400 | DPRINTFN(0x200, | 396 | DPRINTFN(0x200, | |
401 | ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 397 | ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
402 | 398 | |||
403 | if (sc->sc_dying) | 399 | if (sc->sc_dying) | |
404 | return 0; | 400 | return 0; | |
405 | 401 | |||
406 | if (cmd == URL_CMD_READMEM) | 402 | if (cmd == URL_CMD_READMEM) | |
407 | req.bmRequestType = UT_READ_VENDOR_DEVICE; | 403 | req.bmRequestType = UT_READ_VENDOR_DEVICE; | |
408 | else | 404 | else | |
409 | req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | 405 | req.bmRequestType = UT_WRITE_VENDOR_DEVICE; | |
410 | req.bRequest = URL_REQ_MEM; | 406 | req.bRequest = URL_REQ_MEM; | |
411 | USETW(req.wValue, offset); | 407 | USETW(req.wValue, offset); | |
412 | USETW(req.wIndex, 0x0000); | 408 | USETW(req.wIndex, 0x0000); | |
413 | USETW(req.wLength, len); | 409 | USETW(req.wLength, len); | |
414 | 410 | |||
415 | sc->sc_refcnt++; | 411 | sc->sc_refcnt++; | |
416 | err = usbd_do_request(sc->sc_udev, &req, buf); | 412 | err = usbd_do_request(sc->sc_udev, &req, buf); | |
417 | if (--sc->sc_refcnt < 0) | 413 | if (--sc->sc_refcnt < 0) | |
418 | usb_detach_wakeupold(sc->sc_dev); | 414 | usb_detach_wakeupold(sc->sc_dev); | |
419 | if (err) { | 415 | if (err) { | |
420 | DPRINTF(("%s: url_mem(): %s failed. off=%04x, err=%d\n", | 416 | DPRINTF(("%s: url_mem(): %s failed. off=%04x, err=%d\n", | |
421 | device_xname(sc->sc_dev), | 417 | device_xname(sc->sc_dev), | |
422 | cmd == URL_CMD_READMEM ? "read" : "write", | 418 | cmd == URL_CMD_READMEM ? "read" : "write", | |
423 | offset, err)); | 419 | offset, err)); | |
424 | } | 420 | } | |
425 | 421 | |||
426 | return err; | 422 | return err; | |
427 | } | 423 | } | |
428 | 424 | |||
429 | /* read 1byte from register */ | 425 | /* read 1byte from register */ | |
430 | Static int | 426 | Static int | |
431 | url_csr_read_1(struct url_softc *sc, int reg) | 427 | url_csr_read_1(struct url_softc *sc, int reg) | |
432 | { | 428 | { | |
433 | uint8_t val = 0; | 429 | uint8_t val = 0; | |
434 | 430 | |||
435 | DPRINTFN(0x100, | 431 | DPRINTFN(0x100, | |
436 | ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 432 | ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
437 | 433 | |||
438 | if (sc->sc_dying) | 434 | if (sc->sc_dying) | |
439 | return 0; | 435 | return 0; | |
440 | 436 | |||
441 | return url_mem(sc, URL_CMD_READMEM, reg, &val, 1) ? 0 : val; | 437 | return url_mem(sc, URL_CMD_READMEM, reg, &val, 1) ? 0 : val; | |
442 | } | 438 | } | |
443 | 439 | |||
444 | /* read 2bytes from register */ | 440 | /* read 2bytes from register */ | |
445 | Static int | 441 | Static int | |
446 | url_csr_read_2(struct url_softc *sc, int reg) | 442 | url_csr_read_2(struct url_softc *sc, int reg) | |
447 | { | 443 | { | |
448 | uWord val; | 444 | uWord val; | |
449 | 445 | |||
450 | DPRINTFN(0x100, | 446 | DPRINTFN(0x100, | |
451 | ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 447 | ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
452 | 448 | |||
453 | if (sc->sc_dying) | 449 | if (sc->sc_dying) | |
454 | return 0; | 450 | return 0; | |
455 | 451 | |||
456 | USETW(val, 0); | 452 | USETW(val, 0); | |
457 | return url_mem(sc, URL_CMD_READMEM, reg, &val, 2) ? 0 : UGETW(val); | 453 | return url_mem(sc, URL_CMD_READMEM, reg, &val, 2) ? 0 : UGETW(val); | |
458 | } | 454 | } | |
459 | 455 | |||
460 | /* write 1byte to register */ | 456 | /* write 1byte to register */ | |
461 | Static int | 457 | Static int | |
462 | url_csr_write_1(struct url_softc *sc, int reg, int aval) | 458 | url_csr_write_1(struct url_softc *sc, int reg, int aval) | |
463 | { | 459 | { | |
464 | uint8_t val = aval; | 460 | uint8_t val = aval; | |
465 | 461 | |||
466 | DPRINTFN(0x100, | 462 | DPRINTFN(0x100, | |
467 | ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 463 | ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
468 | 464 | |||
469 | if (sc->sc_dying) | 465 | if (sc->sc_dying) | |
470 | return 0; | 466 | return 0; | |
471 | 467 | |||
472 | return url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 1) ? -1 : 0; | 468 | return url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 1) ? -1 : 0; | |
473 | } | 469 | } | |
474 | 470 | |||
475 | /* write 2bytes to register */ | 471 | /* write 2bytes to register */ | |
476 | Static int | 472 | Static int | |
477 | url_csr_write_2(struct url_softc *sc, int reg, int aval) | 473 | url_csr_write_2(struct url_softc *sc, int reg, int aval) | |
478 | { | 474 | { | |
479 | uWord val; | 475 | uWord val; | |
480 | 476 | |||
481 | DPRINTFN(0x100, | 477 | DPRINTFN(0x100, | |
482 | ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 478 | ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
483 | 479 | |||
484 | USETW(val, aval); | 480 | USETW(val, aval); | |
485 | 481 | |||
486 | if (sc->sc_dying) | 482 | if (sc->sc_dying) | |
487 | return 0; | 483 | return 0; | |
488 | 484 | |||
489 | return url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 2) ? -1 : 0; | 485 | return url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 2) ? -1 : 0; | |
490 | } | 486 | } | |
491 | 487 | |||
492 | /* write 4bytes to register */ | 488 | /* write 4bytes to register */ | |
493 | Static int | 489 | Static int | |
494 | url_csr_write_4(struct url_softc *sc, int reg, int aval) | 490 | url_csr_write_4(struct url_softc *sc, int reg, int aval) | |
495 | { | 491 | { | |
496 | uDWord val; | 492 | uDWord val; | |
497 | 493 | |||
498 | DPRINTFN(0x100, | 494 | DPRINTFN(0x100, | |
499 | ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 495 | ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
500 | 496 | |||
501 | USETDW(val, aval); | 497 | USETDW(val, aval); | |
502 | 498 | |||
503 | if (sc->sc_dying) | 499 | if (sc->sc_dying) | |
504 | return 0; | 500 | return 0; | |
505 | 501 | |||
506 | return url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 4) ? -1 : 0; | 502 | return url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 4) ? -1 : 0; | |
507 | } | 503 | } | |
508 | 504 | |||
509 | Static int | 505 | Static int | |
510 | url_init(struct ifnet *ifp) | 506 | url_init(struct ifnet *ifp) | |
511 | { | 507 | { | |
512 | struct url_softc *sc = ifp->if_softc; | 508 | struct url_softc *sc = ifp->if_softc; | |
513 | struct mii_data *mii = GET_MII(sc); | 509 | struct mii_data *mii = GET_MII(sc); | |
514 | const u_char *eaddr; | 510 | const u_char *eaddr; | |
515 | int i, rc, s; | 511 | int i, rc, s; | |
516 | 512 | |||
517 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 513 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
518 | 514 | |||
519 | if (sc->sc_dying) | 515 | if (sc->sc_dying) | |
520 | return EIO; | 516 | return EIO; | |
521 | 517 | |||
522 | s = splnet(); | 518 | s = splnet(); | |
523 | 519 | |||
524 | /* Cancel pending I/O and free all TX/RX buffers */ | 520 | /* Cancel pending I/O and free all TX/RX buffers */ | |
525 | url_stop(ifp, 1); | 521 | url_stop(ifp, 1); | |
526 | 522 | |||
527 | eaddr = CLLADDR(ifp->if_sadl); | 523 | eaddr = CLLADDR(ifp->if_sadl); | |
528 | for (i = 0; i < ETHER_ADDR_LEN; i++) | 524 | for (i = 0; i < ETHER_ADDR_LEN; i++) | |
529 | url_csr_write_1(sc, URL_IDR0 + i, eaddr[i]); | 525 | url_csr_write_1(sc, URL_IDR0 + i, eaddr[i]); | |
530 | 526 | |||
531 | /* Init transmission control register */ | 527 | /* Init transmission control register */ | |
532 | URL_CLRBIT(sc, URL_TCR, | 528 | URL_CLRBIT(sc, URL_TCR, | |
533 | URL_TCR_TXRR1 | URL_TCR_TXRR0 | | 529 | URL_TCR_TXRR1 | URL_TCR_TXRR0 | | |
534 | URL_TCR_IFG1 | URL_TCR_IFG0 | | 530 | URL_TCR_IFG1 | URL_TCR_IFG0 | | |
535 | URL_TCR_NOCRC); | 531 | URL_TCR_NOCRC); | |
536 | 532 | |||
537 | /* Init receive control register */ | 533 | /* Init receive control register */ | |
538 | URL_SETBIT2(sc, URL_RCR, URL_RCR_TAIL | URL_RCR_AD); | 534 | URL_SETBIT2(sc, URL_RCR, URL_RCR_TAIL | URL_RCR_AD); | |
539 | if (ifp->if_flags & IFF_BROADCAST) | 535 | if (ifp->if_flags & IFF_BROADCAST) | |
540 | URL_SETBIT2(sc, URL_RCR, URL_RCR_AB); | 536 | URL_SETBIT2(sc, URL_RCR, URL_RCR_AB); | |
541 | else | 537 | else | |
542 | URL_CLRBIT2(sc, URL_RCR, URL_RCR_AB); | 538 | URL_CLRBIT2(sc, URL_RCR, URL_RCR_AB); | |
543 | 539 | |||
544 | /* If we want promiscuous mode, accept all physical frames. */ | 540 | /* If we want promiscuous mode, accept all physical frames. */ | |
545 | if (ifp->if_flags & IFF_PROMISC) | 541 | if (ifp->if_flags & IFF_PROMISC) | |
546 | URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); | 542 | URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); | |
547 | else | 543 | else | |
548 | URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); | 544 | URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); | |
549 | 545 | |||
550 | 546 | |||
551 | /* Load the multicast filter */ | 547 | /* Load the multicast filter */ | |
552 | url_setmulti(sc); | 548 | url_setmulti(sc); | |
553 | 549 | |||
554 | /* Enable RX and TX */ | 550 | /* Enable RX and TX */ | |
555 | URL_SETBIT(sc, URL_CR, URL_CR_TE | URL_CR_RE); | 551 | URL_SETBIT(sc, URL_CR, URL_CR_TE | URL_CR_RE); | |
556 | 552 | |||
557 | if ((rc = mii_mediachg(mii)) == ENXIO) | 553 | if ((rc = mii_mediachg(mii)) == ENXIO) | |
558 | rc = 0; | 554 | rc = 0; | |
559 | else if (rc != 0) | 555 | else if (rc != 0) | |
560 | goto out; | 556 | goto out; | |
561 | 557 | |||
562 | if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) { | 558 | if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) { | |
563 | if (url_openpipes(sc)) { | 559 | if (url_openpipes(sc)) { | |
564 | splx(s); | 560 | splx(s); | |
565 | return EIO; | 561 | return EIO; | |
566 | } | 562 | } | |
567 | } | 563 | } | |
568 | /* Initialize transmit ring */ | 564 | /* Initialize transmit ring */ | |
569 | if (url_tx_list_init(sc)) { | 565 | if (url_tx_list_init(sc)) { | |
570 | printf("%s: tx list init failed\n", device_xname(sc->sc_dev)); | 566 | printf("%s: tx list init failed\n", device_xname(sc->sc_dev)); | |
571 | splx(s); | 567 | splx(s); | |
572 | return EIO; | 568 | return EIO; | |
573 | } | 569 | } | |
574 | 570 | |||
575 | /* Initialize receive ring */ | 571 | /* Initialize receive ring */ | |
576 | if (url_rx_list_init(sc)) { | 572 | if (url_rx_list_init(sc)) { | |
577 | printf("%s: rx list init failed\n", device_xname(sc->sc_dev)); | 573 | printf("%s: rx list init failed\n", device_xname(sc->sc_dev)); | |
578 | splx(s); | 574 | splx(s); | |
579 | return EIO; | 575 | return EIO; | |
580 | } | 576 | } | |
581 | /* Start up the receive pipe. */ | 577 | /* Start up the receive pipe. */ | |
582 | for (i = 0; i < URL_RX_LIST_CNT; i++) { | 578 | for (i = 0; i < URL_RX_LIST_CNT; i++) { | |
583 | struct url_chain *c = &sc->sc_cdata.url_rx_chain[i]; | 579 | struct url_chain *c = &sc->sc_cdata.url_rx_chain[i]; | |
584 | 580 | |||
585 | usbd_setup_xfer(c->url_xfer, c, c->url_buf, URL_BUFSZ, | 581 | usbd_setup_xfer(c->url_xfer, c, c->url_buf, URL_BUFSZ, | |
586 | USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, url_rxeof); | 582 | USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, url_rxeof); | |
587 | (void)usbd_transfer(c->url_xfer); | 583 | (void)usbd_transfer(c->url_xfer); | |
588 | DPRINTF(("%s: %s: start read\n", device_xname(sc->sc_dev), | 584 | DPRINTF(("%s: %s: start read\n", device_xname(sc->sc_dev), | |
589 | __func__)); | 585 | __func__)); | |
590 | } | 586 | } | |
591 | 587 | |||
592 | ifp->if_flags |= IFF_RUNNING; | 588 | ifp->if_flags |= IFF_RUNNING; | |
593 | ifp->if_flags &= ~IFF_OACTIVE; | 589 | ifp->if_flags &= ~IFF_OACTIVE; | |
594 | 590 | |||
595 | callout_reset(&sc->sc_stat_ch, hz, url_tick, sc); | 591 | callout_reset(&sc->sc_stat_ch, hz, url_tick, sc); | |
596 | 592 | |||
597 | out: | 593 | out: | |
598 | splx(s); | 594 | splx(s); | |
599 | return rc; | 595 | return rc; | |
600 | } | 596 | } | |
601 | 597 | |||
602 | Static void | 598 | Static void | |
603 | url_reset(struct url_softc *sc) | 599 | url_reset(struct url_softc *sc) | |
604 | { | 600 | { | |
605 | int i; | 601 | int i; | |
606 | 602 | |||
607 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 603 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
608 | 604 | |||
609 | if (sc->sc_dying) | 605 | if (sc->sc_dying) | |
610 | return; | 606 | return; | |
611 | 607 | |||
612 | URL_SETBIT(sc, URL_CR, URL_CR_SOFT_RST); | 608 | URL_SETBIT(sc, URL_CR, URL_CR_SOFT_RST); | |
613 | 609 | |||
614 | for (i = 0; i < URL_TX_TIMEOUT; i++) { | 610 | for (i = 0; i < URL_TX_TIMEOUT; i++) { | |
615 | if (!(url_csr_read_1(sc, URL_CR) & URL_CR_SOFT_RST)) | 611 | if (!(url_csr_read_1(sc, URL_CR) & URL_CR_SOFT_RST)) | |
616 | break; | 612 | break; | |
617 | delay(10); /* XXX */ | 613 | delay(10); /* XXX */ | |
618 | } | 614 | } | |
619 | 615 | |||
620 | delay(10000); /* XXX */ | 616 | delay(10000); /* XXX */ | |
621 | } | 617 | } | |
622 | 618 | |||
623 | int | 619 | int | |
624 | url_activate(device_t self, enum devact act) | 620 | url_activate(device_t self, enum devact act) | |
625 | { | 621 | { | |
626 | struct url_softc *sc = device_private(self); | 622 | struct url_softc *sc = device_private(self); | |
627 | 623 | |||
628 | DPRINTF(("%s: %s: enter, act=%d\n", device_xname(sc->sc_dev), | 624 | DPRINTF(("%s: %s: enter, act=%d\n", device_xname(sc->sc_dev), | |
629 | __func__, act)); | 625 | __func__, act)); | |
630 | 626 | |||
631 | switch (act) { | 627 | switch (act) { | |
632 | case DVACT_DEACTIVATE: | 628 | case DVACT_DEACTIVATE: | |
633 | if_deactivate(&sc->sc_ec.ec_if); | 629 | if_deactivate(&sc->sc_ec.ec_if); | |
634 | sc->sc_dying = 1; | 630 | sc->sc_dying = 1; | |
635 | return 0; | 631 | return 0; | |
636 | default: | 632 | default: | |
637 | return EOPNOTSUPP; | 633 | return EOPNOTSUPP; | |
638 | } | 634 | } | |
639 | } | 635 | } | |
640 | 636 | |||
641 | #define url_calchash(addr) (ether_crc32_be((addr), ETHER_ADDR_LEN) >> 26) | 637 | #define url_calchash(addr) (ether_crc32_be((addr), ETHER_ADDR_LEN) >> 26) | |
642 | 638 | |||
643 | 639 | |||
644 | Static void | 640 | Static void | |
645 | url_setmulti(struct url_softc *sc) | 641 | url_setmulti(struct url_softc *sc) | |
646 | { | 642 | { | |
647 | struct ifnet *ifp; | 643 | struct ifnet *ifp; | |
648 | struct ether_multi *enm; | 644 | struct ether_multi *enm; | |
649 | struct ether_multistep step; | 645 | struct ether_multistep step; | |
650 | uint32_t hashes[2] = { 0, 0 }; | 646 | uint32_t hashes[2] = { 0, 0 }; | |
651 | int h = 0; | 647 | int h = 0; | |
652 | int mcnt = 0; | 648 | int mcnt = 0; | |
653 | 649 | |||
654 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 650 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
655 | 651 | |||
656 | if (sc->sc_dying) | 652 | if (sc->sc_dying) | |
657 | return; | 653 | return; | |
658 | 654 | |||
659 | ifp = GET_IFP(sc); | 655 | ifp = GET_IFP(sc); | |
660 | 656 | |||
661 | if (ifp->if_flags & IFF_PROMISC) { | 657 | if (ifp->if_flags & IFF_PROMISC) { | |
662 | URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); | 658 | URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); | |
663 | return; | 659 | return; | |
664 | } else if (ifp->if_flags & IFF_ALLMULTI) { | 660 | } else if (ifp->if_flags & IFF_ALLMULTI) { | |
665 | allmulti: | 661 | allmulti: | |
666 | ifp->if_flags |= IFF_ALLMULTI; | 662 | ifp->if_flags |= IFF_ALLMULTI; | |
667 | URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM); | 663 | URL_SETBIT2(sc, URL_RCR, URL_RCR_AAM); | |
668 | URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAP); | 664 | URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAP); | |
669 | return; | 665 | return; | |
670 | } | 666 | } | |
671 | 667 | |||
672 | /* first, zot all the existing hash bits */ | 668 | /* first, zot all the existing hash bits */ | |
673 | url_csr_write_4(sc, URL_MAR0, 0); | 669 | url_csr_write_4(sc, URL_MAR0, 0); | |
674 | url_csr_write_4(sc, URL_MAR4, 0); | 670 | url_csr_write_4(sc, URL_MAR4, 0); | |
675 | 671 | |||
676 | /* now program new ones */ | 672 | /* now program new ones */ | |
677 | ETHER_FIRST_MULTI(step, &sc->sc_ec, enm); | 673 | ETHER_FIRST_MULTI(step, &sc->sc_ec, enm); | |
678 | while (enm != NULL) { | 674 | while (enm != NULL) { | |
679 | if (memcmp(enm->enm_addrlo, enm->enm_addrhi, | 675 | if (memcmp(enm->enm_addrlo, enm->enm_addrhi, | |
680 | ETHER_ADDR_LEN) != 0) | 676 | ETHER_ADDR_LEN) != 0) | |
681 | goto allmulti; | 677 | goto allmulti; | |
682 | 678 | |||
683 | h = url_calchash(enm->enm_addrlo); | 679 | h = url_calchash(enm->enm_addrlo); | |
684 | if (h < 32) | 680 | if (h < 32) | |
685 | hashes[0] |= (1 << h); | 681 | hashes[0] |= (1 << h); | |
686 | else | 682 | else | |
687 | hashes[1] |= (1 << (h -32)); | 683 | hashes[1] |= (1 << (h -32)); | |
688 | mcnt++; | 684 | mcnt++; | |
689 | ETHER_NEXT_MULTI(step, enm); | 685 | ETHER_NEXT_MULTI(step, enm); | |
690 | } | 686 | } | |
691 | 687 | |||
692 | ifp->if_flags &= ~IFF_ALLMULTI; | 688 | ifp->if_flags &= ~IFF_ALLMULTI; | |
693 | 689 | |||
694 | URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); | 690 | URL_CLRBIT2(sc, URL_RCR, URL_RCR_AAM|URL_RCR_AAP); | |
695 | 691 | |||
696 | if (mcnt){ | 692 | if (mcnt){ | |
697 | URL_SETBIT2(sc, URL_RCR, URL_RCR_AM); | 693 | URL_SETBIT2(sc, URL_RCR, URL_RCR_AM); | |
698 | } else { | 694 | } else { | |
699 | URL_CLRBIT2(sc, URL_RCR, URL_RCR_AM); | 695 | URL_CLRBIT2(sc, URL_RCR, URL_RCR_AM); | |
700 | } | 696 | } | |
701 | url_csr_write_4(sc, URL_MAR0, hashes[0]); | 697 | url_csr_write_4(sc, URL_MAR0, hashes[0]); | |
702 | url_csr_write_4(sc, URL_MAR4, hashes[1]); | 698 | url_csr_write_4(sc, URL_MAR4, hashes[1]); | |
703 | } | 699 | } | |
704 | 700 | |||
705 | Static int | 701 | Static int | |
706 | url_openpipes(struct url_softc *sc) | 702 | url_openpipes(struct url_softc *sc) | |
707 | { | 703 | { | |
708 | usbd_status err; | 704 | usbd_status err; | |
709 | int error = 0; | 705 | int error = 0; | |
710 | 706 | |||
711 | if (sc->sc_dying) | 707 | if (sc->sc_dying) | |
712 | return EIO; | 708 | return EIO; | |
713 | 709 | |||
714 | sc->sc_refcnt++; | 710 | sc->sc_refcnt++; | |
715 | 711 | |||
716 | /* Open RX pipe */ | 712 | /* Open RX pipe */ | |
717 | err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no, | 713 | err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no, | |
718 | USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx); | 714 | USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx); | |
719 | if (err) { | 715 | if (err) { | |
720 | printf("%s: open rx pipe failed: %s\n", | 716 | printf("%s: open rx pipe failed: %s\n", | |
721 | device_xname(sc->sc_dev), usbd_errstr(err)); | 717 | device_xname(sc->sc_dev), usbd_errstr(err)); | |
722 | error = EIO; | 718 | error = EIO; | |
723 | goto done; | 719 | goto done; | |
724 | } | 720 | } | |
725 | 721 | |||
726 | /* Open TX pipe */ | 722 | /* Open TX pipe */ | |
727 | err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no, | 723 | err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no, | |
728 | USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx); | 724 | USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx); | |
729 | if (err) { | 725 | if (err) { | |
730 | printf("%s: open tx pipe failed: %s\n", | 726 | printf("%s: open tx pipe failed: %s\n", | |
731 | device_xname(sc->sc_dev), usbd_errstr(err)); | 727 | device_xname(sc->sc_dev), usbd_errstr(err)); | |
732 | error = EIO; | 728 | error = EIO; | |
733 | goto done; | 729 | goto done; | |
734 | } | 730 | } | |
735 | 731 | |||
736 | #if 0 | 732 | #if 0 | |
737 | /* XXX: interrupt endpoint is not yet supported */ | 733 | /* XXX: interrupt endpoint is not yet supported */ | |
738 | /* Open Interrupt pipe */ | 734 | /* Open Interrupt pipe */ | |
739 | err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no, | 735 | err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no, | |
740 | USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc, | 736 | USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc, | |
741 | &sc->sc_cdata.url_ibuf, URL_INTR_PKGLEN, | 737 | &sc->sc_cdata.url_ibuf, URL_INTR_PKGLEN, | |
742 | url_intr, USBD_DEFAULT_INTERVAL); | 738 | url_intr, USBD_DEFAULT_INTERVAL); | |
743 | if (err) { | 739 | if (err) { | |
744 | printf("%s: open intr pipe failed: %s\n", | 740 | printf("%s: open intr pipe failed: %s\n", | |
745 | device_xname(sc->sc_dev), usbd_errstr(err)); | 741 | device_xname(sc->sc_dev), usbd_errstr(err)); | |
746 | error = EIO; | 742 | error = EIO; | |
747 | goto done; | 743 | goto done; | |
748 | } | 744 | } | |
749 | #endif | 745 | #endif | |
750 | 746 | |||
751 | done: | 747 | done: | |
752 | if (--sc->sc_refcnt < 0) | 748 | if (--sc->sc_refcnt < 0) | |
753 | usb_detach_wakeupold(sc->sc_dev); | 749 | usb_detach_wakeupold(sc->sc_dev); | |
754 | 750 | |||
755 | return error; | 751 | return error; | |
756 | } | 752 | } | |
757 | 753 | |||
758 | Static int | 754 | Static int | |
759 | url_newbuf(struct url_softc *sc, struct url_chain *c, struct mbuf *m) | 755 | url_newbuf(struct url_softc *sc, struct url_chain *c, struct mbuf *m) | |
760 | { | 756 | { | |
761 | struct mbuf *m_new = NULL; | 757 | struct mbuf *m_new = NULL; | |
762 | 758 | |||
763 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 759 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
764 | 760 | |||
765 | if (m == NULL) { | 761 | if (m == NULL) { | |
766 | MGETHDR(m_new, M_DONTWAIT, MT_DATA); | 762 | MGETHDR(m_new, M_DONTWAIT, MT_DATA); | |
767 | if (m_new == NULL) { | 763 | if (m_new == NULL) { | |
768 | printf("%s: no memory for rx list " | 764 | printf("%s: no memory for rx list " | |
769 | "-- packet dropped!\n", device_xname(sc->sc_dev)); | 765 | "-- packet dropped!\n", device_xname(sc->sc_dev)); | |
770 | return ENOBUFS; | 766 | return ENOBUFS; | |
771 | } | 767 | } | |
772 | MCLGET(m_new, M_DONTWAIT); | 768 | MCLGET(m_new, M_DONTWAIT); | |
773 | if (!(m_new->m_flags & M_EXT)) { | 769 | if (!(m_new->m_flags & M_EXT)) { | |
774 | printf("%s: no memory for rx list " | 770 | printf("%s: no memory for rx list " | |
775 | "-- packet dropped!\n", device_xname(sc->sc_dev)); | 771 | "-- packet dropped!\n", device_xname(sc->sc_dev)); | |
776 | m_freem(m_new); | 772 | m_freem(m_new); | |
777 | return ENOBUFS; | 773 | return ENOBUFS; | |
778 | } | 774 | } | |
779 | m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; | 775 | m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; | |
780 | } else { | 776 | } else { | |
781 | m_new = m; | 777 | m_new = m; | |
782 | m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; | 778 | m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; | |
783 | m_new->m_data = m_new->m_ext.ext_buf; | 779 | m_new->m_data = m_new->m_ext.ext_buf; | |
784 | } | 780 | } | |
785 | 781 | |||
786 | m_adj(m_new, ETHER_ALIGN); | 782 | m_adj(m_new, ETHER_ALIGN); | |
787 | c->url_mbuf = m_new; | 783 | c->url_mbuf = m_new; | |
788 | 784 | |||
789 | return 0; | 785 | return 0; | |
790 | } | 786 | } | |
791 | 787 | |||
792 | 788 | |||
793 | Static int | 789 | Static int | |
794 | url_rx_list_init(struct url_softc *sc) | 790 | url_rx_list_init(struct url_softc *sc) | |
795 | { | 791 | { | |
796 | struct url_cdata *cd; | 792 | struct url_cdata *cd; | |
797 | struct url_chain *c; | 793 | struct url_chain *c; | |
798 | int i; | 794 | int i; | |
799 | 795 | |||
800 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 796 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
801 | 797 | |||
802 | cd = &sc->sc_cdata; | 798 | cd = &sc->sc_cdata; | |
803 | for (i = 0; i < URL_RX_LIST_CNT; i++) { | 799 | for (i = 0; i < URL_RX_LIST_CNT; i++) { | |
804 | c = &cd->url_rx_chain[i]; | 800 | c = &cd->url_rx_chain[i]; | |
805 | c->url_sc = sc; | 801 | c->url_sc = sc; | |
806 | c->url_idx = i; | 802 | c->url_idx = i; | |
807 | if (url_newbuf(sc, c, NULL) == ENOBUFS) | 803 | if (url_newbuf(sc, c, NULL) == ENOBUFS) | |
808 | return ENOBUFS; | 804 | return ENOBUFS; | |
809 | if (c->url_xfer == NULL) { | 805 | if (c->url_xfer == NULL) { | |
810 | int error = usbd_create_xfer(sc->sc_pipe_rx, URL_BUFSZ, | 806 | int error = usbd_create_xfer(sc->sc_pipe_rx, URL_BUFSZ, | |
811 | USBD_SHORT_XFER_OK, 0, &c->url_xfer); | 807 | USBD_SHORT_XFER_OK, 0, &c->url_xfer); | |
812 | if (error) | 808 | if (error) | |
813 | return error; | 809 | return error; | |
814 | c->url_buf = usbd_get_buffer(c->url_xfer); | 810 | c->url_buf = usbd_get_buffer(c->url_xfer); | |
815 | } | 811 | } | |
816 | } | 812 | } | |
817 | 813 | |||
818 | return 0; | 814 | return 0; | |
819 | } | 815 | } | |
820 | 816 | |||
821 | Static int | 817 | Static int | |
822 | url_tx_list_init(struct url_softc *sc) | 818 | url_tx_list_init(struct url_softc *sc) | |
823 | { | 819 | { | |
824 | struct url_cdata *cd; | 820 | struct url_cdata *cd; | |
825 | struct url_chain *c; | 821 | struct url_chain *c; | |
826 | int i; | 822 | int i; | |
827 | 823 | |||
828 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 824 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
829 | 825 | |||
830 | cd = &sc->sc_cdata; | 826 | cd = &sc->sc_cdata; | |
831 | for (i = 0; i < URL_TX_LIST_CNT; i++) { | 827 | for (i = 0; i < URL_TX_LIST_CNT; i++) { | |
832 | c = &cd->url_tx_chain[i]; | 828 | c = &cd->url_tx_chain[i]; | |
833 | c->url_sc = sc; | 829 | c->url_sc = sc; | |
834 | c->url_idx = i; | 830 | c->url_idx = i; | |
835 | c->url_mbuf = NULL; | 831 | c->url_mbuf = NULL; | |
836 | if (c->url_xfer == NULL) { | 832 | if (c->url_xfer == NULL) { | |
837 | int error = usbd_create_xfer(sc->sc_pipe_tx, URL_BUFSZ, | 833 | int error = usbd_create_xfer(sc->sc_pipe_tx, URL_BUFSZ, | |
838 | USBD_FORCE_SHORT_XFER, 0, &c->url_xfer); | 834 | USBD_FORCE_SHORT_XFER, 0, &c->url_xfer); | |
839 | if (error) | 835 | if (error) | |
840 | return error; | 836 | return error; | |
841 | c->url_buf = usbd_get_buffer(c->url_xfer); | 837 | c->url_buf = usbd_get_buffer(c->url_xfer); | |
842 | } | 838 | } | |
843 | } | 839 | } | |
844 | 840 | |||
845 | return 0; | 841 | return 0; | |
846 | } | 842 | } | |
847 | 843 | |||
848 | Static void | 844 | Static void | |
849 | url_start(struct ifnet *ifp) | 845 | url_start(struct ifnet *ifp) | |
850 | { | 846 | { | |
851 | struct url_softc *sc = ifp->if_softc; | 847 | struct url_softc *sc = ifp->if_softc; | |
852 | struct mbuf *m_head = NULL; | 848 | struct mbuf *m_head = NULL; | |
853 | 849 | |||
854 | DPRINTF(("%s: %s: enter, link=%d\n", device_xname(sc->sc_dev), | 850 | DPRINTF(("%s: %s: enter, link=%d\n", device_xname(sc->sc_dev), | |
855 | __func__, sc->sc_link)); | 851 | __func__, sc->sc_link)); | |
856 | 852 | |||
857 | if (sc->sc_dying) | 853 | if (sc->sc_dying) | |
858 | return; | 854 | return; | |
859 | 855 | |||
860 | if (!sc->sc_link) | 856 | if (!sc->sc_link) | |
861 | return; | 857 | return; | |
862 | 858 | |||
863 | if (ifp->if_flags & IFF_OACTIVE) | 859 | if (ifp->if_flags & IFF_OACTIVE) | |
864 | return; | 860 | return; | |
865 | 861 | |||
866 | IFQ_POLL(&ifp->if_snd, m_head); | 862 | IFQ_POLL(&ifp->if_snd, m_head); | |
867 | if (m_head == NULL) | 863 | if (m_head == NULL) | |
868 | return; | 864 | return; | |
869 | 865 | |||
870 | if (url_send(sc, m_head, 0)) { | 866 | if (url_send(sc, m_head, 0)) { | |
871 | ifp->if_flags |= IFF_OACTIVE; | 867 | ifp->if_flags |= IFF_OACTIVE; | |
872 | return; | 868 | return; | |
873 | } | 869 | } | |
874 | 870 | |||
875 | IFQ_DEQUEUE(&ifp->if_snd, m_head); | 871 | IFQ_DEQUEUE(&ifp->if_snd, m_head); | |
876 | 872 | |||
877 | bpf_mtap(ifp, m_head); | 873 | bpf_mtap(ifp, m_head); | |
878 | 874 | |||
879 | ifp->if_flags |= IFF_OACTIVE; | 875 | ifp->if_flags |= IFF_OACTIVE; | |
880 | 876 | |||
881 | /* Set a timeout in case the chip goes out to lunch. */ | 877 | /* Set a timeout in case the chip goes out to lunch. */ | |
882 | ifp->if_timer = 5; | 878 | ifp->if_timer = 5; | |
883 | } | 879 | } | |
884 | 880 | |||
885 | Static int | 881 | Static int | |
886 | url_send(struct url_softc *sc, struct mbuf *m, int idx) | 882 | url_send(struct url_softc *sc, struct mbuf *m, int idx) | |
887 | { | 883 | { | |
888 | int total_len; | 884 | int total_len; | |
889 | struct url_chain *c; | 885 | struct url_chain *c; | |
890 | usbd_status err; | 886 | usbd_status err; | |
891 | 887 | |||
892 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev),__func__)); | 888 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev),__func__)); | |
893 | 889 | |||
894 | c = &sc->sc_cdata.url_tx_chain[idx]; | 890 | c = &sc->sc_cdata.url_tx_chain[idx]; | |
895 | 891 | |||
896 | /* Copy the mbuf data into a contiguous buffer */ | 892 | /* Copy the mbuf data into a contiguous buffer */ | |
897 | m_copydata(m, 0, m->m_pkthdr.len, c->url_buf); | 893 | m_copydata(m, 0, m->m_pkthdr.len, c->url_buf); | |
898 | c->url_mbuf = m; | 894 | c->url_mbuf = m; | |
899 | total_len = m->m_pkthdr.len; | 895 | total_len = m->m_pkthdr.len; | |
900 | 896 | |||
901 | if (total_len < URL_MIN_FRAME_LEN) { | 897 | if (total_len < URL_MIN_FRAME_LEN) { | |
902 | memset(c->url_buf + total_len, 0, | 898 | memset(c->url_buf + total_len, 0, | |
903 | URL_MIN_FRAME_LEN - total_len); | 899 | URL_MIN_FRAME_LEN - total_len); | |
904 | total_len = URL_MIN_FRAME_LEN; | 900 | total_len = URL_MIN_FRAME_LEN; | |
905 | } | 901 | } | |
906 | usbd_setup_xfer(c->url_xfer,c, c->url_buf, total_len, | 902 | usbd_setup_xfer(c->url_xfer,c, c->url_buf, total_len, | |
907 | USBD_FORCE_SHORT_XFER, URL_TX_TIMEOUT, url_txeof); | 903 | USBD_FORCE_SHORT_XFER, URL_TX_TIMEOUT, url_txeof); | |
908 | 904 | |||
909 | /* Transmit */ | 905 | /* Transmit */ | |
910 | sc->sc_refcnt++; | 906 | sc->sc_refcnt++; | |
911 | err = usbd_transfer(c->url_xfer); | 907 | err = usbd_transfer(c->url_xfer); | |
912 | if (--sc->sc_refcnt < 0) | 908 | if (--sc->sc_refcnt < 0) | |
913 | usb_detach_wakeupold(sc->sc_dev); | 909 | usb_detach_wakeupold(sc->sc_dev); | |
914 | if (err != USBD_IN_PROGRESS) { | 910 | if (err != USBD_IN_PROGRESS) { | |
915 | printf("%s: url_send error=%s\n", device_xname(sc->sc_dev), | 911 | printf("%s: url_send error=%s\n", device_xname(sc->sc_dev), | |
916 | usbd_errstr(err)); | 912 | usbd_errstr(err)); | |
917 | /* Stop the interface */ | 913 | /* Stop the interface */ | |
918 | usb_add_task(sc->sc_udev, &sc->sc_stop_task, | 914 | usb_add_task(sc->sc_udev, &sc->sc_stop_task, | |
919 | USB_TASKQ_DRIVER); | 915 | USB_TASKQ_DRIVER); | |
920 | return EIO; | 916 | return EIO; | |
921 | } | 917 | } | |
922 | 918 | |||
923 | DPRINTF(("%s: %s: send %d bytes\n", device_xname(sc->sc_dev), | 919 | DPRINTF(("%s: %s: send %d bytes\n", device_xname(sc->sc_dev), | |
924 | __func__, total_len)); | 920 | __func__, total_len)); | |
925 | 921 | |||
926 | sc->sc_cdata.url_tx_cnt++; | 922 | sc->sc_cdata.url_tx_cnt++; | |
927 | 923 | |||
928 | return 0; | 924 | return 0; | |
929 | } | 925 | } | |
930 | 926 | |||
931 | Static void | 927 | Static void | |
932 | url_txeof(struct usbd_xfer *xfer, void *priv, | 928 | url_txeof(struct usbd_xfer *xfer, void *priv, | |
933 | usbd_status status) | 929 | usbd_status status) | |
934 | { | 930 | { | |
935 | struct url_chain *c = priv; | 931 | struct url_chain *c = priv; | |
936 | struct url_softc *sc = c->url_sc; | 932 | struct url_softc *sc = c->url_sc; | |
937 | struct ifnet *ifp = GET_IFP(sc); | 933 | struct ifnet *ifp = GET_IFP(sc); | |
938 | int s; | 934 | int s; | |
939 | 935 | |||
940 | if (sc->sc_dying) | 936 | if (sc->sc_dying) | |
941 | return; | 937 | return; | |
942 | 938 | |||
943 | s = splnet(); | 939 | s = splnet(); | |
944 | 940 | |||
945 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 941 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
946 | 942 | |||
947 | ifp->if_timer = 0; | 943 | ifp->if_timer = 0; | |
948 | ifp->if_flags &= ~IFF_OACTIVE; | 944 | ifp->if_flags &= ~IFF_OACTIVE; | |
949 | 945 | |||
950 | if (status != USBD_NORMAL_COMPLETION) { | 946 | if (status != USBD_NORMAL_COMPLETION) { | |
951 | if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { | 947 | if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { | |
952 | splx(s); | 948 | splx(s); | |
953 | return; | 949 | return; | |
954 | } | 950 | } | |
955 | ifp->if_oerrors++; | 951 | ifp->if_oerrors++; | |
956 | printf("%s: usb error on tx: %s\n", device_xname(sc->sc_dev), | 952 | printf("%s: usb error on tx: %s\n", device_xname(sc->sc_dev), | |
957 | usbd_errstr(status)); | 953 | usbd_errstr(status)); | |
958 | if (status == USBD_STALLED) { | 954 | if (status == USBD_STALLED) { | |
959 | sc->sc_refcnt++; | 955 | sc->sc_refcnt++; | |
960 | usbd_clear_endpoint_stall_async(sc->sc_pipe_tx); | 956 | usbd_clear_endpoint_stall_async(sc->sc_pipe_tx); | |
961 | if (--sc->sc_refcnt < 0) | 957 | if (--sc->sc_refcnt < 0) | |
962 | usb_detach_wakeupold(sc->sc_dev); | 958 | usb_detach_wakeupold(sc->sc_dev); | |
963 | } | 959 | } | |
964 | splx(s); | 960 | splx(s); | |
965 | return; | 961 | return; | |
966 | } | 962 | } | |
967 | 963 | |||
968 | ifp->if_opackets++; | 964 | ifp->if_opackets++; | |
969 | 965 | |||
970 | m_freem(c->url_mbuf); | 966 | m_freem(c->url_mbuf); | |
971 | c->url_mbuf = NULL; | 967 | c->url_mbuf = NULL; | |
972 | 968 | |||
973 | if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) | 969 | if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) | |
974 | url_start(ifp); | 970 | url_start(ifp); | |
975 | 971 | |||
976 | splx(s); | 972 | splx(s); | |
977 | } | 973 | } | |
978 | 974 | |||
979 | Static void | 975 | Static void | |
980 | url_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) | 976 | url_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) | |
981 | { | 977 | { | |
982 | struct url_chain *c = priv; | 978 | struct url_chain *c = priv; | |
983 | struct url_softc *sc = c->url_sc; | 979 | struct url_softc *sc = c->url_sc; | |
984 | struct ifnet *ifp = GET_IFP(sc); | 980 | struct ifnet *ifp = GET_IFP(sc); | |
985 | struct mbuf *m; | 981 | struct mbuf *m; | |
986 | uint32_t total_len; | 982 | uint32_t total_len; | |
987 | url_rxhdr_t rxhdr; | 983 | url_rxhdr_t rxhdr; | |
988 | int s; | 984 | int s; | |
989 | 985 | |||
990 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev),__func__)); | 986 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev),__func__)); | |
991 | 987 | |||
992 | if (sc->sc_dying) | 988 | if (sc->sc_dying) | |
993 | return; | 989 | return; | |
994 | 990 | |||
995 | if (status != USBD_NORMAL_COMPLETION) { | 991 | if (status != USBD_NORMAL_COMPLETION) { | |
996 | if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) | 992 | if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) | |
997 | return; | 993 | return; | |
998 | sc->sc_rx_errs++; | 994 | sc->sc_rx_errs++; | |
999 | if (usbd_ratecheck(&sc->sc_rx_notice)) { | 995 | if (usbd_ratecheck(&sc->sc_rx_notice)) { | |
1000 | printf("%s: %u usb errors on rx: %s\n", | 996 | printf("%s: %u usb errors on rx: %s\n", | |
1001 | device_xname(sc->sc_dev), sc->sc_rx_errs, | 997 | device_xname(sc->sc_dev), sc->sc_rx_errs, | |
1002 | usbd_errstr(status)); | 998 | usbd_errstr(status)); | |
1003 | sc->sc_rx_errs = 0; | 999 | sc->sc_rx_errs = 0; | |
1004 | } | 1000 | } | |
1005 | if (status == USBD_STALLED) { | 1001 | if (status == USBD_STALLED) { | |
1006 | sc->sc_refcnt++; | 1002 | sc->sc_refcnt++; | |
1007 | usbd_clear_endpoint_stall_async(sc->sc_pipe_rx); | 1003 | usbd_clear_endpoint_stall_async(sc->sc_pipe_rx); | |
1008 | if (--sc->sc_refcnt < 0) | 1004 | if (--sc->sc_refcnt < 0) | |
1009 | usb_detach_wakeupold(sc->sc_dev); | 1005 | usb_detach_wakeupold(sc->sc_dev); | |
1010 | } | 1006 | } | |
1011 | goto done; | 1007 | goto done; | |
1012 | } | 1008 | } | |
1013 | 1009 | |||
1014 | usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); | 1010 | usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); | |
1015 | 1011 | |||
1016 | memcpy(mtod(c->url_mbuf, char *), c->url_buf, total_len); | 1012 | memcpy(mtod(c->url_mbuf, char *), c->url_buf, total_len); | |
1017 | 1013 | |||
1018 | if (total_len <= ETHER_CRC_LEN) { | 1014 | if (total_len <= ETHER_CRC_LEN) { | |
1019 | ifp->if_ierrors++; | 1015 | ifp->if_ierrors++; | |
1020 | goto done; | 1016 | goto done; | |
1021 | } | 1017 | } | |
1022 | 1018 | |||
1023 | memcpy(&rxhdr, c->url_buf + total_len - ETHER_CRC_LEN, sizeof(rxhdr)); | 1019 | memcpy(&rxhdr, c->url_buf + total_len - ETHER_CRC_LEN, sizeof(rxhdr)); | |
1024 | 1020 | |||
1025 | DPRINTF(("%s: RX Status: %dbytes%s%s%s%s packets\n", | 1021 | DPRINTF(("%s: RX Status: %dbytes%s%s%s%s packets\n", | |
1026 | device_xname(sc->sc_dev), | 1022 | device_xname(sc->sc_dev), | |
1027 | UGETW(rxhdr) & URL_RXHDR_BYTEC_MASK, | 1023 | UGETW(rxhdr) & URL_RXHDR_BYTEC_MASK, | |
1028 | UGETW(rxhdr) & URL_RXHDR_VALID_MASK ? ", Valid" : "", | 1024 | UGETW(rxhdr) & URL_RXHDR_VALID_MASK ? ", Valid" : "", | |
1029 | UGETW(rxhdr) & URL_RXHDR_RUNTPKT_MASK ? ", Runt" : "", | 1025 | UGETW(rxhdr) & URL_RXHDR_RUNTPKT_MASK ? ", Runt" : "", | |
1030 | UGETW(rxhdr) & URL_RXHDR_PHYPKT_MASK ? ", Physical match" : "", | 1026 | UGETW(rxhdr) & URL_RXHDR_PHYPKT_MASK ? ", Physical match" : "", | |
1031 | UGETW(rxhdr) & URL_RXHDR_MCASTPKT_MASK ? ", Multicast" : "")); | 1027 | UGETW(rxhdr) & URL_RXHDR_MCASTPKT_MASK ? ", Multicast" : "")); | |
1032 | 1028 | |||
1033 | if ((UGETW(rxhdr) & URL_RXHDR_VALID_MASK) == 0) { | 1029 | if ((UGETW(rxhdr) & URL_RXHDR_VALID_MASK) == 0) { | |
1034 | ifp->if_ierrors++; | 1030 | ifp->if_ierrors++; | |
1035 | goto done; | 1031 | goto done; | |
1036 | } | 1032 | } | |
1037 | 1033 | |||
1038 | ifp->if_ipackets++; | 1034 | ifp->if_ipackets++; | |
1039 | total_len -= ETHER_CRC_LEN; | 1035 | total_len -= ETHER_CRC_LEN; | |
1040 | 1036 | |||
1041 | m = c->url_mbuf; | 1037 | m = c->url_mbuf; | |
1042 | m->m_pkthdr.len = m->m_len = total_len; | 1038 | m->m_pkthdr.len = m->m_len = total_len; | |
1043 | m_set_rcvif(m, ifp); | 1039 | m_set_rcvif(m, ifp); | |
1044 | 1040 | |||
1045 | s = splnet(); | 1041 | s = splnet(); | |
1046 | 1042 | |||
1047 | if (url_newbuf(sc, c, NULL) == ENOBUFS) { | 1043 | if (url_newbuf(sc, c, NULL) == ENOBUFS) { | |
1048 | ifp->if_ierrors++; | 1044 | ifp->if_ierrors++; | |
1049 | goto done1; | 1045 | goto done1; | |
1050 | } | 1046 | } | |
1051 | 1047 | |||
1052 | bpf_mtap(ifp, m); | 1048 | bpf_mtap(ifp, m); | |
1053 | 1049 | |||
1054 | DPRINTF(("%s: %s: deliver %d\n", device_xname(sc->sc_dev), | 1050 | DPRINTF(("%s: %s: deliver %d\n", device_xname(sc->sc_dev), | |
1055 | __func__, m->m_len)); | 1051 | __func__, m->m_len)); | |
1056 | if_percpuq_enqueue((ifp)->if_percpuq, (m)); | 1052 | if_percpuq_enqueue((ifp)->if_percpuq, (m)); | |
1057 | 1053 | |||
1058 | done1: | 1054 | done1: | |
1059 | splx(s); | 1055 | splx(s); | |
1060 | 1056 | |||
1061 | done: | 1057 | done: | |
1062 | /* Setup new transfer */ | 1058 | /* Setup new transfer */ | |
1063 | usbd_setup_xfer(xfer, c, c->url_buf, URL_BUFSZ, USBD_SHORT_XFER_OK, | 1059 | usbd_setup_xfer(xfer, c, c->url_buf, URL_BUFSZ, USBD_SHORT_XFER_OK, | |
1064 | USBD_NO_TIMEOUT, url_rxeof); | 1060 | USBD_NO_TIMEOUT, url_rxeof); | |
1065 | sc->sc_refcnt++; | 1061 | sc->sc_refcnt++; | |
1066 | usbd_transfer(xfer); | 1062 | usbd_transfer(xfer); | |
1067 | if (--sc->sc_refcnt < 0) | 1063 | if (--sc->sc_refcnt < 0) | |
1068 | usb_detach_wakeupold(sc->sc_dev); | 1064 | usb_detach_wakeupold(sc->sc_dev); | |
1069 | 1065 | |||
1070 | DPRINTF(("%s: %s: start rx\n", device_xname(sc->sc_dev), __func__)); | 1066 | DPRINTF(("%s: %s: start rx\n", device_xname(sc->sc_dev), __func__)); | |
1071 | } | 1067 | } | |
1072 | 1068 | |||
1073 | #if 0 | 1069 | #if 0 | |
1074 | Static void url_intr(void) | 1070 | Static void url_intr(void) | |
1075 | { | 1071 | { | |
1076 | } | 1072 | } | |
1077 | #endif | 1073 | #endif | |
1078 | 1074 | |||
1079 | Static int | 1075 | Static int | |
1080 | url_ioctl(struct ifnet *ifp, u_long cmd, void *data) | 1076 | url_ioctl(struct ifnet *ifp, u_long cmd, void *data) | |
1081 | { | 1077 | { | |
1082 | struct url_softc *sc = ifp->if_softc; | 1078 | struct url_softc *sc = ifp->if_softc; | |
1083 | int s, error = 0; | 1079 | int s, error = 0; | |
1084 | 1080 | |||
1085 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 1081 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
1086 | 1082 | |||
1087 | if (sc->sc_dying) | 1083 | if (sc->sc_dying) | |
1088 | return EIO; | 1084 | return EIO; | |
1089 | 1085 | |||
1090 | s = splnet(); | 1086 | s = splnet(); | |
1091 | 1087 | |||
1092 | error = ether_ioctl(ifp, cmd, data); | 1088 | error = ether_ioctl(ifp, cmd, data); | |
1093 | if (error == ENETRESET) { | 1089 | if (error == ENETRESET) { | |
1094 | if (ifp->if_flags & IFF_RUNNING) | 1090 | if (ifp->if_flags & IFF_RUNNING) | |
1095 | url_setmulti(sc); | 1091 | url_setmulti(sc); | |
1096 | error = 0; | 1092 | error = 0; | |
1097 | } | 1093 | } | |
1098 | 1094 | |||
1099 | splx(s); | 1095 | splx(s); | |
1100 | 1096 | |||
1101 | return error; | 1097 | return error; | |
1102 | } | 1098 | } | |
1103 | 1099 | |||
1104 | Static void | 1100 | Static void | |
1105 | url_watchdog(struct ifnet *ifp) | 1101 | url_watchdog(struct ifnet *ifp) | |
1106 | { | 1102 | { | |
1107 | struct url_softc *sc = ifp->if_softc; | 1103 | struct url_softc *sc = ifp->if_softc; | |
1108 | struct url_chain *c; | 1104 | struct url_chain *c; | |
1109 | usbd_status stat; | 1105 | usbd_status stat; | |
1110 | int s; | 1106 | int s; | |
1111 | 1107 | |||
1112 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 1108 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
1113 | 1109 | |||
1114 | ifp->if_oerrors++; | 1110 | ifp->if_oerrors++; | |
1115 | printf("%s: watchdog timeout\n", device_xname(sc->sc_dev)); | 1111 | printf("%s: watchdog timeout\n", device_xname(sc->sc_dev)); | |
1116 | 1112 | |||
1117 | s = splusb(); | 1113 | s = splusb(); | |
1118 | c = &sc->sc_cdata.url_tx_chain[0]; | 1114 | c = &sc->sc_cdata.url_tx_chain[0]; | |
1119 | usbd_get_xfer_status(c->url_xfer, NULL, NULL, NULL, &stat); | 1115 | usbd_get_xfer_status(c->url_xfer, NULL, NULL, NULL, &stat); | |
1120 | url_txeof(c->url_xfer, c, stat); | 1116 | url_txeof(c->url_xfer, c, stat); | |
1121 | 1117 | |||
1122 | if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) | 1118 | if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) | |
1123 | url_start(ifp); | 1119 | url_start(ifp); | |
1124 | splx(s); | 1120 | splx(s); | |
1125 | } | 1121 | } | |
1126 | 1122 | |||
1127 | Static void | 1123 | Static void | |
1128 | url_stop_task(struct url_softc *sc) | 1124 | url_stop_task(struct url_softc *sc) | |
1129 | { | 1125 | { | |
1130 | url_stop(GET_IFP(sc), 1); | 1126 | url_stop(GET_IFP(sc), 1); | |
1131 | } | 1127 | } | |
1132 | 1128 | |||
1133 | /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ | 1129 | /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ | |
1134 | Static void | 1130 | Static void | |
1135 | url_stop(struct ifnet *ifp, int disable) | 1131 | url_stop(struct ifnet *ifp, int disable) | |
1136 | { | 1132 | { | |
1137 | struct url_softc *sc = ifp->if_softc; | 1133 | struct url_softc *sc = ifp->if_softc; | |
1138 | usbd_status err; | 1134 | usbd_status err; | |
1139 | int i; | 1135 | int i; | |
1140 | 1136 | |||
1141 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 1137 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
1142 | 1138 | |||
1143 | ifp->if_timer = 0; | 1139 | ifp->if_timer = 0; | |
1144 | 1140 | |||
1145 | url_reset(sc); | 1141 | url_reset(sc); | |
1146 | 1142 | |||
1147 | callout_stop(&sc->sc_stat_ch); | 1143 | callout_stop(&sc->sc_stat_ch); | |
1148 | 1144 | |||
1149 | /* Stop transfers */ | 1145 | /* Stop transfers */ | |
1150 | /* RX endpoint */ | 1146 | /* RX endpoint */ | |
1151 | if (sc->sc_pipe_rx != NULL) { | 1147 | if (sc->sc_pipe_rx != NULL) { | |
1152 | err = usbd_abort_pipe(sc->sc_pipe_rx); | 1148 | err = usbd_abort_pipe(sc->sc_pipe_rx); | |
1153 | if (err) | 1149 | if (err) | |
1154 | printf("%s: abort rx pipe failed: %s\n", | 1150 | printf("%s: abort rx pipe failed: %s\n", | |
1155 | device_xname(sc->sc_dev), usbd_errstr(err)); | 1151 | device_xname(sc->sc_dev), usbd_errstr(err)); | |
1156 | } | 1152 | } | |
1157 | 1153 | |||
1158 | /* TX endpoint */ | 1154 | /* TX endpoint */ | |
1159 | if (sc->sc_pipe_tx != NULL) { | 1155 | if (sc->sc_pipe_tx != NULL) { | |
1160 | err = usbd_abort_pipe(sc->sc_pipe_tx); | 1156 | err = usbd_abort_pipe(sc->sc_pipe_tx); | |
1161 | if (err) | 1157 | if (err) | |
1162 | printf("%s: abort tx pipe failed: %s\n", | 1158 | printf("%s: abort tx pipe failed: %s\n", | |
1163 | device_xname(sc->sc_dev), usbd_errstr(err)); | 1159 | device_xname(sc->sc_dev), usbd_errstr(err)); | |
1164 | } | 1160 | } | |
1165 | 1161 | |||
1166 | #if 0 | 1162 | #if 0 | |
1167 | /* XXX: Interrupt endpoint is not yet supported!! */ | 1163 | /* XXX: Interrupt endpoint is not yet supported!! */ | |
1168 | /* Interrupt endpoint */ | 1164 | /* Interrupt endpoint */ | |
1169 | if (sc->sc_pipe_intr != NULL) { | 1165 | if (sc->sc_pipe_intr != NULL) { | |
1170 | err = usbd_abort_pipe(sc->sc_pipe_intr); | 1166 | err = usbd_abort_pipe(sc->sc_pipe_intr); | |
1171 | if (err) | 1167 | if (err) | |
1172 | printf("%s: abort intr pipe failed: %s\n", | 1168 | printf("%s: abort intr pipe failed: %s\n", | |
1173 | device_xname(sc->sc_dev), usbd_errstr(err)); | 1169 | device_xname(sc->sc_dev), usbd_errstr(err)); | |
1174 | err = usbd_close_pipe(sc->sc_pipe_intr); | 1170 | err = usbd_close_pipe(sc->sc_pipe_intr); | |
1175 | if (err) | 1171 | if (err) | |
1176 | printf("%s: close intr pipe failed: %s\n", | 1172 | printf("%s: close intr pipe failed: %s\n", | |
1177 | device_xname(sc->sc_dev), usbd_errstr(err)); | 1173 | device_xname(sc->sc_dev), usbd_errstr(err)); | |
1178 | sc->sc_pipe_intr = NULL; | 1174 | sc->sc_pipe_intr = NULL; | |
1179 | } | 1175 | } | |
1180 | #endif | 1176 | #endif | |
1181 | 1177 | |||
1182 | /* Free RX resources. */ | 1178 | /* Free RX resources. */ | |
1183 | for (i = 0; i < URL_RX_LIST_CNT; i++) { | 1179 | for (i = 0; i < URL_RX_LIST_CNT; i++) { | |
1184 | if (sc->sc_cdata.url_rx_chain[i].url_mbuf != NULL) { | 1180 | if (sc->sc_cdata.url_rx_chain[i].url_mbuf != NULL) { | |
1185 | m_freem(sc->sc_cdata.url_rx_chain[i].url_mbuf); | 1181 | m_freem(sc->sc_cdata.url_rx_chain[i].url_mbuf); | |
1186 | sc->sc_cdata.url_rx_chain[i].url_mbuf = NULL; | 1182 | sc->sc_cdata.url_rx_chain[i].url_mbuf = NULL; | |
1187 | } | 1183 | } | |
1188 | if (sc->sc_cdata.url_rx_chain[i].url_xfer != NULL) { | 1184 | if (sc->sc_cdata.url_rx_chain[i].url_xfer != NULL) { | |
1189 | usbd_destroy_xfer(sc->sc_cdata.url_rx_chain[i].url_xfer); | 1185 | usbd_destroy_xfer(sc->sc_cdata.url_rx_chain[i].url_xfer); | |
1190 | sc->sc_cdata.url_rx_chain[i].url_xfer = NULL; | 1186 | sc->sc_cdata.url_rx_chain[i].url_xfer = NULL; | |
1191 | } | 1187 | } | |
1192 | } | 1188 | } | |
1193 | 1189 | |||
1194 | /* Free TX resources. */ | 1190 | /* Free TX resources. */ | |
1195 | for (i = 0; i < URL_TX_LIST_CNT; i++) { | 1191 | for (i = 0; i < URL_TX_LIST_CNT; i++) { | |
1196 | if (sc->sc_cdata.url_tx_chain[i].url_mbuf != NULL) { | 1192 | if (sc->sc_cdata.url_tx_chain[i].url_mbuf != NULL) { | |
1197 | m_freem(sc->sc_cdata.url_tx_chain[i].url_mbuf); | 1193 | m_freem(sc->sc_cdata.url_tx_chain[i].url_mbuf); | |
1198 | sc->sc_cdata.url_tx_chain[i].url_mbuf = NULL; | 1194 | sc->sc_cdata.url_tx_chain[i].url_mbuf = NULL; | |
1199 | } | 1195 | } | |
1200 | if (sc->sc_cdata.url_tx_chain[i].url_xfer != NULL) { | 1196 | if (sc->sc_cdata.url_tx_chain[i].url_xfer != NULL) { | |
1201 | usbd_destroy_xfer(sc->sc_cdata.url_tx_chain[i].url_xfer); | 1197 | usbd_destroy_xfer(sc->sc_cdata.url_tx_chain[i].url_xfer); | |
1202 | sc->sc_cdata.url_tx_chain[i].url_xfer = NULL; | 1198 | sc->sc_cdata.url_tx_chain[i].url_xfer = NULL; | |
1203 | } | 1199 | } | |
1204 | } | 1200 | } | |
1205 | 1201 | |||
1206 | /* Close pipes */ | 1202 | /* Close pipes */ | |
1207 | /* RX endpoint */ | 1203 | /* RX endpoint */ | |
1208 | if (sc->sc_pipe_rx != NULL) { | 1204 | if (sc->sc_pipe_rx != NULL) { | |
1209 | err = usbd_close_pipe(sc->sc_pipe_rx); | 1205 | err = usbd_close_pipe(sc->sc_pipe_rx); | |
1210 | if (err) | 1206 | if (err) | |
1211 | printf("%s: close rx pipe failed: %s\n", | 1207 | printf("%s: close rx pipe failed: %s\n", | |
1212 | device_xname(sc->sc_dev), usbd_errstr(err)); | 1208 | device_xname(sc->sc_dev), usbd_errstr(err)); | |
1213 | sc->sc_pipe_rx = NULL; | 1209 | sc->sc_pipe_rx = NULL; | |
1214 | } | 1210 | } | |
1215 | 1211 | |||
1216 | /* TX endpoint */ | 1212 | /* TX endpoint */ | |
1217 | if (sc->sc_pipe_tx != NULL) { | 1213 | if (sc->sc_pipe_tx != NULL) { | |
1218 | err = usbd_close_pipe(sc->sc_pipe_tx); | 1214 | err = usbd_close_pipe(sc->sc_pipe_tx); | |
1219 | if (err) | 1215 | if (err) | |
1220 | printf("%s: close tx pipe failed: %s\n", | 1216 | printf("%s: close tx pipe failed: %s\n", | |
1221 | device_xname(sc->sc_dev), usbd_errstr(err)); | 1217 | device_xname(sc->sc_dev), usbd_errstr(err)); | |
1222 | sc->sc_pipe_tx = NULL; | 1218 | sc->sc_pipe_tx = NULL; | |
1223 | } | 1219 | } | |
1224 | 1220 | |||
1225 | sc->sc_link = 0; | 1221 | sc->sc_link = 0; | |
1226 | ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); | 1222 | ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); | |
1227 | } | 1223 | } | |
1228 | 1224 | |||
1229 | /* Set media options */ | 1225 | /* Set media options */ | |
1230 | Static int | 1226 | Static int | |
1231 | url_ifmedia_change(struct ifnet *ifp) | 1227 | url_ifmedia_change(struct ifnet *ifp) | |
1232 | { | 1228 | { | |
1233 | struct url_softc *sc = ifp->if_softc; | 1229 | struct url_softc *sc = ifp->if_softc; | |
1234 | struct mii_data *mii = GET_MII(sc); | 1230 | struct mii_data *mii = GET_MII(sc); | |
1235 | int rc; | 1231 | int rc; | |
1236 | 1232 | |||
1237 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 1233 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
1238 | 1234 | |||
1239 | if (sc->sc_dying) | 1235 | if (sc->sc_dying) | |
1240 | return 0; | 1236 | return 0; | |
1241 | 1237 | |||
1242 | sc->sc_link = 0; | 1238 | sc->sc_link = 0; | |
1243 | if ((rc = mii_mediachg(mii)) == ENXIO) | 1239 | if ((rc = mii_mediachg(mii)) == ENXIO) | |
1244 | return 0; | 1240 | return 0; | |
1245 | return rc; | 1241 | return rc; | |
1246 | } | 1242 | } | |
1247 | 1243 | |||
1248 | /* Report current media status. */ | 1244 | /* Report current media status. */ | |
1249 | Static void | 1245 | Static void | |
1250 | url_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr) | 1246 | url_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr) | |
1251 | { | 1247 | { | |
1252 | struct url_softc *sc = ifp->if_softc; | 1248 | struct url_softc *sc = ifp->if_softc; | |
1253 | 1249 | |||
1254 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | 1250 | DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); | |
1255 | 1251 | |||
1256 | if (sc->sc_dying) | 1252 | if (sc->sc_dying) | |
1257 | return; | 1253 | return; | |
1258 | 1254 | |||
1259 | ether_mediastatus(ifp, ifmr); | 1255 | ether_mediastatus(ifp, ifmr); | |
1260 | } | 1256 | } | |
1261 | 1257 | |||
1262 | Static void | 1258 | Static void | |
1263 | url_tick(void *xsc) | 1259 | url_tick(void *xsc) | |
1264 | { | 1260 | { | |
1265 | struct url_softc *sc = xsc; | 1261 | struct url_softc *sc = xsc; | |
1266 | 1262 | |||
1267 | if (sc == NULL) | 1263 | if (sc == NULL) | |
1268 | return; | 1264 | return; | |
1269 | 1265 | |||
1270 | DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev), | 1266 | DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev), | |
1271 | __func__)); | 1267 | __func__)); | |
1272 | 1268 | |||
1273 | if (sc->sc_dying) | 1269 | if (sc->sc_dying) | |
1274 | return; | 1270 | return; | |
1275 | 1271 | |||
1276 | /* Perform periodic stuff in process context */ | 1272 | /* Perform periodic stuff in process context */ | |
1277 | usb_add_task(sc->sc_udev, &sc->sc_tick_task, USB_TASKQ_DRIVER); | 1273 | usb_add_task(sc->sc_udev, &sc->sc_tick_task, USB_TASKQ_DRIVER); | |
1278 | } | 1274 | } | |
1279 | 1275 | |||
1280 | Static void | 1276 | Static void | |
1281 | url_tick_task(void *xsc) | 1277 | url_tick_task(void *xsc) | |
1282 | { | 1278 | { | |
1283 | struct url_softc *sc = xsc; | 1279 | struct url_softc *sc = xsc; | |
1284 | struct ifnet *ifp; | 1280 | struct ifnet *ifp; | |
1285 | struct mii_data *mii; | 1281 | struct mii_data *mii; | |
1286 | int s; | 1282 | int s; | |
1287 | 1283 | |||
1288 | if (sc == NULL) | 1284 | if (sc == NULL) | |
1289 | return; | 1285 | return; | |
1290 | 1286 | |||
1291 | DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev), | 1287 | DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev), | |
1292 | __func__)); | 1288 | __func__)); | |
1293 | 1289 | |||
1294 | if (sc->sc_dying) | 1290 | if (sc->sc_dying) | |
1295 | return; | 1291 | return; | |
1296 | 1292 | |||
1297 | ifp = GET_IFP(sc); | 1293 | ifp = GET_IFP(sc); | |
1298 | mii = GET_MII(sc); | 1294 | mii = GET_MII(sc); | |
1299 | 1295 | |||
1300 | if (mii == NULL) | 1296 | if (mii == NULL) | |
1301 | return; | 1297 | return; | |
1302 | 1298 | |||
1303 | s = splnet(); | 1299 | s = splnet(); | |
1304 | 1300 | |||
1305 | mii_tick(mii); | 1301 | mii_tick(mii); | |
1306 | if (!sc->sc_link) { | 1302 | if (!sc->sc_link) { | |
1307 | mii_pollstat(mii); | 1303 | mii_pollstat(mii); | |
1308 | if (mii->mii_media_status & IFM_ACTIVE && | 1304 | if (mii->mii_media_status & IFM_ACTIVE && | |
1309 | IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { | 1305 | IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { | |
1310 | DPRINTF(("%s: %s: got link\n", | 1306 | DPRINTF(("%s: %s: got link\n", | |
1311 | device_xname(sc->sc_dev), __func__)); | 1307 | device_xname(sc->sc_dev), __func__)); | |
1312 | sc->sc_link++; | 1308 | sc->sc_link++; | |
1313 | if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) | 1309 | if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) | |
1314 | url_start(ifp); | 1310 | url_start(ifp); | |
1315 | } | 1311 | } | |
1316 | } | 1312 | } | |
1317 | 1313 | |||
1318 | callout_reset(&sc->sc_stat_ch, hz, url_tick, sc); | 1314 | callout_reset(&sc->sc_stat_ch, hz, url_tick, sc); | |
1319 | 1315 | |||
1320 | splx(s); | 1316 | splx(s); | |
1321 | } | 1317 | } | |
1322 | 1318 | |||
1323 | /* Get exclusive access to the MII registers */ | 1319 | /* Get exclusive access to the MII registers */ |
--- src/sys/dev/usb/if_urndis.c 2016/12/29 08:04:08 1.9.4.14
+++ src/sys/dev/usb/if_urndis.c 2017/01/26 12:40:16 1.9.4.15
@@ -1,1597 +1,1597 @@ | @@ -1,1597 +1,1597 @@ | |||
1 | /* $NetBSD: if_urndis.c,v 1.9.4.14 2016/12/29 08:04:08 skrll Exp $ */ | 1 | /* $NetBSD: if_urndis.c,v 1.9.4.15 2017/01/26 12:40:16 skrll Exp $ */ | |
2 | /* $OpenBSD: if_urndis.c,v 1.31 2011/07/03 15:47:17 matthew Exp $ */ | 2 | /* $OpenBSD: if_urndis.c,v 1.31 2011/07/03 15:47:17 matthew Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 2010 Jonathan Armani <armani@openbsd.org> | 5 | * Copyright (c) 2010 Jonathan Armani <armani@openbsd.org> | |
6 | * Copyright (c) 2010 Fabien Romano <fabien@openbsd.org> | 6 | * Copyright (c) 2010 Fabien Romano <fabien@openbsd.org> | |
7 | * Copyright (c) 2010 Michael Knudsen <mk@openbsd.org> | 7 | * Copyright (c) 2010 Michael Knudsen <mk@openbsd.org> | |
8 | * All rights reserved. | 8 | * All rights reserved. | |
9 | * | 9 | * | |
10 | * Permission to use, copy, modify, and distribute this software for any | 10 | * Permission to use, copy, modify, and distribute this software for any | |
11 | * purpose with or without fee is hereby granted, provided that the above | 11 | * purpose with or without fee is hereby granted, provided that the above | |
12 | * copyright notice and this permission notice appear in all copies. | 12 | * copyright notice and this permission notice appear in all copies. | |
13 | * | 13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 14 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
15 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 15 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
16 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 16 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
17 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 17 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
18 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 18 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
19 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 19 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
20 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 20 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
21 | */ | 21 | */ | |
22 | 22 | |||
23 | #include <sys/cdefs.h> | 23 | #include <sys/cdefs.h> | |
24 | __KERNEL_RCSID(0, "$NetBSD: if_urndis.c,v 1.9.4.14 2016/12/29 08:04:08 skrll Exp $"); | 24 | __KERNEL_RCSID(0, "$NetBSD: if_urndis.c,v 1.9.4.15 2017/01/26 12:40:16 skrll Exp $"); | |
25 | 25 | |||
26 | #ifdef _KERNEL_OPT | 26 | #ifdef _KERNEL_OPT | |
27 | #include "opt_usb.h" | 27 | #include "opt_usb.h" | |
28 | #endif | 28 | #endif | |
29 | 29 | |||
30 | #include <sys/param.h> | 30 | #include <sys/param.h> | |
31 | #include <sys/systm.h> | 31 | #include <sys/systm.h> | |
32 | #include <sys/sockio.h> | 32 | #include <sys/sockio.h> | |
33 | #include <sys/rwlock.h> | 33 | #include <sys/rwlock.h> | |
34 | #include <sys/mbuf.h> | 34 | #include <sys/mbuf.h> | |
35 | #include <sys/kmem.h> | 35 | #include <sys/kmem.h> | |
36 | #include <sys/kernel.h> | 36 | #include <sys/kernel.h> | |
37 | #include <sys/proc.h> | 37 | #include <sys/proc.h> | |
38 | #include <sys/socket.h> | 38 | #include <sys/socket.h> | |
39 | #include <sys/device.h> | 39 | #include <sys/device.h> | |
40 | 40 | |||
41 | #include <net/if.h> | 41 | #include <net/if.h> | |
42 | #include <net/if_dl.h> | 42 | #include <net/if_dl.h> | |
43 | #include <net/if_media.h> | 43 | #include <net/if_media.h> | |
44 | #include <net/if_ether.h> | 44 | #include <net/if_ether.h> | |
45 | 45 | |||
46 | #include <net/bpf.h> | 46 | #include <net/bpf.h> | |
47 | 47 | |||
48 | #include <sys/bus.h> | 48 | #include <sys/bus.h> | |
49 | #include <dev/usb/usb.h> | 49 | #include <dev/usb/usb.h> | |
50 | #include <dev/usb/usbdi.h> | 50 | #include <dev/usb/usbdi.h> | |
51 | #include <dev/usb/usbdi_util.h> | 51 | #include <dev/usb/usbdi_util.h> | |
52 | #include <dev/usb/usbdivar.h> | 52 | #include <dev/usb/usbdivar.h> | |
53 | #include <dev/usb/usbdevs.h> | 53 | #include <dev/usb/usbdevs.h> | |
54 | #include <dev/usb/usbcdc.h> | 54 | #include <dev/usb/usbcdc.h> | |
55 | 55 | |||
56 | #include <dev/usb/if_urndisreg.h> | 56 | #include <dev/usb/if_urndisreg.h> | |
57 | 57 | |||
58 | #ifdef URNDIS_DEBUG | 58 | #ifdef URNDIS_DEBUG | |
59 | #define DPRINTF(x) do { printf x; } while (0) | 59 | #define DPRINTF(x) do { printf x; } while (0) | |
60 | #else | 60 | #else | |
61 | #define DPRINTF(x) | 61 | #define DPRINTF(x) | |
62 | #endif | 62 | #endif | |
63 | 63 | |||
64 | #define DEVNAME(sc) (device_xname(sc->sc_dev)) | 64 | #define DEVNAME(sc) (device_xname(sc->sc_dev)) | |
65 | 65 | |||
66 | #define ETHER_ALIGN 2 | 66 | #define ETHER_ALIGN 2 | |
67 | #define URNDIS_RESPONSE_LEN 0x400 | 67 | #define URNDIS_RESPONSE_LEN 0x400 | |
68 | 68 | |||
69 | 69 | |||
70 | static int urndis_newbuf(struct urndis_softc *, struct urndis_chain *); | 70 | static int urndis_newbuf(struct urndis_softc *, struct urndis_chain *); | |
71 | 71 | |||
72 | static int urndis_ioctl(struct ifnet *, unsigned long, void *); | 72 | static int urndis_ioctl(struct ifnet *, unsigned long, void *); | |
73 | #if 0 | 73 | #if 0 | |
74 | static void urndis_watchdog(struct ifnet *); | 74 | static void urndis_watchdog(struct ifnet *); | |
75 | #endif | 75 | #endif | |
76 | 76 | |||
77 | static void urndis_start(struct ifnet *); | 77 | static void urndis_start(struct ifnet *); | |
78 | static void urndis_start_locked(struct ifnet *); | 78 | static void urndis_start_locked(struct ifnet *); | |
79 | static void urndis_rxeof(struct usbd_xfer *, void *, usbd_status); | 79 | static void urndis_rxeof(struct usbd_xfer *, void *, usbd_status); | |
80 | static void urndis_txeof(struct usbd_xfer *, void *, usbd_status); | 80 | static void urndis_txeof(struct usbd_xfer *, void *, usbd_status); | |
81 | static int urndis_rx_list_init(struct urndis_softc *); | 81 | static int urndis_rx_list_init(struct urndis_softc *); | |
82 | static void urndis_rx_list_free(struct urndis_softc *); | 82 | static void urndis_rx_list_free(struct urndis_softc *); | |
83 | static int urndis_tx_list_init(struct urndis_softc *); | 83 | static int urndis_tx_list_init(struct urndis_softc *); | |
84 | static void urndis_tx_list_free(struct urndis_softc *); | 84 | static void urndis_tx_list_free(struct urndis_softc *); | |
85 | 85 | |||
86 | static int urndis_init(struct ifnet *); | 86 | static int urndis_init(struct ifnet *); | |
87 | static int urndis_init_locked(struct ifnet *); | 87 | static int urndis_init_locked(struct ifnet *); | |
88 | static void urndis_stop(struct ifnet *); | 88 | static void urndis_stop(struct ifnet *); | |
89 | static void urndis_stop_locked(struct ifnet *); | 89 | static void urndis_stop_locked(struct ifnet *); | |
90 | 90 | |||
91 | static usbd_status urndis_ctrl_msg(struct urndis_softc *, uint8_t, uint8_t, | 91 | static usbd_status urndis_ctrl_msg(struct urndis_softc *, uint8_t, uint8_t, | |
92 | uint16_t, uint16_t, void *, size_t); | 92 | uint16_t, uint16_t, void *, size_t); | |
93 | static usbd_status urndis_ctrl_send(struct urndis_softc *, void *, size_t); | 93 | static usbd_status urndis_ctrl_send(struct urndis_softc *, void *, size_t); | |
94 | static struct urndis_comp_hdr *urndis_ctrl_recv(struct urndis_softc *); | 94 | static struct urndis_comp_hdr *urndis_ctrl_recv(struct urndis_softc *); | |
95 | 95 | |||
96 | static uint32_t urndis_ctrl_handle(struct urndis_softc *, | 96 | static uint32_t urndis_ctrl_handle(struct urndis_softc *, | |
97 | struct urndis_comp_hdr *, void **, size_t *); | 97 | struct urndis_comp_hdr *, void **, size_t *); | |
98 | static uint32_t urndis_ctrl_handle_init(struct urndis_softc *, | 98 | static uint32_t urndis_ctrl_handle_init(struct urndis_softc *, | |
99 | const struct urndis_comp_hdr *); | 99 | const struct urndis_comp_hdr *); | |
100 | static uint32_t urndis_ctrl_handle_query(struct urndis_softc *, | 100 | static uint32_t urndis_ctrl_handle_query(struct urndis_softc *, | |
101 | const struct urndis_comp_hdr *, void **, size_t *); | 101 | const struct urndis_comp_hdr *, void **, size_t *); | |
102 | static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *, | 102 | static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *, | |
103 | const struct urndis_comp_hdr *); | 103 | const struct urndis_comp_hdr *); | |
104 | 104 | |||
105 | static uint32_t urndis_ctrl_init(struct urndis_softc *); | 105 | static uint32_t urndis_ctrl_init(struct urndis_softc *); | |
106 | #if 0 | 106 | #if 0 | |
107 | static uint32_t urndis_ctrl_halt(struct urndis_softc *); | 107 | static uint32_t urndis_ctrl_halt(struct urndis_softc *); | |
108 | #endif | 108 | #endif | |
109 | static uint32_t urndis_ctrl_query(struct urndis_softc *, uint32_t, void *, | 109 | static uint32_t urndis_ctrl_query(struct urndis_softc *, uint32_t, void *, | |
110 | size_t, void **, size_t *); | 110 | size_t, void **, size_t *); | |
111 | static uint32_t urndis_ctrl_set(struct urndis_softc *, uint32_t, void *, | 111 | static uint32_t urndis_ctrl_set(struct urndis_softc *, uint32_t, void *, | |
112 | size_t); | 112 | size_t); | |
113 | #if 0 | 113 | #if 0 | |
114 | static uint32_t urndis_ctrl_set_param(struct urndis_softc *, const char *, | 114 | static uint32_t urndis_ctrl_set_param(struct urndis_softc *, const char *, | |
115 | uint32_t, void *, size_t); | 115 | uint32_t, void *, size_t); | |
116 | static uint32_t urndis_ctrl_reset(struct urndis_softc *); | 116 | static uint32_t urndis_ctrl_reset(struct urndis_softc *); | |
117 | static uint32_t urndis_ctrl_keepalive(struct urndis_softc *); | 117 | static uint32_t urndis_ctrl_keepalive(struct urndis_softc *); | |
118 | #endif | 118 | #endif | |
119 | 119 | |||
120 | static int urndis_encap(struct urndis_softc *, struct mbuf *, int); | 120 | static int urndis_encap(struct urndis_softc *, struct mbuf *, int); | |
121 | static void urndis_decap(struct urndis_softc *, struct urndis_chain *, | 121 | static void urndis_decap(struct urndis_softc *, struct urndis_chain *, | |
122 | uint32_t); | 122 | uint32_t); | |
123 | 123 | |||
124 | static int urndis_match(device_t, cfdata_t, void *); | 124 | static int urndis_match(device_t, cfdata_t, void *); | |
125 | static void urndis_attach(device_t, device_t, void *); | 125 | static void urndis_attach(device_t, device_t, void *); | |
126 | static int urndis_detach(device_t, int); | 126 | static int urndis_detach(device_t, int); | |
127 | static int urndis_activate(device_t, enum devact); | 127 | static int urndis_activate(device_t, enum devact); | |
128 | 128 | |||
129 | CFATTACH_DECL_NEW(urndis, sizeof(struct urndis_softc), | 129 | CFATTACH_DECL_NEW(urndis, sizeof(struct urndis_softc), | |
130 | urndis_match, urndis_attach, urndis_detach, urndis_activate); | 130 | urndis_match, urndis_attach, urndis_detach, urndis_activate); | |
131 | 131 | |||
132 | /* | 132 | /* | |
133 | * Supported devices that we can't match by class IDs. | 133 | * Supported devices that we can't match by class IDs. | |
134 | */ | 134 | */ | |
135 | static const struct usb_devno urndis_devs[] = { | 135 | static const struct usb_devno urndis_devs[] = { | |
136 | { USB_VENDOR_HTC, USB_PRODUCT_HTC_ANDROID }, | 136 | { USB_VENDOR_HTC, USB_PRODUCT_HTC_ANDROID }, | |
137 | { USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_ANDROID2 }, | 137 | { USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_ANDROID2 }, | |
138 | }; | 138 | }; | |
139 | 139 | |||
140 | static usbd_status | 140 | static usbd_status | |
141 | urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r, | 141 | urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r, | |
142 | uint16_t index, uint16_t value, void *buf, size_t buflen) | 142 | uint16_t index, uint16_t value, void *buf, size_t buflen) | |
143 | { | 143 | { | |
144 | usb_device_request_t req; | 144 | usb_device_request_t req; | |
145 | 145 | |||
146 | req.bmRequestType = rt; | 146 | req.bmRequestType = rt; | |
147 | req.bRequest = r; | 147 | req.bRequest = r; | |
148 | USETW(req.wValue, value); | 148 | USETW(req.wValue, value); | |
149 | USETW(req.wIndex, index); | 149 | USETW(req.wIndex, index); | |
150 | USETW(req.wLength, buflen); | 150 | USETW(req.wLength, buflen); | |
151 | 151 | |||
152 | return usbd_do_request(sc->sc_udev, &req, buf); | 152 | return usbd_do_request(sc->sc_udev, &req, buf); | |
153 | } | 153 | } | |
154 | 154 | |||
155 | static usbd_status | 155 | static usbd_status | |
156 | urndis_ctrl_send(struct urndis_softc *sc, void *buf, size_t len) | 156 | urndis_ctrl_send(struct urndis_softc *sc, void *buf, size_t len) | |
157 | { | 157 | { | |
158 | usbd_status err; | 158 | usbd_status err; | |
159 | 159 | |||
160 | if (sc->sc_dying) | 160 | if (sc->sc_dying) | |
161 | return(0); | 161 | return(0); | |
162 | 162 | |||
163 | err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS, | 163 | err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS, | |
164 | sc->sc_ifaceno_ctl, 0, buf, len); | 164 | sc->sc_ifaceno_ctl, 0, buf, len); | |
165 | 165 | |||
166 | if (err != USBD_NORMAL_COMPLETION) | 166 | if (err != USBD_NORMAL_COMPLETION) | |
167 | printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err)); | 167 | printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err)); | |
168 | 168 | |||
169 | return err; | 169 | return err; | |
170 | } | 170 | } | |
171 | 171 | |||
172 | static struct urndis_comp_hdr * | 172 | static struct urndis_comp_hdr * | |
173 | urndis_ctrl_recv(struct urndis_softc *sc) | 173 | urndis_ctrl_recv(struct urndis_softc *sc) | |
174 | { | 174 | { | |
175 | struct urndis_comp_hdr *hdr; | 175 | struct urndis_comp_hdr *hdr; | |
176 | char *buf; | 176 | char *buf; | |
177 | usbd_status err; | 177 | usbd_status err; | |
178 | 178 | |||
179 | buf = kmem_alloc(URNDIS_RESPONSE_LEN, KM_SLEEP); | 179 | buf = kmem_alloc(URNDIS_RESPONSE_LEN, KM_SLEEP); | |
180 | if (buf == NULL) { | 180 | if (buf == NULL) { | |
181 | printf("%s: out of memory\n", DEVNAME(sc)); | 181 | printf("%s: out of memory\n", DEVNAME(sc)); | |
182 | return NULL; | 182 | return NULL; | |
183 | } | 183 | } | |
184 | 184 | |||
185 | err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE, | 185 | err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE, | |
186 | sc->sc_ifaceno_ctl, 0, buf, URNDIS_RESPONSE_LEN); | 186 | sc->sc_ifaceno_ctl, 0, buf, URNDIS_RESPONSE_LEN); | |
187 | 187 | |||
188 | if (err != USBD_NORMAL_COMPLETION && err != USBD_SHORT_XFER) { | 188 | if (err != USBD_NORMAL_COMPLETION && err != USBD_SHORT_XFER) { | |
189 | printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err)); | 189 | printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err)); | |
190 | kmem_free(buf, URNDIS_RESPONSE_LEN); | 190 | kmem_free(buf, URNDIS_RESPONSE_LEN); | |
191 | return NULL; | 191 | return NULL; | |
192 | } | 192 | } | |
193 | 193 | |||
194 | hdr = (struct urndis_comp_hdr *)buf; | 194 | hdr = (struct urndis_comp_hdr *)buf; | |
195 | DPRINTF(("%s: urndis_ctrl_recv: type 0x%x len %u\n", | 195 | DPRINTF(("%s: urndis_ctrl_recv: type 0x%x len %u\n", | |
196 | DEVNAME(sc), | 196 | DEVNAME(sc), | |
197 | le32toh(hdr->rm_type), | 197 | le32toh(hdr->rm_type), | |
198 | le32toh(hdr->rm_len))); | 198 | le32toh(hdr->rm_len))); | |
199 | 199 | |||
200 | if (le32toh(hdr->rm_len) > URNDIS_RESPONSE_LEN) { | 200 | if (le32toh(hdr->rm_len) > URNDIS_RESPONSE_LEN) { | |
201 | printf("%s: ctrl message error: wrong size %u > %u\n", | 201 | printf("%s: ctrl message error: wrong size %u > %u\n", | |
202 | DEVNAME(sc), | 202 | DEVNAME(sc), | |
203 | le32toh(hdr->rm_len), | 203 | le32toh(hdr->rm_len), | |
204 | URNDIS_RESPONSE_LEN); | 204 | URNDIS_RESPONSE_LEN); | |
205 | kmem_free(buf, URNDIS_RESPONSE_LEN); | 205 | kmem_free(buf, URNDIS_RESPONSE_LEN); | |
206 | return NULL; | 206 | return NULL; | |
207 | } | 207 | } | |
208 | 208 | |||
209 | return hdr; | 209 | return hdr; | |
210 | } | 210 | } | |
211 | 211 | |||
212 | static uint32_t | 212 | static uint32_t | |
213 | urndis_ctrl_handle(struct urndis_softc *sc, struct urndis_comp_hdr *hdr, | 213 | urndis_ctrl_handle(struct urndis_softc *sc, struct urndis_comp_hdr *hdr, | |
214 | void **buf, size_t *bufsz) | 214 | void **buf, size_t *bufsz) | |
215 | { | 215 | { | |
216 | uint32_t rval; | 216 | uint32_t rval; | |
217 | 217 | |||
218 | DPRINTF(("%s: urndis_ctrl_handle\n", DEVNAME(sc))); | 218 | DPRINTF(("%s: urndis_ctrl_handle\n", DEVNAME(sc))); | |
219 | 219 | |||
220 | if (buf && bufsz) { | 220 | if (buf && bufsz) { | |
221 | *buf = NULL; | 221 | *buf = NULL; | |
222 | *bufsz = 0; | 222 | *bufsz = 0; | |
223 | } | 223 | } | |
224 | 224 | |||
225 | switch (le32toh(hdr->rm_type)) { | 225 | switch (le32toh(hdr->rm_type)) { | |
226 | case REMOTE_NDIS_INITIALIZE_CMPLT: | 226 | case REMOTE_NDIS_INITIALIZE_CMPLT: | |
227 | rval = urndis_ctrl_handle_init(sc, hdr); | 227 | rval = urndis_ctrl_handle_init(sc, hdr); | |
228 | break; | 228 | break; | |
229 | 229 | |||
230 | case REMOTE_NDIS_QUERY_CMPLT: | 230 | case REMOTE_NDIS_QUERY_CMPLT: | |
231 | rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz); | 231 | rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz); | |
232 | break; | 232 | break; | |
233 | 233 | |||
234 | case REMOTE_NDIS_RESET_CMPLT: | 234 | case REMOTE_NDIS_RESET_CMPLT: | |
235 | rval = urndis_ctrl_handle_reset(sc, hdr); | 235 | rval = urndis_ctrl_handle_reset(sc, hdr); | |
236 | break; | 236 | break; | |
237 | 237 | |||
238 | case REMOTE_NDIS_KEEPALIVE_CMPLT: | 238 | case REMOTE_NDIS_KEEPALIVE_CMPLT: | |
239 | case REMOTE_NDIS_SET_CMPLT: | 239 | case REMOTE_NDIS_SET_CMPLT: | |
240 | rval = le32toh(hdr->rm_status); | 240 | rval = le32toh(hdr->rm_status); | |
241 | break; | 241 | break; | |
242 | 242 | |||
243 | default: | 243 | default: | |
244 | printf("%s: ctrl message error: unknown event 0x%x\n", | 244 | printf("%s: ctrl message error: unknown event 0x%x\n", | |
245 | DEVNAME(sc), le32toh(hdr->rm_type)); | 245 | DEVNAME(sc), le32toh(hdr->rm_type)); | |
246 | rval = RNDIS_STATUS_FAILURE; | 246 | rval = RNDIS_STATUS_FAILURE; | |
247 | } | 247 | } | |
248 | 248 | |||
249 | kmem_free(hdr, URNDIS_RESPONSE_LEN); | 249 | kmem_free(hdr, URNDIS_RESPONSE_LEN); | |
250 | 250 | |||
251 | return rval; | 251 | return rval; | |
252 | } | 252 | } | |
253 | 253 | |||
254 | static uint32_t | 254 | static uint32_t | |
255 | urndis_ctrl_handle_init(struct urndis_softc *sc, | 255 | urndis_ctrl_handle_init(struct urndis_softc *sc, | |
256 | const struct urndis_comp_hdr *hdr) | 256 | const struct urndis_comp_hdr *hdr) | |
257 | { | 257 | { | |
258 | const struct urndis_init_comp *msg; | 258 | const struct urndis_init_comp *msg; | |
259 | 259 | |||
260 | msg = (const struct urndis_init_comp *) hdr; | 260 | msg = (const struct urndis_init_comp *) hdr; | |
261 | 261 | |||
262 | DPRINTF(("%s: urndis_ctrl_handle_init: len %u rid %u status 0x%x " | 262 | DPRINTF(("%s: urndis_ctrl_handle_init: len %u rid %u status 0x%x " | |
263 | "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u " | 263 | "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u " | |
264 | "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n", | 264 | "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n", | |
265 | DEVNAME(sc), | 265 | DEVNAME(sc), | |
266 | le32toh(msg->rm_len), | 266 | le32toh(msg->rm_len), | |
267 | le32toh(msg->rm_rid), | 267 | le32toh(msg->rm_rid), | |
268 | le32toh(msg->rm_status), | 268 | le32toh(msg->rm_status), | |
269 | le32toh(msg->rm_ver_major), | 269 | le32toh(msg->rm_ver_major), | |
270 | le32toh(msg->rm_ver_minor), | 270 | le32toh(msg->rm_ver_minor), | |
271 | le32toh(msg->rm_devflags), | 271 | le32toh(msg->rm_devflags), | |
272 | le32toh(msg->rm_medium), | 272 | le32toh(msg->rm_medium), | |
273 | le32toh(msg->rm_pktmaxcnt), | 273 | le32toh(msg->rm_pktmaxcnt), | |
274 | le32toh(msg->rm_pktmaxsz), | 274 | le32toh(msg->rm_pktmaxsz), | |
275 | le32toh(msg->rm_align), | 275 | le32toh(msg->rm_align), | |
276 | le32toh(msg->rm_aflistoffset), | 276 | le32toh(msg->rm_aflistoffset), | |
277 | le32toh(msg->rm_aflistsz))); | 277 | le32toh(msg->rm_aflistsz))); | |
278 | 278 | |||
279 | if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) { | 279 | if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) { | |
280 | printf("%s: init failed 0x%x\n", | 280 | printf("%s: init failed 0x%x\n", | |
281 | DEVNAME(sc), | 281 | DEVNAME(sc), | |
282 | le32toh(msg->rm_status)); | 282 | le32toh(msg->rm_status)); | |
283 | 283 | |||
284 | return le32toh(msg->rm_status); | 284 | return le32toh(msg->rm_status); | |
285 | } | 285 | } | |
286 | 286 | |||
287 | if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) { | 287 | if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) { | |
288 | printf("%s: wrong device type (current type: 0x%x)\n", | 288 | printf("%s: wrong device type (current type: 0x%x)\n", | |
289 | DEVNAME(sc), | 289 | DEVNAME(sc), | |
290 | le32toh(msg->rm_devflags)); | 290 | le32toh(msg->rm_devflags)); | |
291 | 291 | |||
292 | return RNDIS_STATUS_FAILURE; | 292 | return RNDIS_STATUS_FAILURE; | |
293 | } | 293 | } | |
294 | 294 | |||
295 | if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) { | 295 | if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) { | |
296 | printf("%s: medium not 802.3 (current medium: 0x%x)\n", | 296 | printf("%s: medium not 802.3 (current medium: 0x%x)\n", | |
297 | DEVNAME(sc), le32toh(msg->rm_medium)); | 297 | DEVNAME(sc), le32toh(msg->rm_medium)); | |
298 | 298 | |||
299 | return RNDIS_STATUS_FAILURE; | 299 | return RNDIS_STATUS_FAILURE; | |
300 | } | 300 | } | |
301 | 301 | |||
302 | sc->sc_lim_pktsz = le32toh(msg->rm_pktmaxsz); | 302 | sc->sc_lim_pktsz = le32toh(msg->rm_pktmaxsz); | |
303 | 303 | |||
304 | return le32toh(msg->rm_status); | 304 | return le32toh(msg->rm_status); | |
305 | } | 305 | } | |
306 | 306 | |||
307 | static uint32_t | 307 | static uint32_t | |
308 | urndis_ctrl_handle_query(struct urndis_softc *sc, | 308 | urndis_ctrl_handle_query(struct urndis_softc *sc, | |
309 | const struct urndis_comp_hdr *hdr, void **buf, size_t *bufsz) | 309 | const struct urndis_comp_hdr *hdr, void **buf, size_t *bufsz) | |
310 | { | 310 | { | |
311 | const struct urndis_query_comp *msg; | 311 | const struct urndis_query_comp *msg; | |
312 | 312 | |||
313 | msg = (const struct urndis_query_comp *) hdr; | 313 | msg = (const struct urndis_query_comp *) hdr; | |
314 | 314 | |||
315 | DPRINTF(("%s: urndis_ctrl_handle_query: len %u rid %u status 0x%x " | 315 | DPRINTF(("%s: urndis_ctrl_handle_query: len %u rid %u status 0x%x " | |
316 | "buflen %u bufoff %u\n", | 316 | "buflen %u bufoff %u\n", | |
317 | DEVNAME(sc), | 317 | DEVNAME(sc), | |
318 | le32toh(msg->rm_len), | 318 | le32toh(msg->rm_len), | |
319 | le32toh(msg->rm_rid), | 319 | le32toh(msg->rm_rid), | |
320 | le32toh(msg->rm_status), | 320 | le32toh(msg->rm_status), | |
321 | le32toh(msg->rm_infobuflen), | 321 | le32toh(msg->rm_infobuflen), | |
322 | le32toh(msg->rm_infobufoffset))); | 322 | le32toh(msg->rm_infobufoffset))); | |
323 | 323 | |||
324 | if (buf && bufsz) { | 324 | if (buf && bufsz) { | |
325 | *buf = NULL; | 325 | *buf = NULL; | |
326 | *bufsz = 0; | 326 | *bufsz = 0; | |
327 | } | 327 | } | |
328 | 328 | |||
329 | if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) { | 329 | if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) { | |
330 | printf("%s: query failed 0x%x\n", | 330 | printf("%s: query failed 0x%x\n", | |
331 | DEVNAME(sc), | 331 | DEVNAME(sc), | |
332 | le32toh(msg->rm_status)); | 332 | le32toh(msg->rm_status)); | |
333 | 333 | |||
334 | return le32toh(msg->rm_status); | 334 | return le32toh(msg->rm_status); | |
335 | } | 335 | } | |
336 | 336 | |||
337 | if (le32toh(msg->rm_infobuflen) + le32toh(msg->rm_infobufoffset) + | 337 | if (le32toh(msg->rm_infobuflen) + le32toh(msg->rm_infobufoffset) + | |
338 | RNDIS_HEADER_OFFSET > le32toh(msg->rm_len)) { | 338 | RNDIS_HEADER_OFFSET > le32toh(msg->rm_len)) { | |
339 | printf("%s: ctrl message error: invalid query info " | 339 | printf("%s: ctrl message error: invalid query info " | |
340 | "len/offset/end_position(%u/%u/%u) -> " | 340 | "len/offset/end_position(%u/%u/%u) -> " | |
341 | "go out of buffer limit %u\n", | 341 | "go out of buffer limit %u\n", | |
342 | DEVNAME(sc), | 342 | DEVNAME(sc), | |
343 | le32toh(msg->rm_infobuflen), | 343 | le32toh(msg->rm_infobuflen), | |
344 | le32toh(msg->rm_infobufoffset), | 344 | le32toh(msg->rm_infobufoffset), | |
345 | le32toh(msg->rm_infobuflen) + | 345 | le32toh(msg->rm_infobuflen) + | |
346 | le32toh(msg->rm_infobufoffset) + (uint32_t)RNDIS_HEADER_OFFSET, | 346 | le32toh(msg->rm_infobufoffset) + (uint32_t)RNDIS_HEADER_OFFSET, | |
347 | le32toh(msg->rm_len)); | 347 | le32toh(msg->rm_len)); | |
348 | return RNDIS_STATUS_FAILURE; | 348 | return RNDIS_STATUS_FAILURE; | |
349 | } | 349 | } | |
350 | 350 | |||
351 | if (buf && bufsz) { | 351 | if (buf && bufsz) { | |
352 | *buf = kmem_alloc(le32toh(msg->rm_infobuflen), KM_SLEEP); | 352 | *buf = kmem_alloc(le32toh(msg->rm_infobuflen), KM_SLEEP); | |
353 | if (*buf == NULL) { | 353 | if (*buf == NULL) { | |
354 | printf("%s: out of memory\n", DEVNAME(sc)); | 354 | printf("%s: out of memory\n", DEVNAME(sc)); | |
355 | return RNDIS_STATUS_FAILURE; | 355 | return RNDIS_STATUS_FAILURE; | |
356 | } else { | 356 | } else { | |
357 | const char *p; | 357 | const char *p; | |
358 | *bufsz = le32toh(msg->rm_infobuflen); | 358 | *bufsz = le32toh(msg->rm_infobuflen); | |
359 | 359 | |||
360 | p = (const char *)&msg->rm_rid; | 360 | p = (const char *)&msg->rm_rid; | |
361 | p += le32toh(msg->rm_infobufoffset); | 361 | p += le32toh(msg->rm_infobufoffset); | |
362 | memcpy(*buf, p, le32toh(msg->rm_infobuflen)); | 362 | memcpy(*buf, p, le32toh(msg->rm_infobuflen)); | |
363 | } | 363 | } | |
364 | } | 364 | } | |
365 | 365 | |||
366 | return le32toh(msg->rm_status); | 366 | return le32toh(msg->rm_status); | |
367 | } | 367 | } | |
368 | 368 | |||
369 | static uint32_t | 369 | static uint32_t | |
370 | urndis_ctrl_handle_reset(struct urndis_softc *sc, | 370 | urndis_ctrl_handle_reset(struct urndis_softc *sc, | |
371 | const struct urndis_comp_hdr *hdr) | 371 | const struct urndis_comp_hdr *hdr) | |
372 | { | 372 | { | |
373 | const struct urndis_reset_comp *msg; | 373 | const struct urndis_reset_comp *msg; | |
374 | uint32_t rval; | 374 | uint32_t rval; | |
375 | 375 | |||
376 | msg = (const struct urndis_reset_comp *) hdr; | 376 | msg = (const struct urndis_reset_comp *) hdr; | |
377 | 377 | |||
378 | rval = le32toh(msg->rm_status); | 378 | rval = le32toh(msg->rm_status); | |
379 | 379 | |||
380 | DPRINTF(("%s: urndis_ctrl_handle_reset: len %u status 0x%x " | 380 | DPRINTF(("%s: urndis_ctrl_handle_reset: len %u status 0x%x " | |
381 | "adrreset %u\n", | 381 | "adrreset %u\n", | |
382 | DEVNAME(sc), | 382 | DEVNAME(sc), | |
383 | le32toh(msg->rm_len), | 383 | le32toh(msg->rm_len), | |
384 | rval, | 384 | rval, | |
385 | le32toh(msg->rm_adrreset))); | 385 | le32toh(msg->rm_adrreset))); | |
386 | 386 | |||
387 | if (rval != RNDIS_STATUS_SUCCESS) { | 387 | if (rval != RNDIS_STATUS_SUCCESS) { | |
388 | printf("%s: reset failed 0x%x\n", DEVNAME(sc), rval); | 388 | printf("%s: reset failed 0x%x\n", DEVNAME(sc), rval); | |
389 | return rval; | 389 | return rval; | |
390 | } | 390 | } | |
391 | 391 | |||
392 | if (le32toh(msg->rm_adrreset) != 0) { | 392 | if (le32toh(msg->rm_adrreset) != 0) { | |
393 | uint32_t filter; | 393 | uint32_t filter; | |
394 | 394 | |||
395 | filter = htole32(sc->sc_filter); | 395 | filter = htole32(sc->sc_filter); | |
396 | rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER, | 396 | rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER, | |
397 | &filter, sizeof(filter)); | 397 | &filter, sizeof(filter)); | |
398 | if (rval != RNDIS_STATUS_SUCCESS) { | 398 | if (rval != RNDIS_STATUS_SUCCESS) { | |
399 | printf("%s: unable to reset data filters\n", | 399 | printf("%s: unable to reset data filters\n", | |
400 | DEVNAME(sc)); | 400 | DEVNAME(sc)); | |
401 | return rval; | 401 | return rval; | |
402 | } | 402 | } | |
403 | } | 403 | } | |
404 | 404 | |||
405 | return rval; | 405 | return rval; | |
406 | } | 406 | } | |
407 | 407 | |||
408 | static uint32_t | 408 | static uint32_t | |
409 | urndis_ctrl_init(struct urndis_softc *sc) | 409 | urndis_ctrl_init(struct urndis_softc *sc) | |
410 | { | 410 | { | |
411 | struct urndis_init_req *msg; | 411 | struct urndis_init_req *msg; | |
412 | uint32_t rval; | 412 | uint32_t rval; | |
413 | struct urndis_comp_hdr *hdr; | 413 | struct urndis_comp_hdr *hdr; | |
414 | 414 | |||
415 | msg = kmem_alloc(sizeof(*msg), KM_SLEEP); | 415 | msg = kmem_alloc(sizeof(*msg), KM_SLEEP); | |
416 | if (msg == NULL) { | 416 | if (msg == NULL) { | |
417 | printf("%s: out of memory\n", DEVNAME(sc)); | 417 | printf("%s: out of memory\n", DEVNAME(sc)); | |
418 | return RNDIS_STATUS_FAILURE; | 418 | return RNDIS_STATUS_FAILURE; | |
419 | } | 419 | } | |
420 | 420 | |||
421 | msg->rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG); | 421 | msg->rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG); | |
422 | msg->rm_len = htole32(sizeof(*msg)); | 422 | msg->rm_len = htole32(sizeof(*msg)); | |
423 | msg->rm_rid = htole32(0); | 423 | msg->rm_rid = htole32(0); | |
424 | msg->rm_ver_major = htole32(1); | 424 | msg->rm_ver_major = htole32(1); | |
425 | msg->rm_ver_minor = htole32(1); | 425 | msg->rm_ver_minor = htole32(1); | |
426 | msg->rm_max_xfersz = htole32(RNDIS_BUFSZ); | 426 | msg->rm_max_xfersz = htole32(RNDIS_BUFSZ); | |
427 | 427 | |||
428 | DPRINTF(("%s: urndis_ctrl_init send: type %u len %u rid %u ver_major %u " | 428 | DPRINTF(("%s: urndis_ctrl_init send: type %u len %u rid %u ver_major %u " | |
429 | "ver_minor %u max_xfersz %u\n", | 429 | "ver_minor %u max_xfersz %u\n", | |
430 | DEVNAME(sc), | 430 | DEVNAME(sc), | |
431 | le32toh(msg->rm_type), | 431 | le32toh(msg->rm_type), | |
432 | le32toh(msg->rm_len), | 432 | le32toh(msg->rm_len), | |
433 | le32toh(msg->rm_rid), | 433 | le32toh(msg->rm_rid), | |
434 | le32toh(msg->rm_ver_major), | 434 | le32toh(msg->rm_ver_major), | |
435 | le32toh(msg->rm_ver_minor), | 435 | le32toh(msg->rm_ver_minor), | |
436 | le32toh(msg->rm_max_xfersz))); | 436 | le32toh(msg->rm_max_xfersz))); | |
437 | 437 | |||
438 | rval = urndis_ctrl_send(sc, msg, sizeof(*msg)); | 438 | rval = urndis_ctrl_send(sc, msg, sizeof(*msg)); | |
439 | kmem_free(msg, sizeof(*msg)); | 439 | kmem_free(msg, sizeof(*msg)); | |
440 | 440 | |||
441 | if (rval != RNDIS_STATUS_SUCCESS) { | 441 | if (rval != RNDIS_STATUS_SUCCESS) { | |
442 | printf("%s: init failed\n", DEVNAME(sc)); | 442 | printf("%s: init failed\n", DEVNAME(sc)); | |
443 | return rval; | 443 | return rval; | |
444 | } | 444 | } | |
445 | 445 | |||
446 | if ((hdr = urndis_ctrl_recv(sc)) == NULL) { | 446 | if ((hdr = urndis_ctrl_recv(sc)) == NULL) { | |
447 | printf("%s: unable to get init response\n", DEVNAME(sc)); | 447 | printf("%s: unable to get init response\n", DEVNAME(sc)); | |
448 | return RNDIS_STATUS_FAILURE; | 448 | return RNDIS_STATUS_FAILURE; | |
449 | } | 449 | } | |
450 | rval = urndis_ctrl_handle(sc, hdr, NULL, NULL); | 450 | rval = urndis_ctrl_handle(sc, hdr, NULL, NULL); | |
451 | 451 | |||
452 | return rval; | 452 | return rval; | |
453 | } | 453 | } | |
454 | 454 | |||
455 | #if 0 | 455 | #if 0 | |
456 | static uint32_t | 456 | static uint32_t | |
457 | urndis_ctrl_halt(struct urndis_softc *sc) | 457 | urndis_ctrl_halt(struct urndis_softc *sc) | |
458 | { | 458 | { | |
459 | struct urndis_halt_req *msg; | 459 | struct urndis_halt_req *msg; | |
460 | uint32_t rval; | 460 | uint32_t rval; | |
461 | 461 | |||
462 | msg = kmem_alloc(sizeof(*msg), KM_SLEEP); | 462 | msg = kmem_alloc(sizeof(*msg), KM_SLEEP); | |
463 | if (msg == NULL) { | 463 | if (msg == NULL) { | |
464 | printf("%s: out of memory\n", DEVNAME(sc)); | 464 | printf("%s: out of memory\n", DEVNAME(sc)); | |
465 | return RNDIS_STATUS_FAILURE; | 465 | return RNDIS_STATUS_FAILURE; | |
466 | } | 466 | } | |
467 | 467 | |||
468 | msg->rm_type = htole32(REMOTE_NDIS_HALT_MSG); | 468 | msg->rm_type = htole32(REMOTE_NDIS_HALT_MSG); | |
469 | msg->rm_len = htole32(sizeof(*msg)); | 469 | msg->rm_len = htole32(sizeof(*msg)); | |
470 | msg->rm_rid = 0; | 470 | msg->rm_rid = 0; | |
471 | 471 | |||
472 | DPRINTF(("%s: urndis_ctrl_halt send: type %u len %u rid %u\n", | 472 | DPRINTF(("%s: urndis_ctrl_halt send: type %u len %u rid %u\n", | |
473 | DEVNAME(sc), | 473 | DEVNAME(sc), | |
474 | le32toh(msg->rm_type), | 474 | le32toh(msg->rm_type), | |
475 | le32toh(msg->rm_len), | 475 | le32toh(msg->rm_len), | |
476 | le32toh(msg->rm_rid))); | 476 | le32toh(msg->rm_rid))); | |
477 | 477 | |||
478 | rval = urndis_ctrl_send(sc, msg, sizeof(*msg)); | 478 | rval = urndis_ctrl_send(sc, msg, sizeof(*msg)); | |
479 | kmem_free(msg, sizeof(*msg)); | 479 | kmem_free(msg, sizeof(*msg)); | |
480 | 480 | |||
481 | if (rval != RNDIS_STATUS_SUCCESS) | 481 | if (rval != RNDIS_STATUS_SUCCESS) | |
482 | printf("%s: halt failed\n", DEVNAME(sc)); | 482 | printf("%s: halt failed\n", DEVNAME(sc)); | |
483 | 483 | |||
484 | return rval; | 484 | return rval; | |
485 | } | 485 | } | |
486 | #endif | 486 | #endif | |
487 | 487 | |||
488 | static uint32_t | 488 | static uint32_t | |
489 | urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid, | 489 | urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid, | |
490 | void *qbuf, size_t qlen, | 490 | void *qbuf, size_t qlen, | |
491 | void **rbuf, size_t *rbufsz) | 491 | void **rbuf, size_t *rbufsz) | |
492 | { | 492 | { | |
493 | struct urndis_query_req *msg; | 493 | struct urndis_query_req *msg; | |
494 | uint32_t rval; | 494 | uint32_t rval; | |
495 | struct urndis_comp_hdr *hdr; | 495 | struct urndis_comp_hdr *hdr; | |
496 | 496 | |||
497 | msg = kmem_alloc(sizeof(*msg) + qlen, KM_SLEEP); | 497 | msg = kmem_alloc(sizeof(*msg) + qlen, KM_SLEEP); | |
498 | if (msg == NULL) { | 498 | if (msg == NULL) { | |
499 | printf("%s: out of memory\n", DEVNAME(sc)); | 499 | printf("%s: out of memory\n", DEVNAME(sc)); | |
500 | return RNDIS_STATUS_FAILURE; | 500 | return RNDIS_STATUS_FAILURE; | |
501 | } | 501 | } | |
502 | 502 | |||
503 | msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG); | 503 | msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG); | |
504 | msg->rm_len = htole32(sizeof(*msg) + qlen); | 504 | msg->rm_len = htole32(sizeof(*msg) + qlen); | |
505 | msg->rm_rid = 0; /* XXX */ | 505 | msg->rm_rid = 0; /* XXX */ | |
506 | msg->rm_oid = htole32(oid); | 506 | msg->rm_oid = htole32(oid); | |
507 | msg->rm_infobuflen = htole32(qlen); | 507 | msg->rm_infobuflen = htole32(qlen); | |
508 | if (qlen != 0) { | 508 | if (qlen != 0) { | |
509 | msg->rm_infobufoffset = htole32(20); | 509 | msg->rm_infobufoffset = htole32(20); | |
510 | memcpy((char*)msg + 20, qbuf, qlen); | 510 | memcpy((char*)msg + 20, qbuf, qlen); | |
511 | } else | 511 | } else | |
512 | msg->rm_infobufoffset = 0; | 512 | msg->rm_infobufoffset = 0; | |
513 | msg->rm_devicevchdl = 0; | 513 | msg->rm_devicevchdl = 0; | |
514 | 514 | |||
515 | DPRINTF(("%s: urndis_ctrl_query send: type %u len %u rid %u oid 0x%x " | 515 | DPRINTF(("%s: urndis_ctrl_query send: type %u len %u rid %u oid 0x%x " | |
516 | "infobuflen %u infobufoffset %u devicevchdl %u\n", | 516 | "infobuflen %u infobufoffset %u devicevchdl %u\n", | |
517 | DEVNAME(sc), | 517 | DEVNAME(sc), | |
518 | le32toh(msg->rm_type), | 518 | le32toh(msg->rm_type), | |
519 | le32toh(msg->rm_len), | 519 | le32toh(msg->rm_len), | |
520 | le32toh(msg->rm_rid), | 520 | le32toh(msg->rm_rid), | |
521 | le32toh(msg->rm_oid), | 521 | le32toh(msg->rm_oid), | |
522 | le32toh(msg->rm_infobuflen), | 522 | le32toh(msg->rm_infobuflen), | |
523 | le32toh(msg->rm_infobufoffset), | 523 | le32toh(msg->rm_infobufoffset), | |
524 | le32toh(msg->rm_devicevchdl))); | 524 | le32toh(msg->rm_devicevchdl))); | |
525 | 525 | |||
526 | rval = urndis_ctrl_send(sc, msg, sizeof(*msg)); | 526 | rval = urndis_ctrl_send(sc, msg, sizeof(*msg)); | |
527 | kmem_free(msg, sizeof(*msg) + qlen); | 527 | kmem_free(msg, sizeof(*msg) + qlen); | |
528 | 528 | |||
529 | if (rval != RNDIS_STATUS_SUCCESS) { | 529 | if (rval != RNDIS_STATUS_SUCCESS) { | |
530 | printf("%s: query failed\n", DEVNAME(sc)); | 530 | printf("%s: query failed\n", DEVNAME(sc)); | |
531 | return rval; | 531 | return rval; | |
532 | } | 532 | } | |
533 | 533 | |||
534 | if ((hdr = urndis_ctrl_recv(sc)) == NULL) { | 534 | if ((hdr = urndis_ctrl_recv(sc)) == NULL) { | |
535 | printf("%s: unable to get query response\n", DEVNAME(sc)); | 535 | printf("%s: unable to get query response\n", DEVNAME(sc)); | |
536 | return RNDIS_STATUS_FAILURE; | 536 | return RNDIS_STATUS_FAILURE; | |
537 | } | 537 | } | |
538 | rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz); | 538 | rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz); | |
539 | 539 | |||
540 | return rval; | 540 | return rval; | |
541 | } | 541 | } | |
542 | 542 | |||
543 | static uint32_t | 543 | static uint32_t | |
544 | urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid, void *buf, size_t len) | 544 | urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid, void *buf, size_t len) | |
545 | { | 545 | { | |
546 | struct urndis_set_req *msg; | 546 | struct urndis_set_req *msg; | |
547 | uint32_t rval; | 547 | uint32_t rval; | |
548 | struct urndis_comp_hdr *hdr; | 548 | struct urndis_comp_hdr *hdr; | |
549 | 549 | |||
550 | msg = kmem_alloc(sizeof(*msg) + len, KM_SLEEP); | 550 | msg = kmem_alloc(sizeof(*msg) + len, KM_SLEEP); | |
551 | if (msg == NULL) { | 551 | if (msg == NULL) { | |
552 | printf("%s: out of memory\n", DEVNAME(sc)); | 552 | printf("%s: out of memory\n", DEVNAME(sc)); | |
553 | return RNDIS_STATUS_FAILURE; | 553 | return RNDIS_STATUS_FAILURE; | |
554 | } | 554 | } | |
555 | 555 | |||
556 | msg->rm_type = htole32(REMOTE_NDIS_SET_MSG); | 556 | msg->rm_type = htole32(REMOTE_NDIS_SET_MSG); | |
557 | msg->rm_len = htole32(sizeof(*msg) + len); | 557 | msg->rm_len = htole32(sizeof(*msg) + len); | |
558 | msg->rm_rid = 0; /* XXX */ | 558 | msg->rm_rid = 0; /* XXX */ | |
559 | msg->rm_oid = htole32(oid); | 559 | msg->rm_oid = htole32(oid); | |
560 | msg->rm_infobuflen = htole32(len); | 560 | msg->rm_infobuflen = htole32(len); | |
561 | if (len != 0) { | 561 | if (len != 0) { | |
562 | msg->rm_infobufoffset = htole32(20); | 562 | msg->rm_infobufoffset = htole32(20); | |
563 | memcpy((char*)msg + 20, buf, len); | 563 | memcpy((char*)msg + 20, buf, len); | |
564 | } else | 564 | } else | |
565 | msg->rm_infobufoffset = 0; | 565 | msg->rm_infobufoffset = 0; | |
566 | msg->rm_devicevchdl = 0; | 566 | msg->rm_devicevchdl = 0; | |
567 | 567 | |||
568 | DPRINTF(("%s: urndis_ctrl_set send: type %u len %u rid %u oid 0x%x " | 568 | DPRINTF(("%s: urndis_ctrl_set send: type %u len %u rid %u oid 0x%x " | |
569 | "infobuflen %u infobufoffset %u devicevchdl %u\n", | 569 | "infobuflen %u infobufoffset %u devicevchdl %u\n", | |
570 | DEVNAME(sc), | 570 | DEVNAME(sc), | |
571 | le32toh(msg->rm_type), | 571 | le32toh(msg->rm_type), | |
572 | le32toh(msg->rm_len), | 572 | le32toh(msg->rm_len), | |
573 | le32toh(msg->rm_rid), | 573 | le32toh(msg->rm_rid), | |
574 | le32toh(msg->rm_oid), | 574 | le32toh(msg->rm_oid), | |
575 | le32toh(msg->rm_infobuflen), | 575 | le32toh(msg->rm_infobuflen), | |
576 | le32toh(msg->rm_infobufoffset), | 576 | le32toh(msg->rm_infobufoffset), | |
577 | le32toh(msg->rm_devicevchdl))); | 577 | le32toh(msg->rm_devicevchdl))); | |
578 | 578 | |||
579 | rval = urndis_ctrl_send(sc, msg, sizeof(*msg)); | 579 | rval = urndis_ctrl_send(sc, msg, sizeof(*msg)); | |
580 | kmem_free(msg, sizeof(*msg) + len); | 580 | kmem_free(msg, sizeof(*msg) + len); | |
581 | 581 | |||
582 | if (rval != RNDIS_STATUS_SUCCESS) { | 582 | if (rval != RNDIS_STATUS_SUCCESS) { | |
583 | printf("%s: set failed\n", DEVNAME(sc)); | 583 | printf("%s: set failed\n", DEVNAME(sc)); | |
584 | return rval; | 584 | return rval; | |
585 | } | 585 | } | |
586 | 586 | |||
587 | if ((hdr = urndis_ctrl_recv(sc)) == NULL) { | 587 | if ((hdr = urndis_ctrl_recv(sc)) == NULL) { | |
588 | printf("%s: unable to get set response\n", DEVNAME(sc)); | 588 | printf("%s: unable to get set response\n", DEVNAME(sc)); | |
589 | return RNDIS_STATUS_FAILURE; | 589 | return RNDIS_STATUS_FAILURE; | |
590 | } | 590 | } | |
591 | rval = urndis_ctrl_handle(sc, hdr, NULL, NULL); | 591 | rval = urndis_ctrl_handle(sc, hdr, NULL, NULL); | |
592 | if (rval != RNDIS_STATUS_SUCCESS) | 592 | if (rval != RNDIS_STATUS_SUCCESS) | |
593 | printf("%s: set failed 0x%x\n", DEVNAME(sc), rval); | 593 | printf("%s: set failed 0x%x\n", DEVNAME(sc), rval); | |
594 | 594 | |||
595 | return rval; | 595 | return rval; | |
596 | } | 596 | } | |
597 | 597 | |||
598 | #if 0 | 598 | #if 0 | |
599 | static uint32_t | 599 | static uint32_t | |
600 | urndis_ctrl_set_param(struct urndis_softc *sc, | 600 | urndis_ctrl_set_param(struct urndis_softc *sc, | |
601 | const char *name, | 601 | const char *name, | |
602 | uint32_t type, | 602 | uint32_t type, | |
603 | void *buf, | 603 | void *buf, | |
604 | size_t len) | 604 | size_t len) | |
605 | { | 605 | { | |
606 | struct urndis_set_parameter *param; | 606 | struct urndis_set_parameter *param; | |
607 | uint32_t rval; | 607 | uint32_t rval; | |
608 | size_t namelen, tlen; | 608 | size_t namelen, tlen; | |
609 | 609 | |||
610 | if (name) | 610 | if (name) | |
611 | namelen = strlen(name); | 611 | namelen = strlen(name); | |
612 | else | 612 | else | |
613 | namelen = 0; | 613 | namelen = 0; | |
614 | tlen = sizeof(*param) + len + namelen; | 614 | tlen = sizeof(*param) + len + namelen; | |
615 | param = kmem_alloc(tlen, KM_SLEEP); | 615 | param = kmem_alloc(tlen, KM_SLEEP); | |
616 | if (param == NULL) { | 616 | if (param == NULL) { | |
617 | printf("%s: out of memory\n", DEVNAME(sc)); | 617 | printf("%s: out of memory\n", DEVNAME(sc)); | |
618 | return RNDIS_STATUS_FAILURE; | 618 | return RNDIS_STATUS_FAILURE; | |
619 | } | 619 | } | |
620 | 620 | |||
621 | param->rm_namelen = htole32(namelen); | 621 | param->rm_namelen = htole32(namelen); | |
622 | param->rm_valuelen = htole32(len); | 622 | param->rm_valuelen = htole32(len); | |
623 | param->rm_type = htole32(type); | 623 | param->rm_type = htole32(type); | |
624 | if (namelen != 0) { | 624 | if (namelen != 0) { | |
625 | param->rm_nameoffset = htole32(20); | 625 | param->rm_nameoffset = htole32(20); | |
626 | memcpy(param + 20, name, namelen); | 626 | memcpy(param + 20, name, namelen); | |
627 | } else | 627 | } else | |
628 | param->rm_nameoffset = 0; | 628 | param->rm_nameoffset = 0; | |
629 | if (len != 0) { | 629 | if (len != 0) { | |
630 | param->rm_valueoffset = htole32(20 + namelen); | 630 | param->rm_valueoffset = htole32(20 + namelen); | |
631 | memcpy(param + 20 + namelen, buf, len); | 631 | memcpy(param + 20 + namelen, buf, len); | |
632 | } else | 632 | } else | |
633 | param->rm_valueoffset = 0; | 633 | param->rm_valueoffset = 0; | |
634 | 634 | |||
635 | DPRINTF(("%s: urndis_ctrl_set_param send: nameoffset %u namelen %u " | 635 | DPRINTF(("%s: urndis_ctrl_set_param send: nameoffset %u namelen %u " | |
636 | "type 0x%x valueoffset %u valuelen %u\n", | 636 | "type 0x%x valueoffset %u valuelen %u\n", | |
637 | DEVNAME(sc), | 637 | DEVNAME(sc), | |
638 | le32toh(param->rm_nameoffset), | 638 | le32toh(param->rm_nameoffset), | |
639 | le32toh(param->rm_namelen), | 639 | le32toh(param->rm_namelen), | |
640 | le32toh(param->rm_type), | 640 | le32toh(param->rm_type), | |
641 | le32toh(param->rm_valueoffset), | 641 | le32toh(param->rm_valueoffset), | |
642 | le32toh(param->rm_valuelen))); | 642 | le32toh(param->rm_valuelen))); | |
643 | 643 | |||
644 | rval = urndis_ctrl_set(sc, OID_GEN_RNDIS_CONFIG_PARAMETER, param, tlen); | 644 | rval = urndis_ctrl_set(sc, OID_GEN_RNDIS_CONFIG_PARAMETER, param, tlen); | |
645 | kmem_free(param, tlen); | 645 | kmem_free(param, tlen); | |
646 | if (rval != RNDIS_STATUS_SUCCESS) | 646 | if (rval != RNDIS_STATUS_SUCCESS) | |
647 | printf("%s: set param failed 0x%x\n", DEVNAME(sc), rval); | 647 | printf("%s: set param failed 0x%x\n", DEVNAME(sc), rval); | |
648 | 648 | |||
649 | return rval; | 649 | return rval; | |
650 | } | 650 | } | |
651 | 651 | |||
652 | /* XXX : adrreset, get it from response */ | 652 | /* XXX : adrreset, get it from response */ | |
653 | static uint32_t | 653 | static uint32_t | |
654 | urndis_ctrl_reset(struct urndis_softc *sc) | 654 | urndis_ctrl_reset(struct urndis_softc *sc) | |
655 | { | 655 | { | |
656 | struct urndis_reset_req *reset; | 656 | struct urndis_reset_req *reset; | |
657 | uint32_t rval; | 657 | uint32_t rval; | |
658 | struct urndis_comp_hdr *hdr; | 658 | struct urndis_comp_hdr *hdr; | |
659 | 659 | |||
660 | reset = kmem_alloc(sizeof(*reset), KM_SLEEP); | 660 | reset = kmem_alloc(sizeof(*reset), KM_SLEEP); | |
661 | if (reset == NULL) { | 661 | if (reset == NULL) { | |
662 | printf("%s: out of memory\n", DEVNAME(sc)); | 662 | printf("%s: out of memory\n", DEVNAME(sc)); | |
663 | return RNDIS_STATUS_FAILURE; | 663 | return RNDIS_STATUS_FAILURE; | |
664 | } | 664 | } | |
665 | 665 | |||
666 | reset->rm_type = htole32(REMOTE_NDIS_RESET_MSG); | 666 | reset->rm_type = htole32(REMOTE_NDIS_RESET_MSG); | |
667 | reset->rm_len = htole32(sizeof(*reset)); | 667 | reset->rm_len = htole32(sizeof(*reset)); | |
668 | reset->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */ | 668 | reset->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */ | |
669 | 669 | |||
670 | DPRINTF(("%s: urndis_ctrl_reset send: type %u len %u rid %u\n", | 670 | DPRINTF(("%s: urndis_ctrl_reset send: type %u len %u rid %u\n", | |
671 | DEVNAME(sc), | 671 | DEVNAME(sc), | |
672 | le32toh(reset->rm_type), | 672 | le32toh(reset->rm_type), | |
673 | le32toh(reset->rm_len), | 673 | le32toh(reset->rm_len), | |
674 | le32toh(reset->rm_rid))); | 674 | le32toh(reset->rm_rid))); | |
675 | 675 | |||
676 | rval = urndis_ctrl_send(sc, reset, sizeof(*reset)); | 676 | rval = urndis_ctrl_send(sc, reset, sizeof(*reset)); | |
677 | kmem_free(reset, sizeof(*reset)); | 677 | kmem_free(reset, sizeof(*reset)); | |
678 | 678 | |||
679 | if (rval != RNDIS_STATUS_SUCCESS) { | 679 | if (rval != RNDIS_STATUS_SUCCESS) { | |
680 | printf("%s: reset failed\n", DEVNAME(sc)); | 680 | printf("%s: reset failed\n", DEVNAME(sc)); | |
681 | return rval; | 681 | return rval; | |
682 | } | 682 | } | |
683 | 683 | |||
684 | if ((hdr = urndis_ctrl_recv(sc)) == NULL) { | 684 | if ((hdr = urndis_ctrl_recv(sc)) == NULL) { | |
685 | printf("%s: unable to get reset response\n", DEVNAME(sc)); | 685 | printf("%s: unable to get reset response\n", DEVNAME(sc)); | |
686 | return RNDIS_STATUS_FAILURE; | 686 | return RNDIS_STATUS_FAILURE; | |
687 | } | 687 | } | |
688 | rval = urndis_ctrl_handle(sc, hdr, NULL, NULL); | 688 | rval = urndis_ctrl_handle(sc, hdr, NULL, NULL); | |
689 | 689 | |||
690 | return rval; | 690 | return rval; | |
691 | } | 691 | } | |
692 | 692 | |||
693 | static uint32_t | 693 | static uint32_t | |
694 | urndis_ctrl_keepalive(struct urndis_softc *sc) | 694 | urndis_ctrl_keepalive(struct urndis_softc *sc) | |
695 | { | 695 | { | |
696 | struct urndis_keepalive_req *keep; | 696 | struct urndis_keepalive_req *keep; | |
697 | uint32_t rval; | 697 | uint32_t rval; | |
698 | struct urndis_comp_hdr *hdr; | 698 | struct urndis_comp_hdr *hdr; | |
699 | 699 | |||
700 | keep = kmem_alloc(sizeof(*keep), KM_SLEEP); | 700 | keep = kmem_alloc(sizeof(*keep), KM_SLEEP); | |
701 | if (keep == NULL) { | 701 | if (keep == NULL) { | |
702 | printf("%s: out of memory\n", DEVNAME(sc)); | 702 | printf("%s: out of memory\n", DEVNAME(sc)); | |
703 | return RNDIS_STATUS_FAILURE; | 703 | return RNDIS_STATUS_FAILURE; | |
704 | } | 704 | } | |
705 | 705 | |||
706 | keep->rm_type = htole32(REMOTE_NDIS_KEEPALIVE_MSG); | 706 | keep->rm_type = htole32(REMOTE_NDIS_KEEPALIVE_MSG); | |
707 | keep->rm_len = htole32(sizeof(*keep)); | 707 | keep->rm_len = htole32(sizeof(*keep)); | |
708 | keep->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */ | 708 | keep->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */ | |
709 | 709 | |||
710 | DPRINTF(("%s: urndis_ctrl_keepalive: type %u len %u rid %u\n", | 710 | DPRINTF(("%s: urndis_ctrl_keepalive: type %u len %u rid %u\n", | |
711 | DEVNAME(sc), | 711 | DEVNAME(sc), | |
712 | le32toh(keep->rm_type), | 712 | le32toh(keep->rm_type), | |
713 | le32toh(keep->rm_len), | 713 | le32toh(keep->rm_len), | |
714 | le32toh(keep->rm_rid))); | 714 | le32toh(keep->rm_rid))); | |
715 | 715 | |||
716 | rval = urndis_ctrl_send(sc, keep, sizeof(*keep)); | 716 | rval = urndis_ctrl_send(sc, keep, sizeof(*keep)); | |
717 | kmem_free(keep, sizeof(*keep)); | 717 | kmem_free(keep, sizeof(*keep)); | |
718 | 718 | |||
719 | if (rval != RNDIS_STATUS_SUCCESS) { | 719 | if (rval != RNDIS_STATUS_SUCCESS) { | |
720 | printf("%s: keepalive failed\n", DEVNAME(sc)); | 720 | printf("%s: keepalive failed\n", DEVNAME(sc)); | |
721 | return rval; | 721 | return rval; | |
722 | } | 722 | } | |
723 | 723 | |||
724 | if ((hdr = urndis_ctrl_recv(sc)) == NULL) { | 724 | if ((hdr = urndis_ctrl_recv(sc)) == NULL) { | |
725 | printf("%s: unable to get keepalive response\n", DEVNAME(sc)); | 725 | printf("%s: unable to get keepalive response\n", DEVNAME(sc)); | |
726 | return RNDIS_STATUS_FAILURE; | 726 | return RNDIS_STATUS_FAILURE; | |
727 | } | 727 | } | |
728 | rval = urndis_ctrl_handle(sc, hdr, NULL, NULL); | 728 | rval = urndis_ctrl_handle(sc, hdr, NULL, NULL); | |
729 | if (rval != RNDIS_STATUS_SUCCESS) { | 729 | if (rval != RNDIS_STATUS_SUCCESS) { | |
730 | printf("%s: keepalive failed 0x%x\n", DEVNAME(sc), rval); | 730 | printf("%s: keepalive failed 0x%x\n", DEVNAME(sc), rval); | |
731 | urndis_ctrl_reset(sc); | 731 | urndis_ctrl_reset(sc); | |
732 | } | 732 | } | |
733 | 733 | |||
734 | return rval; | 734 | return rval; | |
735 | } | 735 | } | |
736 | #endif | 736 | #endif | |
737 | 737 | |||
738 | static int | 738 | static int | |
739 | urndis_encap(struct urndis_softc *sc, struct mbuf *m, int idx) | 739 | urndis_encap(struct urndis_softc *sc, struct mbuf *m, int idx) | |
740 | { | 740 | { | |
741 | struct urndis_chain *c; | 741 | struct urndis_chain *c; | |
742 | usbd_status err; | 742 | usbd_status err; | |
743 | struct urndis_packet_msg *msg; | 743 | struct urndis_packet_msg *msg; | |
744 | 744 | |||
745 | c = &sc->sc_data.sc_tx_chain[idx]; | 745 | c = &sc->sc_data.sc_tx_chain[idx]; | |
746 | 746 | |||
747 | msg = (struct urndis_packet_msg *)c->sc_buf; | 747 | msg = (struct urndis_packet_msg *)c->sc_buf; | |
748 | 748 | |||
749 | memset(msg, 0, sizeof(*msg)); | 749 | memset(msg, 0, sizeof(*msg)); | |
750 | msg->rm_type = htole32(REMOTE_NDIS_PACKET_MSG); | 750 | msg->rm_type = htole32(REMOTE_NDIS_PACKET_MSG); | |
751 | msg->rm_len = htole32(sizeof(*msg) + m->m_pkthdr.len); | 751 | msg->rm_len = htole32(sizeof(*msg) + m->m_pkthdr.len); | |
752 | 752 | |||
753 | msg->rm_dataoffset = htole32(RNDIS_DATA_OFFSET); | 753 | msg->rm_dataoffset = htole32(RNDIS_DATA_OFFSET); | |
754 | msg->rm_datalen = htole32(m->m_pkthdr.len); | 754 | msg->rm_datalen = htole32(m->m_pkthdr.len); | |
755 | 755 | |||
756 | m_copydata(m, 0, m->m_pkthdr.len, | 756 | m_copydata(m, 0, m->m_pkthdr.len, | |
757 | ((char*)msg + RNDIS_DATA_OFFSET + RNDIS_HEADER_OFFSET)); | 757 | ((char*)msg + RNDIS_DATA_OFFSET + RNDIS_HEADER_OFFSET)); | |
758 | 758 | |||
759 | DPRINTF(("%s: urndis_encap type 0x%x len %u data(off %u len %u)\n", | 759 | DPRINTF(("%s: urndis_encap type 0x%x len %u data(off %u len %u)\n", | |
760 | DEVNAME(sc), | 760 | DEVNAME(sc), | |
761 | le32toh(msg->rm_type), | 761 | le32toh(msg->rm_type), | |
762 | le32toh(msg->rm_len), | 762 | le32toh(msg->rm_len), | |
763 | le32toh(msg->rm_dataoffset), | 763 | le32toh(msg->rm_dataoffset), | |
764 | le32toh(msg->rm_datalen))); | 764 | le32toh(msg->rm_datalen))); | |
765 | 765 | |||
766 | c->sc_mbuf = m; | 766 | c->sc_mbuf = m; | |
767 | 767 | |||
768 | usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, le32toh(msg->rm_len), | 768 | usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, le32toh(msg->rm_len), | |
769 | USBD_FORCE_SHORT_XFER, 10000, urndis_txeof); | 769 | USBD_FORCE_SHORT_XFER, 10000, urndis_txeof); | |
770 | 770 | |||
771 | /* Transmit */ | 771 | /* Transmit */ | |
772 | err = usbd_transfer(c->sc_xfer); | 772 | err = usbd_transfer(c->sc_xfer); | |
773 | if (err != USBD_IN_PROGRESS) { | 773 | if (err != USBD_IN_PROGRESS) { | |
774 | urndis_stop(GET_IFP(sc)); | 774 | urndis_stop(GET_IFP(sc)); | |
775 | return(EIO); | 775 | return(EIO); | |
776 | } | 776 | } | |
777 | 777 | |||
778 | sc->sc_data.sc_tx_cnt++; | 778 | sc->sc_data.sc_tx_cnt++; | |
779 | 779 | |||
780 | return(0); | 780 | return(0); | |
781 | } | 781 | } | |
782 | 782 | |||
783 | static void | 783 | static void | |
784 | urndis_decap(struct urndis_softc *sc, struct urndis_chain *c, uint32_t len) | 784 | urndis_decap(struct urndis_softc *sc, struct urndis_chain *c, uint32_t len) | |
785 | { | 785 | { | |
786 | struct mbuf *m; | 786 | struct mbuf *m; | |
787 | struct urndis_packet_msg *msg; | 787 | struct urndis_packet_msg *msg; | |
788 | struct ifnet *ifp; | 788 | struct ifnet *ifp; | |
789 | int s; | 789 | int s; | |
790 | int offset; | 790 | int offset; | |
791 | 791 | |||
792 | ifp = GET_IFP(sc); | 792 | ifp = GET_IFP(sc); | |
793 | offset = 0; | 793 | offset = 0; | |
794 | 794 | |||
795 | while (len > 0) { | 795 | while (len > 0) { | |
796 | msg = (struct urndis_packet_msg *)((char*)c->sc_buf + offset); | 796 | msg = (struct urndis_packet_msg *)((char*)c->sc_buf + offset); | |
797 | m = c->sc_mbuf; | 797 | m = c->sc_mbuf; | |
798 | 798 | |||
799 | DPRINTF(("%s: urndis_decap buffer size left %u\n", DEVNAME(sc), | 799 | DPRINTF(("%s: urndis_decap buffer size left %u\n", DEVNAME(sc), | |
800 | len)); | 800 | len)); | |
801 | 801 | |||
802 | if (len < sizeof(*msg)) { | 802 | if (len < sizeof(*msg)) { | |
803 | printf("%s: urndis_decap invalid buffer len %u < " | 803 | printf("%s: urndis_decap invalid buffer len %u < " | |
804 | "minimum header %zu\n", | 804 | "minimum header %zu\n", | |
805 | DEVNAME(sc), | 805 | DEVNAME(sc), | |
806 | len, | 806 | len, | |
807 | sizeof(*msg)); | 807 | sizeof(*msg)); | |
808 | return; | 808 | return; | |
809 | } | 809 | } | |
810 | 810 | |||
811 | DPRINTF(("%s: urndis_decap len %u data(off:%u len:%u) " | 811 | DPRINTF(("%s: urndis_decap len %u data(off:%u len:%u) " | |
812 | "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n", | 812 | "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n", | |
813 | DEVNAME(sc), | 813 | DEVNAME(sc), | |
814 | le32toh(msg->rm_len), | 814 | le32toh(msg->rm_len), | |
815 | le32toh(msg->rm_dataoffset), | 815 | le32toh(msg->rm_dataoffset), | |
816 | le32toh(msg->rm_datalen), | 816 | le32toh(msg->rm_datalen), | |
817 | le32toh(msg->rm_oobdataoffset), | 817 | le32toh(msg->rm_oobdataoffset), | |
818 | le32toh(msg->rm_oobdatalen), | 818 | le32toh(msg->rm_oobdatalen), | |
819 | le32toh(msg->rm_oobdataelements), | 819 | le32toh(msg->rm_oobdataelements), | |
820 | le32toh(msg->rm_pktinfooffset), | 820 | le32toh(msg->rm_pktinfooffset), | |
821 | le32toh(msg->rm_pktinfooffset))); | 821 | le32toh(msg->rm_pktinfooffset))); | |
822 | 822 | |||
823 | if (le32toh(msg->rm_type) != REMOTE_NDIS_PACKET_MSG) { | 823 | if (le32toh(msg->rm_type) != REMOTE_NDIS_PACKET_MSG) { | |
824 | printf("%s: urndis_decap invalid type 0x%x != 0x%x\n", | 824 | printf("%s: urndis_decap invalid type 0x%x != 0x%x\n", | |
825 | DEVNAME(sc), | 825 | DEVNAME(sc), | |
826 | le32toh(msg->rm_type), | 826 | le32toh(msg->rm_type), | |
827 | REMOTE_NDIS_PACKET_MSG); | 827 | REMOTE_NDIS_PACKET_MSG); | |
828 | return; | 828 | return; | |
829 | } | 829 | } | |
830 | if (le32toh(msg->rm_len) < sizeof(*msg)) { | 830 | if (le32toh(msg->rm_len) < sizeof(*msg)) { | |
831 | printf("%s: urndis_decap invalid msg len %u < %zu\n", | 831 | printf("%s: urndis_decap invalid msg len %u < %zu\n", | |
832 | DEVNAME(sc), | 832 | DEVNAME(sc), | |
833 | le32toh(msg->rm_len), | 833 | le32toh(msg->rm_len), | |
834 | sizeof(*msg)); | 834 | sizeof(*msg)); | |
835 | return; | 835 | return; | |
836 | } | 836 | } | |
837 | if (le32toh(msg->rm_len) > len) { | 837 | if (le32toh(msg->rm_len) > len) { | |
838 | printf("%s: urndis_decap invalid msg len %u > buffer " | 838 | printf("%s: urndis_decap invalid msg len %u > buffer " | |
839 | "len %u\n", | 839 | "len %u\n", | |
840 | DEVNAME(sc), | 840 | DEVNAME(sc), | |
841 | le32toh(msg->rm_len), | 841 | le32toh(msg->rm_len), | |
842 | len); | 842 | len); | |
843 | return; | 843 | return; | |
844 | } | 844 | } | |
845 | 845 | |||
846 | if (le32toh(msg->rm_dataoffset) + | 846 | if (le32toh(msg->rm_dataoffset) + | |
847 | le32toh(msg->rm_datalen) + RNDIS_HEADER_OFFSET | 847 | le32toh(msg->rm_datalen) + RNDIS_HEADER_OFFSET | |
848 | > le32toh(msg->rm_len)) { | 848 | > le32toh(msg->rm_len)) { | |
849 | printf("%s: urndis_decap invalid data " | 849 | printf("%s: urndis_decap invalid data " | |
850 | "len/offset/end_position(%u/%u/%u) -> " | 850 | "len/offset/end_position(%u/%u/%u) -> " | |
851 | "go out of receive buffer limit %u\n", | 851 | "go out of receive buffer limit %u\n", | |
852 | DEVNAME(sc), | 852 | DEVNAME(sc), | |
853 | le32toh(msg->rm_datalen), | 853 | le32toh(msg->rm_datalen), | |
854 | le32toh(msg->rm_dataoffset), | 854 | le32toh(msg->rm_dataoffset), | |
855 | le32toh(msg->rm_dataoffset) + | 855 | le32toh(msg->rm_dataoffset) + | |
856 | le32toh(msg->rm_datalen) + (uint32_t)RNDIS_HEADER_OFFSET, | 856 | le32toh(msg->rm_datalen) + (uint32_t)RNDIS_HEADER_OFFSET, | |
857 | le32toh(msg->rm_len)); | 857 | le32toh(msg->rm_len)); | |
858 | return; | 858 | return; | |
859 | } | 859 | } | |
860 | 860 | |||
861 | if (le32toh(msg->rm_datalen) < sizeof(struct ether_header)) { | 861 | if (le32toh(msg->rm_datalen) < sizeof(struct ether_header)) { | |
862 | ifp->if_ierrors++; | 862 | ifp->if_ierrors++; | |
863 | printf("%s: urndis_decap invalid ethernet size " | 863 | printf("%s: urndis_decap invalid ethernet size " | |
864 | "%d < %zu\n", | 864 | "%d < %zu\n", | |
865 | DEVNAME(sc), | 865 | DEVNAME(sc), | |
866 | le32toh(msg->rm_datalen), | 866 | le32toh(msg->rm_datalen), | |
867 | sizeof(struct ether_header)); | 867 | sizeof(struct ether_header)); | |
868 | return; | 868 | return; | |
869 | } | 869 | } | |
870 | 870 | |||
871 | memcpy(mtod(m, char*), | 871 | memcpy(mtod(m, char*), | |
872 | ((char*)&msg->rm_dataoffset + le32toh(msg->rm_dataoffset)), | 872 | ((char*)&msg->rm_dataoffset + le32toh(msg->rm_dataoffset)), | |
873 | le32toh(msg->rm_datalen)); | 873 | le32toh(msg->rm_datalen)); | |
874 | m->m_pkthdr.len = m->m_len = le32toh(msg->rm_datalen); | 874 | m->m_pkthdr.len = m->m_len = le32toh(msg->rm_datalen); | |
875 | 875 | |||
876 | ifp->if_ipackets++; | 876 | ifp->if_ipackets++; | |
877 | m_set_rcvif(m, ifp); | 877 | m_set_rcvif(m, ifp); | |
878 | 878 | |||
879 | s = splnet(); | 879 | s = splnet(); | |
880 | 880 | |||
881 | if (urndis_newbuf(sc, c) == ENOBUFS) { | 881 | if (urndis_newbuf(sc, c) == ENOBUFS) { | |
882 | ifp->if_ierrors++; | 882 | ifp->if_ierrors++; | |
883 | } else { | 883 | } else { | |
884 | 884 | |||
885 | bpf_mtap(ifp, m); | 885 | bpf_mtap(ifp, m); | |
886 | 886 | |||
887 | if_percpuq_enqueue(sc->urndis_ipq, m); | 887 | if_percpuq_enqueue(sc->urndis_ipq, m); | |
888 | } | 888 | } | |
889 | splx(s); | 889 | splx(s); | |
890 | 890 | |||
891 | offset += le32toh(msg->rm_len); | 891 | offset += le32toh(msg->rm_len); | |
892 | len -= le32toh(msg->rm_len); | 892 | len -= le32toh(msg->rm_len); | |
893 | } | 893 | } | |
894 | } | 894 | } | |
895 | 895 | |||
896 | static int | 896 | static int | |
897 | urndis_newbuf(struct urndis_softc *sc, struct urndis_chain *c) | 897 | urndis_newbuf(struct urndis_softc *sc, struct urndis_chain *c) | |
898 | { | 898 | { | |
899 | struct mbuf *m_new = NULL; | 899 | struct mbuf *m_new = NULL; | |
900 | 900 | |||
901 | MGETHDR(m_new, M_DONTWAIT, MT_DATA); | 901 | MGETHDR(m_new, M_DONTWAIT, MT_DATA); | |
902 | if (m_new == NULL) { | 902 | if (m_new == NULL) { | |
903 | printf("%s: no memory for rx list -- packet dropped!\n", | 903 | printf("%s: no memory for rx list -- packet dropped!\n", | |
904 | DEVNAME(sc)); | 904 | DEVNAME(sc)); | |
905 | return ENOBUFS; | 905 | return ENOBUFS; | |
906 | } | 906 | } | |
907 | MCLGET(m_new, M_DONTWAIT); | 907 | MCLGET(m_new, M_DONTWAIT); | |
908 | if (!(m_new->m_flags & M_EXT)) { | 908 | if (!(m_new->m_flags & M_EXT)) { | |
909 | printf("%s: no memory for rx list -- packet dropped!\n", | 909 | printf("%s: no memory for rx list -- packet dropped!\n", | |
910 | DEVNAME(sc)); | 910 | DEVNAME(sc)); | |
911 | m_freem(m_new); | 911 | m_freem(m_new); | |
912 | return ENOBUFS; | 912 | return ENOBUFS; | |
913 | } | 913 | } | |
914 | m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; | 914 | m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; | |
915 | 915 | |||
916 | m_adj(m_new, ETHER_ALIGN); | 916 | m_adj(m_new, ETHER_ALIGN); | |
917 | c->sc_mbuf = m_new; | 917 | c->sc_mbuf = m_new; | |
918 | return 0; | 918 | return 0; | |
919 | } | 919 | } | |
920 | 920 | |||
921 | static int | 921 | static int | |
922 | urndis_rx_list_init(struct urndis_softc *sc) | 922 | urndis_rx_list_init(struct urndis_softc *sc) | |
923 | { | 923 | { | |
924 | struct urndis_cdata *cd; | 924 | struct urndis_cdata *cd; | |
925 | struct urndis_chain *c; | 925 | struct urndis_chain *c; | |
926 | int i; | 926 | int i; | |
927 | 927 | |||
928 | cd = &sc->sc_data; | 928 | cd = &sc->sc_data; | |
929 | for (i = 0; i < RNDIS_RX_LIST_CNT; i++) { | 929 | for (i = 0; i < RNDIS_RX_LIST_CNT; i++) { | |
930 | c = &cd->sc_rx_chain[i]; | 930 | c = &cd->sc_rx_chain[i]; | |
931 | c->sc_softc = sc; | 931 | c->sc_softc = sc; | |
932 | c->sc_idx = i; | 932 | c->sc_idx = i; | |
933 | 933 | |||
934 | if (urndis_newbuf(sc, c) == ENOBUFS) | 934 | if (urndis_newbuf(sc, c) == ENOBUFS) | |
935 | return ENOBUFS; | 935 | return ENOBUFS; | |
936 | 936 | |||
937 | if (c->sc_xfer == NULL) { | 937 | if (c->sc_xfer == NULL) { | |
938 | int err = usbd_create_xfer(sc->sc_bulkin_pipe, | 938 | int err = usbd_create_xfer(sc->sc_bulkin_pipe, | |
939 | RNDIS_BUFSZ, USBD_SHORT_XFER_OK, 0, &c->sc_xfer); | 939 | RNDIS_BUFSZ, USBD_SHORT_XFER_OK, 0, &c->sc_xfer); | |
940 | if (err) | 940 | if (err) | |
941 | return err; | 941 | return err; | |
942 | c->sc_buf = usbd_get_buffer(c->sc_xfer); | 942 | c->sc_buf = usbd_get_buffer(c->sc_xfer); | |
943 | } | 943 | } | |
944 | } | 944 | } | |
945 | 945 | |||
946 | return 0; | 946 | return 0; | |
947 | } | 947 | } | |
948 | 948 | |||
949 | static void | 949 | static void | |
950 | urndis_rx_list_free(struct urndis_softc *sc) | 950 | urndis_rx_list_free(struct urndis_softc *sc) | |
951 | { | 951 | { | |
952 | for (int i = 0; i < RNDIS_RX_LIST_CNT; i++) { | 952 | for (int i = 0; i < RNDIS_RX_LIST_CNT; i++) { | |
953 | if (sc->sc_data.sc_rx_chain[i].sc_mbuf != NULL) { | 953 | if (sc->sc_data.sc_rx_chain[i].sc_mbuf != NULL) { | |
954 | m_freem(sc->sc_data.sc_rx_chain[i].sc_mbuf); | 954 | m_freem(sc->sc_data.sc_rx_chain[i].sc_mbuf); | |
955 | sc->sc_data.sc_rx_chain[i].sc_mbuf = NULL; | 955 | sc->sc_data.sc_rx_chain[i].sc_mbuf = NULL; | |
956 | } | 956 | } | |
957 | if (sc->sc_data.sc_rx_chain[i].sc_xfer != NULL) { | 957 | if (sc->sc_data.sc_rx_chain[i].sc_xfer != NULL) { | |
958 | usbd_destroy_xfer(sc->sc_data.sc_rx_chain[i].sc_xfer); | 958 | usbd_destroy_xfer(sc->sc_data.sc_rx_chain[i].sc_xfer); | |
959 | sc->sc_data.sc_rx_chain[i].sc_xfer = NULL; | 959 | sc->sc_data.sc_rx_chain[i].sc_xfer = NULL; | |
960 | } | 960 | } | |
961 | } | 961 | } | |
962 | } | 962 | } | |
963 | 963 | |||
964 | static int | 964 | static int | |
965 | urndis_tx_list_init(struct urndis_softc *sc) | 965 | urndis_tx_list_init(struct urndis_softc *sc) | |
966 | { | 966 | { | |
967 | struct urndis_cdata *cd; | 967 | struct urndis_cdata *cd; | |
968 | struct urndis_chain *c; | 968 | struct urndis_chain *c; | |
969 | int i; | 969 | int i; | |
970 | 970 | |||
971 | cd = &sc->sc_data; | 971 | cd = &sc->sc_data; | |
972 | for (i = 0; i < RNDIS_TX_LIST_CNT; i++) { | 972 | for (i = 0; i < RNDIS_TX_LIST_CNT; i++) { | |
973 | c = &cd->sc_tx_chain[i]; | 973 | c = &cd->sc_tx_chain[i]; | |
974 | c->sc_softc = sc; | 974 | c->sc_softc = sc; | |
975 | c->sc_idx = i; | 975 | c->sc_idx = i; | |
976 | c->sc_mbuf = NULL; | 976 | c->sc_mbuf = NULL; | |
977 | if (c->sc_xfer == NULL) { | 977 | if (c->sc_xfer == NULL) { | |
978 | int err = usbd_create_xfer(sc->sc_bulkout_pipe, | 978 | int err = usbd_create_xfer(sc->sc_bulkout_pipe, | |
979 | RNDIS_BUFSZ, USBD_FORCE_SHORT_XFER, 0, &c->sc_xfer); | 979 | RNDIS_BUFSZ, USBD_FORCE_SHORT_XFER, 0, &c->sc_xfer); | |
980 | if (err) | 980 | if (err) | |
981 | return err; | 981 | return err; | |
982 | c->sc_buf = usbd_get_buffer(c->sc_xfer); | 982 | c->sc_buf = usbd_get_buffer(c->sc_xfer); | |
983 | } | 983 | } | |
984 | } | 984 | } | |
985 | return 0; | 985 | return 0; | |
986 | } | 986 | } | |
987 | 987 | |||
988 | static void | 988 | static void | |
989 | urndis_tx_list_free(struct urndis_softc *sc) | 989 | urndis_tx_list_free(struct urndis_softc *sc) | |
990 | { | 990 | { | |
991 | for (int i = 0; i < RNDIS_TX_LIST_CNT; i++) { | 991 | for (int i = 0; i < RNDIS_TX_LIST_CNT; i++) { | |
992 | if (sc->sc_data.sc_tx_chain[i].sc_mbuf != NULL) { | 992 | if (sc->sc_data.sc_tx_chain[i].sc_mbuf != NULL) { | |
993 | m_freem(sc->sc_data.sc_tx_chain[i].sc_mbuf); | 993 | m_freem(sc->sc_data.sc_tx_chain[i].sc_mbuf); | |
994 | sc->sc_data.sc_tx_chain[i].sc_mbuf = NULL; | 994 | sc->sc_data.sc_tx_chain[i].sc_mbuf = NULL; | |
995 | } | 995 | } | |
996 | if (sc->sc_data.sc_tx_chain[i].sc_xfer != NULL) { | 996 | if (sc->sc_data.sc_tx_chain[i].sc_xfer != NULL) { | |
997 | usbd_destroy_xfer(sc->sc_data.sc_tx_chain[i].sc_xfer); | 997 | usbd_destroy_xfer(sc->sc_data.sc_tx_chain[i].sc_xfer); | |
998 | sc->sc_data.sc_tx_chain[i].sc_xfer = NULL; | 998 | sc->sc_data.sc_tx_chain[i].sc_xfer = NULL; | |
999 | } | 999 | } | |
1000 | } | 1000 | } | |
1001 | } | 1001 | } | |
1002 | 1002 | |||
1003 | static int | 1003 | static int | |
1004 | urndis_ioctl(struct ifnet *ifp, unsigned long command, void *data) | 1004 | urndis_ioctl(struct ifnet *ifp, unsigned long command, void *data) | |
1005 | { | 1005 | { | |
1006 | struct urndis_softc *sc; | 1006 | struct urndis_softc *sc; | |
1007 | int s, error; | 1007 | int s, error; | |
1008 | 1008 | |||
1009 | sc = ifp->if_softc; | 1009 | sc = ifp->if_softc; | |
1010 | error = 0; | 1010 | error = 0; | |
1011 | 1011 | |||
1012 | if (sc->sc_dying) | 1012 | if (sc->sc_dying) | |
1013 | return EIO; | 1013 | return EIO; | |
1014 | 1014 | |||
1015 | s = splnet(); | 1015 | s = splnet(); | |
1016 | 1016 | |||
1017 | error = ether_ioctl(ifp, command, data); | 1017 | error = ether_ioctl(ifp, command, data); | |
1018 | 1018 | |||
1019 | if (error == ENETRESET) | 1019 | if (error == ENETRESET) | |
1020 | error = 0; | 1020 | error = 0; | |
1021 | 1021 | |||
1022 | splx(s); | 1022 | splx(s); | |
1023 | return error; | 1023 | return error; | |
1024 | } | 1024 | } | |
1025 | 1025 | |||
1026 | #if 0 | 1026 | #if 0 | |
1027 | static void | 1027 | static void | |
1028 | urndis_watchdog(struct ifnet *ifp) | 1028 | urndis_watchdog(struct ifnet *ifp) | |
1029 | { | 1029 | { | |
1030 | struct urndis_softc *sc; | 1030 | struct urndis_softc *sc; | |
1031 | 1031 | |||
1032 | sc = ifp->if_softc; | 1032 | sc = ifp->if_softc; | |
1033 | 1033 | |||
1034 | if (sc->sc_dying) | 1034 | if (sc->sc_dying) | |
1035 | return; | 1035 | return; | |
1036 | 1036 | |||
1037 | ifp->if_oerrors++; | 1037 | ifp->if_oerrors++; | |
1038 | printf("%s: watchdog timeout\n", DEVNAME(sc)); | 1038 | printf("%s: watchdog timeout\n", DEVNAME(sc)); | |
1039 | 1039 | |||
1040 | urndis_ctrl_keepalive(sc); | 1040 | urndis_ctrl_keepalive(sc); | |
1041 | } | 1041 | } | |
1042 | #endif | 1042 | #endif | |
1043 | 1043 | |||
1044 | static int | 1044 | static int | |
1045 | urndis_init(struct ifnet *ifp) | 1045 | urndis_init(struct ifnet *ifp) | |
1046 | { | 1046 | { | |
1047 | struct urndis_softc *sc = ifp->if_softc; | 1047 | struct urndis_softc *sc = ifp->if_softc; | |
1048 | 1048 | |||
1049 | mutex_enter(&sc->urndis_lock); | 1049 | mutex_enter(&sc->sc_lock); | |
1050 | int ret = urndis_init_locked(ifp); | 1050 | int ret = urndis_init_locked(ifp); | |
1051 | mutex_exit(&sc->urndis_lock); | 1051 | mutex_exit(&sc->sc_lock); | |
1052 | 1052 | |||
1053 | return ret; | 1053 | return ret; | |
1054 | } | 1054 | } | |
1055 | 1055 | |||
1056 | static int | 1056 | static int | |
1057 | urndis_init_locked(struct ifnet *ifp) | 1057 | urndis_init_locked(struct ifnet *ifp) | |
1058 | { | 1058 | { | |
1059 | struct urndis_softc *sc; | 1059 | struct urndis_softc *sc; | |
1060 | int i; | 1060 | int i; | |
1061 | int err; | 1061 | int err; | |
1062 | usbd_status usberr; | 1062 | usbd_status usberr; | |
1063 | 1063 | |||
1064 | sc = ifp->if_softc; | 1064 | sc = ifp->if_softc; | |
1065 | 1065 | |||
1066 | if (ifp->if_flags & IFF_RUNNING) | 1066 | if (ifp->if_flags & IFF_RUNNING) | |
1067 | return 0; | 1067 | return 0; | |
1068 | 1068 | |||
1069 | err = urndis_ctrl_init(sc); | 1069 | err = urndis_ctrl_init(sc); | |
1070 | if (err != RNDIS_STATUS_SUCCESS) | 1070 | if (err != RNDIS_STATUS_SUCCESS) | |
1071 | return EIO; | 1071 | return EIO; | |
1072 | 1072 | |||
1073 | usberr = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkin_no, | 1073 | usberr = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkin_no, | |
1074 | USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe); | 1074 | USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe); | |
1075 | if (usberr) { | 1075 | if (usberr) { | |
1076 | printf("%s: open rx pipe failed: %s\n", DEVNAME(sc), | 1076 | printf("%s: open rx pipe failed: %s\n", DEVNAME(sc), | |
1077 | usbd_errstr(err)); | 1077 | usbd_errstr(err)); | |
1078 | goto fail; | 1078 | goto fail; | |
1079 | } | 1079 | } | |
1080 | 1080 | |||
1081 | usberr = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkout_no, | 1081 | usberr = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkout_no, | |
1082 | USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); | 1082 | USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe); | |
1083 | if (usberr) { | 1083 | if (usberr) { | |
1084 | printf("%s: open tx pipe failed: %s\n", DEVNAME(sc), | 1084 | printf("%s: open tx pipe failed: %s\n", DEVNAME(sc), | |
1085 | usbd_errstr(err)); | 1085 | usbd_errstr(err)); | |
1086 | goto fail2; | 1086 | goto fail2; | |
1087 | } | 1087 | } | |
1088 | 1088 | |||
1089 | err = urndis_tx_list_init(sc); | 1089 | err = urndis_tx_list_init(sc); | |
1090 | if (err) { | 1090 | if (err) { | |
1091 | printf("%s: tx list init failed\n", | 1091 | printf("%s: tx list init failed\n", | |
1092 | DEVNAME(sc)); | 1092 | DEVNAME(sc)); | |
1093 | goto fail3; | 1093 | goto fail3; | |
1094 | } | 1094 | } | |
1095 | 1095 | |||
1096 | err = urndis_rx_list_init(sc); | 1096 | err = urndis_rx_list_init(sc); | |
1097 | if (err) { | 1097 | if (err) { | |
1098 | printf("%s: rx list init failed\n", | 1098 | printf("%s: rx list init failed\n", | |
1099 | DEVNAME(sc)); | 1099 | DEVNAME(sc)); | |
1100 | goto fail4; | 1100 | goto fail4; | |
1101 | } | 1101 | } | |
1102 | 1102 | |||
1103 | for (i = 0; i < RNDIS_RX_LIST_CNT; i++) { | 1103 | for (i = 0; i < RNDIS_RX_LIST_CNT; i++) { | |
1104 | struct urndis_chain *c; | 1104 | struct urndis_chain *c; | |
1105 | 1105 | |||
1106 | c = &sc->sc_data.sc_rx_chain[i]; | 1106 | c = &sc->sc_data.sc_rx_chain[i]; | |
1107 | 1107 | |||
1108 | usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, RNDIS_BUFSZ, | 1108 | usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, RNDIS_BUFSZ, | |
1109 | USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, urndis_rxeof); | 1109 | USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, urndis_rxeof); | |
1110 | usbd_transfer(c->sc_xfer); | 1110 | usbd_transfer(c->sc_xfer); | |
1111 | } | 1111 | } | |
1112 | 1112 | |||
1113 | ifp->if_flags |= IFF_RUNNING; | 1113 | ifp->if_flags |= IFF_RUNNING; | |
1114 | ifp->if_flags &= ~IFF_OACTIVE; | 1114 | ifp->if_flags &= ~IFF_OACTIVE; | |
1115 | 1115 | |||
1116 | return 0; | 1116 | return 0; | |
1117 | 1117 | |||
1118 | fail4: | 1118 | fail4: | |
1119 | urndis_tx_list_free(sc); | 1119 | urndis_tx_list_free(sc); | |
1120 | fail3: | 1120 | fail3: | |
1121 | usbd_close_pipe(sc->sc_bulkout_pipe); | 1121 | usbd_close_pipe(sc->sc_bulkout_pipe); | |
1122 | fail2: | 1122 | fail2: | |
1123 | usbd_close_pipe(sc->sc_bulkin_pipe); | 1123 | usbd_close_pipe(sc->sc_bulkin_pipe); | |
1124 | fail: | 1124 | fail: | |
1125 | return EIO; | 1125 | return EIO; | |
1126 | } | 1126 | } | |
1127 | 1127 | |||
1128 | static void | 1128 | static void | |
1129 | urndis_stop(struct ifnet *ifp) | 1129 | urndis_stop(struct ifnet *ifp) | |
1130 | { | 1130 | { | |
1131 | struct urndis_softc *sc = ifp->if_softc; | 1131 | struct urndis_softc *sc = ifp->if_softc; | |
1132 | 1132 | |||
1133 | mutex_enter(&sc->urndis_lock); | 1133 | mutex_enter(&sc->sc_lock); | |
1134 | urndis_stop_locked(ifp); | 1134 | urndis_stop_locked(ifp); | |
1135 | mutex_exit(&sc->urndis_lock); | 1135 | mutex_exit(&sc->sc_lock); | |
1136 | } | 1136 | } | |
1137 | 1137 | |||
1138 | static void | 1138 | static void | |
1139 | urndis_stop_locked(struct ifnet *ifp) | 1139 | urndis_stop_locked(struct ifnet *ifp) | |
1140 | { | 1140 | { | |
1141 | struct urndis_softc *sc; | 1141 | struct urndis_softc *sc; | |
1142 | usbd_status err; | 1142 | usbd_status err; | |
1143 | 1143 | |||
1144 | sc = ifp->if_softc; | 1144 | sc = ifp->if_softc; | |
1145 | 1145 | |||
1146 | ifp->if_timer = 0; | 1146 | ifp->if_timer = 0; | |
1147 | ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); | 1147 | ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); | |
1148 | 1148 | |||
1149 | if (sc->sc_bulkin_pipe != NULL) { | 1149 | if (sc->sc_bulkin_pipe != NULL) { | |
1150 | err = usbd_abort_pipe(sc->sc_bulkin_pipe); | 1150 | err = usbd_abort_pipe(sc->sc_bulkin_pipe); | |
1151 | if (err) | 1151 | if (err) | |
1152 | printf("%s: abort rx pipe failed: %s\n", | 1152 | printf("%s: abort rx pipe failed: %s\n", | |
1153 | DEVNAME(sc), usbd_errstr(err)); | 1153 | DEVNAME(sc), usbd_errstr(err)); | |
1154 | } | 1154 | } | |
1155 | 1155 | |||
1156 | if (sc->sc_bulkout_pipe != NULL) { | 1156 | if (sc->sc_bulkout_pipe != NULL) { | |
1157 | err = usbd_abort_pipe(sc->sc_bulkout_pipe); | 1157 | err = usbd_abort_pipe(sc->sc_bulkout_pipe); | |
1158 | if (err) | 1158 | if (err) | |
1159 | printf("%s: abort tx pipe failed: %s\n", | 1159 | printf("%s: abort tx pipe failed: %s\n", | |
1160 | DEVNAME(sc), usbd_errstr(err)); | 1160 | DEVNAME(sc), usbd_errstr(err)); | |
1161 | } | 1161 | } | |
1162 | 1162 | |||
1163 | urndis_tx_list_free(sc); | 1163 | urndis_tx_list_free(sc); | |
1164 | 1164 | |||
1165 | urndis_rx_list_free(sc); | 1165 | urndis_rx_list_free(sc); | |
1166 | 1166 | |||
1167 | /* Close pipes. */ | 1167 | /* Close pipes. */ | |
1168 | if (sc->sc_bulkin_pipe != NULL) { | 1168 | if (sc->sc_bulkin_pipe != NULL) { | |
1169 | err = usbd_close_pipe(sc->sc_bulkin_pipe); | 1169 | err = usbd_close_pipe(sc->sc_bulkin_pipe); | |
1170 | if (err) | 1170 | if (err) | |
1171 | printf("%s: close rx pipe failed: %s\n", | 1171 | printf("%s: close rx pipe failed: %s\n", | |
1172 | DEVNAME(sc), usbd_errstr(err)); | 1172 | DEVNAME(sc), usbd_errstr(err)); | |
1173 | sc->sc_bulkin_pipe = NULL; | 1173 | sc->sc_bulkin_pipe = NULL; | |
1174 | } | 1174 | } | |
1175 | 1175 | |||
1176 | if (sc->sc_bulkout_pipe != NULL) { | 1176 | if (sc->sc_bulkout_pipe != NULL) { | |
1177 | err = usbd_close_pipe(sc->sc_bulkout_pipe); | 1177 | err = usbd_close_pipe(sc->sc_bulkout_pipe); | |
1178 | if (err) | 1178 | if (err) | |
1179 | printf("%s: close tx pipe failed: %s\n", | 1179 | printf("%s: close tx pipe failed: %s\n", | |
1180 | DEVNAME(sc), usbd_errstr(err)); | 1180 | DEVNAME(sc), usbd_errstr(err)); | |
1181 | sc->sc_bulkout_pipe = NULL; | 1181 | sc->sc_bulkout_pipe = NULL; | |
1182 | } | 1182 | } | |
1183 | } | 1183 | } | |
1184 | 1184 | |||
1185 | static void | 1185 | static void | |
1186 | urndis_start(struct ifnet *ifp) | 1186 | urndis_start(struct ifnet *ifp) | |
1187 | { | 1187 | { | |
1188 | struct urndis_softc *sc = ifp->if_softc; | 1188 | struct urndis_softc *sc = ifp->if_softc; | |
1189 | KASSERT(ifp->if_extflags & IFEF_START_MPSAFE); | 1189 | KASSERT(ifp->if_extflags & IFEF_START_MPSAFE); | |
1190 | 1190 | |||
1191 | mutex_enter(&sc->urndis_txlock); | 1191 | mutex_enter(&sc->sc_txlock); | |
1192 | urndis_start_locked(ifp); | 1192 | urndis_start_locked(ifp); | |
1193 | mutex_exit(&sc->urndis_txlock); | 1193 | mutex_exit(&sc->sc_txlock); | |
1194 | } | 1194 | } | |
1195 | 1195 | |||
1196 | static void | 1196 | static void | |
1197 | urndis_start_locked(struct ifnet *ifp) | 1197 | urndis_start_locked(struct ifnet *ifp) | |
1198 | { | 1198 | { | |
1199 | struct urndis_softc *sc; | 1199 | struct urndis_softc *sc; | |
1200 | struct mbuf *m_head = NULL; | 1200 | struct mbuf *m_head = NULL; | |
1201 | 1201 | |||
1202 | sc = ifp->if_softc; | 1202 | sc = ifp->if_softc; | |
1203 | 1203 | |||
1204 | if (sc->sc_dying || (ifp->if_flags & IFF_OACTIVE)) | 1204 | if (sc->sc_dying || (ifp->if_flags & IFF_OACTIVE)) | |
1205 | return; | 1205 | return; | |
1206 | 1206 | |||
1207 | IFQ_POLL(&ifp->if_snd, m_head); | 1207 | IFQ_POLL(&ifp->if_snd, m_head); | |
1208 | if (m_head == NULL) | 1208 | if (m_head == NULL) | |
1209 | return; | 1209 | return; | |
1210 | 1210 | |||
1211 | if (urndis_encap(sc, m_head, 0)) { | 1211 | if (urndis_encap(sc, m_head, 0)) { | |
1212 | ifp->if_flags |= IFF_OACTIVE; | 1212 | ifp->if_flags |= IFF_OACTIVE; | |
1213 | return; | 1213 | return; | |
1214 | } | 1214 | } | |
1215 | IFQ_DEQUEUE(&ifp->if_snd, m_head); | 1215 | IFQ_DEQUEUE(&ifp->if_snd, m_head); | |
1216 | 1216 | |||
1217 | /* | 1217 | /* | |
1218 | * If there's a BPF listener, bounce a copy of this frame | 1218 | * If there's a BPF listener, bounce a copy of this frame | |
1219 | * to him. | 1219 | * to him. | |
1220 | */ | 1220 | */ | |
1221 | bpf_mtap(ifp, m_head); | 1221 | bpf_mtap(ifp, m_head); | |
1222 | 1222 | |||
1223 | ifp->if_flags |= IFF_OACTIVE; | 1223 | ifp->if_flags |= IFF_OACTIVE; | |
1224 | 1224 | |||
1225 | /* | 1225 | /* | |
1226 | * Set a timeout in case the chip goes out to lunch. | 1226 | * Set a timeout in case the chip goes out to lunch. | |
1227 | */ | 1227 | */ | |
1228 | ifp->if_timer = 5; | 1228 | ifp->if_timer = 5; | |
1229 | 1229 | |||
1230 | return; | 1230 | return; | |
1231 | } | 1231 | } | |
1232 | 1232 | |||
1233 | static void | 1233 | static void | |
1234 | urndis_rxeof(struct usbd_xfer *xfer, | 1234 | urndis_rxeof(struct usbd_xfer *xfer, | |
1235 | void *priv, | 1235 | void *priv, | |
1236 | usbd_status status) | 1236 | usbd_status status) | |
1237 | { | 1237 | { | |
1238 | struct urndis_chain *c; | 1238 | struct urndis_chain *c; | |
1239 | struct urndis_softc *sc; | 1239 | struct urndis_softc *sc; | |
1240 | struct ifnet *ifp; | 1240 | struct ifnet *ifp; | |
1241 | uint32_t total_len; | 1241 | uint32_t total_len; | |
1242 | 1242 | |||
1243 | c = priv; | 1243 | c = priv; | |
1244 | sc = c->sc_softc; | 1244 | sc = c->sc_softc; | |
1245 | ifp = GET_IFP(sc); | 1245 | ifp = GET_IFP(sc); | |
1246 | total_len = 0; | 1246 | total_len = 0; | |
1247 | 1247 | |||
1248 | if (sc->sc_dying || !(ifp->if_flags & IFF_RUNNING)) | 1248 | if (sc->sc_dying || !(ifp->if_flags & IFF_RUNNING)) | |
1249 | return; | 1249 | return; | |
1250 | 1250 | |||
1251 | if (status != USBD_NORMAL_COMPLETION) { | 1251 | if (status != USBD_NORMAL_COMPLETION) { | |
1252 | if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) | 1252 | if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) | |
1253 | return; | 1253 | return; | |
1254 | if (usbd_ratecheck(&sc->sc_rx_notice)) { | 1254 | if (usbd_ratecheck(&sc->sc_rx_notice)) { | |
1255 | printf("%s: usb errors on rx: %s\n", | 1255 | printf("%s: usb errors on rx: %s\n", | |
1256 | DEVNAME(sc), usbd_errstr(status)); | 1256 | DEVNAME(sc), usbd_errstr(status)); | |
1257 | } | 1257 | } | |
1258 | if (status == USBD_STALLED) | 1258 | if (status == USBD_STALLED) | |
1259 | usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); | 1259 | usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe); | |
1260 | 1260 | |||
1261 | goto done; | 1261 | goto done; | |
1262 | } | 1262 | } | |
1263 | 1263 | |||
1264 | usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); | 1264 | usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); | |
1265 | urndis_decap(sc, c, total_len); | 1265 | urndis_decap(sc, c, total_len); | |
1266 | 1266 | |||
1267 | done: | 1267 | done: | |
1268 | /* Setup new transfer. */ | 1268 | /* Setup new transfer. */ | |
1269 | usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, RNDIS_BUFSZ, | 1269 | usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, RNDIS_BUFSZ, | |
1270 | USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, urndis_rxeof); | 1270 | USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, urndis_rxeof); | |
1271 | usbd_transfer(c->sc_xfer); | 1271 | usbd_transfer(c->sc_xfer); | |
1272 | } | 1272 | } | |
1273 | 1273 | |||
1274 | static void | 1274 | static void | |
1275 | urndis_txeof(struct usbd_xfer *xfer, | 1275 | urndis_txeof(struct usbd_xfer *xfer, | |
1276 | void *priv, | 1276 | void *priv, | |
1277 | usbd_status status) | 1277 | usbd_status status) | |
1278 | { | 1278 | { | |
1279 | struct urndis_chain *c; | 1279 | struct urndis_chain *c; | |
1280 | struct urndis_softc *sc; | 1280 | struct urndis_softc *sc; | |
1281 | struct ifnet *ifp; | 1281 | struct ifnet *ifp; | |
1282 | usbd_status err; | 1282 | usbd_status err; | |
1283 | int s; | 1283 | int s; | |
1284 | 1284 | |||
1285 | c = priv; | 1285 | c = priv; | |
1286 | sc = c->sc_softc; | 1286 | sc = c->sc_softc; | |
1287 | ifp = GET_IFP(sc); | 1287 | ifp = GET_IFP(sc); | |
1288 | 1288 | |||
1289 | DPRINTF(("%s: urndis_txeof\n", DEVNAME(sc))); | 1289 | DPRINTF(("%s: urndis_txeof\n", DEVNAME(sc))); | |
1290 | 1290 | |||
1291 | if (sc->sc_dying) | 1291 | if (sc->sc_dying) | |
1292 | return; | 1292 | return; | |
1293 | 1293 | |||
1294 | s = splnet(); | 1294 | s = splnet(); | |
1295 | 1295 | |||
1296 | ifp->if_timer = 0; | 1296 | ifp->if_timer = 0; | |
1297 | ifp->if_flags &= ~IFF_OACTIVE; | 1297 | ifp->if_flags &= ~IFF_OACTIVE; | |
1298 | 1298 | |||
1299 | if (status != USBD_NORMAL_COMPLETION) { | 1299 | if (status != USBD_NORMAL_COMPLETION) { | |
1300 | if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { | 1300 | if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { | |
1301 | splx(s); | 1301 | splx(s); | |
1302 | return; | 1302 | return; | |
1303 | } | 1303 | } | |
1304 | ifp->if_oerrors++; | 1304 | ifp->if_oerrors++; | |
1305 | printf("%s: usb error on tx: %s\n", DEVNAME(sc), | 1305 | printf("%s: usb error on tx: %s\n", DEVNAME(sc), | |
1306 | usbd_errstr(status)); | 1306 | usbd_errstr(status)); | |
1307 | if (status == USBD_STALLED) | 1307 | if (status == USBD_STALLED) | |
1308 | usbd_clear_endpoint_stall_async(sc->sc_bulkout_pipe); | 1308 | usbd_clear_endpoint_stall_async(sc->sc_bulkout_pipe); | |
1309 | splx(s); | 1309 | splx(s); | |
1310 | return; | 1310 | return; | |
1311 | } | 1311 | } | |
1312 | 1312 | |||
1313 | usbd_get_xfer_status(c->sc_xfer, NULL, NULL, NULL, &err); | 1313 | usbd_get_xfer_status(c->sc_xfer, NULL, NULL, NULL, &err); | |
1314 | 1314 | |||
1315 | if (c->sc_mbuf != NULL) { | 1315 | if (c->sc_mbuf != NULL) { | |
1316 | m_freem(c->sc_mbuf); | 1316 | m_freem(c->sc_mbuf); | |
1317 | c->sc_mbuf = NULL; | 1317 | c->sc_mbuf = NULL; | |
1318 | } | 1318 | } | |
1319 | 1319 | |||
1320 | if (err) | 1320 | if (err) | |
1321 | ifp->if_oerrors++; | 1321 | ifp->if_oerrors++; | |
1322 | else | 1322 | else | |
1323 | ifp->if_opackets++; | 1323 | ifp->if_opackets++; | |
1324 | 1324 | |||
1325 | if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) | 1325 | if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) | |
1326 | urndis_start(ifp); | 1326 | urndis_start(ifp); | |
1327 | 1327 | |||
1328 | splx(s); | 1328 | splx(s); | |
1329 | } | 1329 | } | |
1330 | 1330 | |||
1331 | static int | 1331 | static int | |
1332 | urndis_match(device_t parent, cfdata_t match, void *aux) | 1332 | urndis_match(device_t parent, cfdata_t match, void *aux) | |
1333 | { | 1333 | { | |
1334 | struct usbif_attach_arg *uiaa = aux; | 1334 | struct usbif_attach_arg *uiaa = aux; | |
1335 | usb_interface_descriptor_t *id; | 1335 | usb_interface_descriptor_t *id; | |
1336 | 1336 | |||
1337 | if (!uiaa->uiaa_iface) | 1337 | if (!uiaa->uiaa_iface) | |
1338 | return UMATCH_NONE; | 1338 | return UMATCH_NONE; | |
1339 | 1339 | |||
1340 | id = usbd_get_interface_descriptor(uiaa->uiaa_iface); | 1340 | id = usbd_get_interface_descriptor(uiaa->uiaa_iface); | |
1341 | if (id == NULL) | 1341 | if (id == NULL) | |
1342 | return UMATCH_NONE; | 1342 | return UMATCH_NONE; | |
1343 | 1343 | |||
1344 | if (id->bInterfaceClass == UICLASS_WIRELESS && | 1344 | if (id->bInterfaceClass == UICLASS_WIRELESS && | |
1345 | id->bInterfaceSubClass == UISUBCLASS_RF && | 1345 | id->bInterfaceSubClass == UISUBCLASS_RF && | |
1346 | id->bInterfaceProtocol == UIPROTO_RNDIS) | 1346 | id->bInterfaceProtocol == UIPROTO_RNDIS) | |
1347 | return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; | 1347 | return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; | |
1348 | 1348 | |||
1349 | return usb_lookup(urndis_devs, uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL ? | 1349 | return usb_lookup(urndis_devs, uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL ? | |
1350 | UMATCH_VENDOR_PRODUCT : UMATCH_NONE; | 1350 | UMATCH_VENDOR_PRODUCT : UMATCH_NONE; | |
1351 | } | 1351 | } | |
1352 | 1352 | |||
1353 | static void | 1353 | static void | |
1354 | urndis_attach(device_t parent, device_t self, void *aux) | 1354 | urndis_attach(device_t parent, device_t self, void *aux) | |
1355 | { | 1355 | { | |
1356 | struct urndis_softc *sc; | 1356 | struct urndis_softc *sc; | |
1357 | struct usbif_attach_arg *uiaa; | 1357 | struct usbif_attach_arg *uiaa; | |
1358 | struct ifnet *ifp; | 1358 | struct ifnet *ifp; | |
1359 | usb_interface_descriptor_t *id; | 1359 | usb_interface_descriptor_t *id; | |
1360 | usb_endpoint_descriptor_t *ed; | 1360 | usb_endpoint_descriptor_t *ed; | |
1361 | usb_config_descriptor_t *cd; | 1361 | usb_config_descriptor_t *cd; | |
1362 | const usb_cdc_union_descriptor_t *ud; | 1362 | const usb_cdc_union_descriptor_t *ud; | |
1363 | const usb_cdc_header_descriptor_t *desc; | 1363 | const usb_cdc_header_descriptor_t *desc; | |
1364 | usbd_desc_iter_t iter; | 1364 | usbd_desc_iter_t iter; | |
1365 | int if_ctl, if_data; | 1365 | int if_ctl, if_data; | |
1366 | int i, j, altcnt; | 1366 | int i, j, altcnt; | |
1367 | u_char eaddr[ETHER_ADDR_LEN]; | 1367 | u_char eaddr[ETHER_ADDR_LEN]; | |
1368 | void *buf; | 1368 | void *buf; | |
1369 | size_t bufsz; | 1369 | size_t bufsz; | |
1370 | uint32_t filter; | 1370 | uint32_t filter; | |
1371 | char *devinfop; | 1371 | char *devinfop; | |
1372 | 1372 | |||
1373 | sc = device_private(self); | 1373 | sc = device_private(self); | |
1374 | uiaa = aux; | 1374 | uiaa = aux; | |
1375 | sc->sc_dev = self; | 1375 | sc->sc_dev = self; | |
1376 | sc->sc_udev = uiaa->uiaa_device; | 1376 | sc->sc_udev = uiaa->uiaa_device; | |
1377 | 1377 | |||
1378 | aprint_naive("\n"); | 1378 | aprint_naive("\n"); | |
1379 | aprint_normal("\n"); | 1379 | aprint_normal("\n"); | |
1380 | 1380 | |||
1381 | devinfop = usbd_devinfo_alloc(uiaa->uiaa_device, 0); | 1381 | devinfop = usbd_devinfo_alloc(uiaa->uiaa_device, 0); | |
1382 | aprint_normal_dev(self, "%s\n", devinfop); | 1382 | aprint_normal_dev(self, "%s\n", devinfop); | |
1383 | usbd_devinfo_free(devinfop); | 1383 | usbd_devinfo_free(devinfop); | |
1384 | 1384 | |||
1385 | sc->sc_iface_ctl = uiaa->uiaa_iface; | 1385 | sc->sc_iface_ctl = uiaa->uiaa_iface; | |
1386 | id = usbd_get_interface_descriptor(sc->sc_iface_ctl); | 1386 | id = usbd_get_interface_descriptor(sc->sc_iface_ctl); | |
1387 | if_ctl = id->bInterfaceNumber; | 1387 | if_ctl = id->bInterfaceNumber; | |
1388 | sc->sc_ifaceno_ctl = if_ctl; | 1388 | sc->sc_ifaceno_ctl = if_ctl; | |
1389 | if_data = -1; | 1389 | if_data = -1; | |
1390 | 1390 | |||
1391 | usb_desc_iter_init(sc->sc_udev, &iter); | 1391 | usb_desc_iter_init(sc->sc_udev, &iter); | |
1392 | while ((desc = (const void *)usb_desc_iter_next(&iter)) != NULL) { | 1392 | while ((desc = (const void *)usb_desc_iter_next(&iter)) != NULL) { | |
1393 | 1393 | |||
1394 | if (desc->bDescriptorType != UDESC_CS_INTERFACE) { | 1394 | if (desc->bDescriptorType != UDESC_CS_INTERFACE) { | |
1395 | continue; | 1395 | continue; | |
1396 | } | 1396 | } | |
1397 | switch (desc->bDescriptorSubtype) { | 1397 | switch (desc->bDescriptorSubtype) { | |
1398 | case UDESCSUB_CDC_UNION: | 1398 | case UDESCSUB_CDC_UNION: | |
1399 | /* XXX bail out when found first? */ | 1399 | /* XXX bail out when found first? */ | |
1400 | ud = (const usb_cdc_union_descriptor_t *)desc; | 1400 | ud = (const usb_cdc_union_descriptor_t *)desc; | |
1401 | if (if_data == -1) | 1401 | if (if_data == -1) | |
1402 | if_data = ud->bSlaveInterface[0]; | 1402 | if_data = ud->bSlaveInterface[0]; | |
1403 | break; | 1403 | break; | |
1404 | } | 1404 | } | |
1405 | } | 1405 | } | |
1406 | 1406 | |||
1407 | if (if_data == -1) { | 1407 | if (if_data == -1) { | |
1408 | DPRINTF(("urndis_attach: no union interface\n")); | 1408 | DPRINTF(("urndis_attach: no union interface\n")); | |
1409 | sc->sc_iface_data = sc->sc_iface_ctl; | 1409 | sc->sc_iface_data = sc->sc_iface_ctl; | |
1410 | } else { | 1410 | } else { | |
1411 | DPRINTF(("urndis_attach: union interface: ctl %u, data %u\n", | 1411 | DPRINTF(("urndis_attach: union interface: ctl %u, data %u\n", | |
1412 | if_ctl, if_data)); | 1412 | if_ctl, if_data)); | |
1413 | for (i = 0; i < uiaa->uiaa_nifaces; i++) { | 1413 | for (i = 0; i < uiaa->uiaa_nifaces; i++) { | |
1414 | if (uiaa->uiaa_ifaces[i] != NULL) { | 1414 | if (uiaa->uiaa_ifaces[i] != NULL) { | |
1415 | id = usbd_get_interface_descriptor( | 1415 | id = usbd_get_interface_descriptor( | |
1416 | uiaa->uiaa_ifaces[i]); | 1416 | uiaa->uiaa_ifaces[i]); | |
1417 | if (id != NULL && id->bInterfaceNumber == | 1417 | if (id != NULL && id->bInterfaceNumber == | |
1418 | if_data) { | 1418 | if_data) { | |
1419 | sc->sc_iface_data = uiaa->uiaa_ifaces[i]; | 1419 | sc->sc_iface_data = uiaa->uiaa_ifaces[i]; | |
1420 | uiaa->uiaa_ifaces[i] = NULL; | 1420 | uiaa->uiaa_ifaces[i] = NULL; | |
1421 | } | 1421 | } | |
1422 | } | 1422 | } | |
1423 | } | 1423 | } | |
1424 | } | 1424 | } | |
1425 | 1425 | |||
1426 | if (sc->sc_iface_data == NULL) { | 1426 | if (sc->sc_iface_data == NULL) { | |
1427 | aprint_error("%s: no data interface\n", DEVNAME(sc)); | 1427 | aprint_error("%s: no data interface\n", DEVNAME(sc)); | |
1428 | return; | 1428 | return; | |
1429 | } | 1429 | } | |
1430 | 1430 | |||
1431 | id = usbd_get_interface_descriptor(sc->sc_iface_data); | 1431 | id = usbd_get_interface_descriptor(sc->sc_iface_data); | |
1432 | cd = usbd_get_config_descriptor(sc->sc_udev); | 1432 | cd = usbd_get_config_descriptor(sc->sc_udev); | |
1433 | altcnt = usbd_get_no_alts(cd, id->bInterfaceNumber); | 1433 | altcnt = usbd_get_no_alts(cd, id->bInterfaceNumber); | |
1434 | 1434 | |||
1435 | for (j = 0; j < altcnt; j++) { | 1435 | for (j = 0; j < altcnt; j++) { | |
1436 | if (usbd_set_interface(sc->sc_iface_data, j)) { | 1436 | if (usbd_set_interface(sc->sc_iface_data, j)) { | |
1437 | aprint_error("%s: interface alternate setting %u " | 1437 | aprint_error("%s: interface alternate setting %u " | |
1438 | "failed\n", DEVNAME(sc), j); | 1438 | "failed\n", DEVNAME(sc), j); | |
1439 | return; | 1439 | return; | |
1440 | } | 1440 | } | |
1441 | /* Find endpoints. */ | 1441 | /* Find endpoints. */ | |
1442 | id = usbd_get_interface_descriptor(sc->sc_iface_data); | 1442 | id = usbd_get_interface_descriptor(sc->sc_iface_data); | |
1443 | sc->sc_bulkin_no = sc->sc_bulkout_no = -1; | 1443 | sc->sc_bulkin_no = sc->sc_bulkout_no = -1; | |
1444 | for (i = 0; i < id->bNumEndpoints; i++) { | 1444 | for (i = 0; i < id->bNumEndpoints; i++) { | |
1445 | ed = usbd_interface2endpoint_descriptor( | 1445 | ed = usbd_interface2endpoint_descriptor( | |
1446 | sc->sc_iface_data, i); | 1446 | sc->sc_iface_data, i); | |
1447 | if (!ed) { | 1447 | if (!ed) { | |
1448 | aprint_error("%s: no descriptor for bulk " | 1448 | aprint_error("%s: no descriptor for bulk " | |
1449 | "endpoint %u\n", DEVNAME(sc), i); | 1449 | "endpoint %u\n", DEVNAME(sc), i); | |
1450 | return; | 1450 | return; | |
1451 | } | 1451 | } | |
1452 | if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && | 1452 | if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && | |
1453 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { | 1453 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { | |
1454 | sc->sc_bulkin_no = ed->bEndpointAddress; | 1454 | sc->sc_bulkin_no = ed->bEndpointAddress; | |
1455 | } | 1455 | } | |
1456 | else if ( | 1456 | else if ( | |
1457 | UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && | 1457 | UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && | |
1458 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { | 1458 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { | |
1459 | sc->sc_bulkout_no = ed->bEndpointAddress; | 1459 | sc->sc_bulkout_no = ed->bEndpointAddress; | |
1460 | } | 1460 | } | |
1461 | } | 1461 | } | |
1462 | 1462 | |||
1463 | if (sc->sc_bulkin_no != -1 && sc->sc_bulkout_no != -1) { | 1463 | if (sc->sc_bulkin_no != -1 && sc->sc_bulkout_no != -1) { | |
1464 | DPRINTF(("%s: in=0x%x, out=0x%x\n", | 1464 | DPRINTF(("%s: in=0x%x, out=0x%x\n", | |
1465 | DEVNAME(sc), | 1465 | DEVNAME(sc), | |
1466 | sc->sc_bulkin_no, | 1466 | sc->sc_bulkin_no, | |
1467 | sc->sc_bulkout_no)); | 1467 | sc->sc_bulkout_no)); | |
1468 | goto found; | 1468 | goto found; | |
1469 | } | 1469 | } | |
1470 | } | 1470 | } | |
1471 | 1471 | |||
1472 | if (sc->sc_bulkin_no == -1) | 1472 | if (sc->sc_bulkin_no == -1) | |
1473 | aprint_error("%s: could not find data bulk in\n", DEVNAME(sc)); | 1473 | aprint_error("%s: could not find data bulk in\n", DEVNAME(sc)); | |
1474 | if (sc->sc_bulkout_no == -1 ) | 1474 | if (sc->sc_bulkout_no == -1 ) | |
1475 | aprint_error("%s: could not find data bulk out\n",DEVNAME(sc)); | 1475 | aprint_error("%s: could not find data bulk out\n",DEVNAME(sc)); | |
1476 | return; | 1476 | return; | |
1477 | 1477 | |||
1478 | found: | 1478 | found: | |
1479 | mutex_init(&sc->urndis_lock, MUTEX_DEFAULT, IPL_NONE); | 1479 | mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); | |
1480 | mutex_init(&sc->urndis_txlock, MUTEX_DEFAULT, IPL_SOFTUSB); | 1480 | mutex_init(&sc->sc_txlock, MUTEX_DEFAULT, IPL_SOFTUSB); | |
1481 | mutex_init(&sc->urndis_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB); | 1481 | mutex_init(&sc->sc_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB); | |
1482 | 1482 | |||
1483 | ifp = GET_IFP(sc); | 1483 | ifp = GET_IFP(sc); | |
1484 | ifp->if_softc = sc; | 1484 | ifp->if_softc = sc; | |
1485 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | 1485 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | |
1486 | ifp->if_extflags = IFEF_START_MPSAFE; | 1486 | ifp->if_extflags = IFEF_START_MPSAFE; | |
1487 | ifp->if_start = urndis_start; | 1487 | ifp->if_start = urndis_start; | |
1488 | ifp->if_ioctl = urndis_ioctl; | 1488 | ifp->if_ioctl = urndis_ioctl; | |
1489 | ifp->if_init = urndis_init; | 1489 | ifp->if_init = urndis_init; | |
1490 | #if 0 | 1490 | #if 0 | |
1491 | ifp->if_watchdog = urndis_watchdog; | 1491 | ifp->if_watchdog = urndis_watchdog; | |
1492 | #endif | 1492 | #endif | |
1493 | 1493 | |||
1494 | strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); | 1494 | strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); | |
1495 | 1495 | |||
1496 | IFQ_SET_READY(&ifp->if_snd); | 1496 | IFQ_SET_READY(&ifp->if_snd); | |
1497 | 1497 | |||
1498 | urndis_init(ifp); | 1498 | urndis_init(ifp); | |
1499 | 1499 | |||
1500 | if (urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0, | 1500 | if (urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0, | |
1501 | &buf, &bufsz) != RNDIS_STATUS_SUCCESS) { | 1501 | &buf, &bufsz) != RNDIS_STATUS_SUCCESS) { | |
1502 | aprint_error("%s: unable to get hardware address\n", | 1502 | aprint_error("%s: unable to get hardware address\n", | |
1503 | DEVNAME(sc)); | 1503 | DEVNAME(sc)); | |
1504 | urndis_stop(ifp); | 1504 | urndis_stop(ifp); | |
1505 | goto fail; | 1505 | goto fail; | |
1506 | } | 1506 | } | |
1507 | 1507 | |||
1508 | if (bufsz == ETHER_ADDR_LEN) { | 1508 | if (bufsz == ETHER_ADDR_LEN) { | |
1509 | memcpy(eaddr, buf, ETHER_ADDR_LEN); | 1509 | memcpy(eaddr, buf, ETHER_ADDR_LEN); | |
1510 | aprint_normal("%s: address %s\n", DEVNAME(sc), | 1510 | aprint_normal("%s: address %s\n", DEVNAME(sc), | |
1511 | ether_sprintf(eaddr)); | 1511 | ether_sprintf(eaddr)); | |
1512 | kmem_free(buf, bufsz); | 1512 | kmem_free(buf, bufsz); | |
1513 | } else { | 1513 | } else { | |
1514 | aprint_error("%s: invalid address\n", DEVNAME(sc)); | 1514 | aprint_error("%s: invalid address\n", DEVNAME(sc)); | |
1515 | kmem_free(buf, bufsz); | 1515 | kmem_free(buf, bufsz); | |
1516 | urndis_stop(ifp); | 1516 | urndis_stop(ifp); | |
1517 | goto fail; | 1517 | goto fail; | |
1518 | } | 1518 | } | |
1519 | 1519 | |||
1520 | /* Initialize packet filter */ | 1520 | /* Initialize packet filter */ | |
1521 | sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST; | 1521 | sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST; | |
1522 | sc->sc_filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; | 1522 | sc->sc_filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; | |
1523 | filter = htole32(sc->sc_filter); | 1523 | filter = htole32(sc->sc_filter); | |
1524 | if (urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER, &filter, | 1524 | if (urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER, &filter, | |
1525 | sizeof(filter)) != RNDIS_STATUS_SUCCESS) { | 1525 | sizeof(filter)) != RNDIS_STATUS_SUCCESS) { | |
1526 | aprint_error("%s: unable to set data filters\n", DEVNAME(sc)); | 1526 | aprint_error("%s: unable to set data filters\n", DEVNAME(sc)); | |
1527 | urndis_stop(ifp); | 1527 | urndis_stop(ifp); | |
1528 | goto fail; | 1528 | goto fail; | |
1529 | } | 1529 | } | |
1530 | 1530 | |||
1531 | if_initialize(ifp); | 1531 | if_initialize(ifp); | |
1532 | sc->urndis_ipq = if_percpuq_create(&sc->sc_ec.ec_if); | 1532 | sc->urndis_ipq = if_percpuq_create(&sc->sc_ec.ec_if); | |
1533 | ether_ifattach(ifp, eaddr); | 1533 | ether_ifattach(ifp, eaddr); | |
1534 | if_register(ifp); | 1534 | if_register(ifp); | |
1535 | 1535 | |||
1536 | sc->sc_attached = 1; | 1536 | sc->sc_attached = 1; | |
1537 | return; | 1537 | return; | |
1538 | 1538 | |||
1539 | fail: | 1539 | fail: | |
1540 | mutex_destroy(&sc->urndis_lock); | 1540 | mutex_destroy(&sc->sc_lock); | |
1541 | mutex_destroy(&sc->urndis_txlock); | 1541 | mutex_destroy(&sc->sc_txlock); | |
1542 | mutex_destroy(&sc->urndis_rxlock); | 1542 | mutex_destroy(&sc->sc_rxlock); | |
1543 | } | 1543 | } | |
1544 | 1544 | |||
1545 | static int | 1545 | static int | |
1546 | urndis_detach(device_t self, int flags) | 1546 | urndis_detach(device_t self, int flags) | |
1547 | { | 1547 | { | |
1548 | struct urndis_softc *sc; | 1548 | struct urndis_softc *sc; | |
1549 | struct ifnet *ifp; | 1549 | struct ifnet *ifp; | |
1550 | int s; | 1550 | int s; | |
1551 | 1551 | |||
1552 | sc = device_private(self); | 1552 | sc = device_private(self); | |
1553 | 1553 | |||
1554 | DPRINTF(("urndis_detach: %s flags %u\n", DEVNAME(sc), | 1554 | DPRINTF(("urndis_detach: %s flags %u\n", DEVNAME(sc), | |
1555 | flags)); | 1555 | flags)); | |
1556 | 1556 | |||
1557 | if (!sc->sc_attached) | 1557 | if (!sc->sc_attached) | |
1558 | return 0; | 1558 | return 0; | |
1559 | 1559 | |||
1560 | s = splusb(); | 1560 | s = splusb(); | |
1561 | 1561 | |||
1562 | ifp = GET_IFP(sc); | 1562 | ifp = GET_IFP(sc); | |
1563 | 1563 | |||
1564 | if (ifp->if_softc != NULL) { | 1564 | if (ifp->if_softc != NULL) { | |
1565 | ether_ifdetach(ifp); | 1565 | ether_ifdetach(ifp); | |
1566 | if_detach(ifp); | 1566 | if_detach(ifp); | |
1567 | } | 1567 | } | |
1568 | 1568 | |||
1569 | urndis_stop(ifp); | 1569 | urndis_stop(ifp); | |
1570 | 1570 | |||
1571 | mutex_destroy(&sc->urndis_rxlock); | 1571 | mutex_destroy(&sc->sc_rxlock); | |
1572 | mutex_destroy(&sc->urndis_txlock); | 1572 | mutex_destroy(&sc->sc_txlock); | |
1573 | mutex_destroy(&sc->urndis_lock); | 1573 | mutex_destroy(&sc->sc_lock); | |
1574 | 1574 | |||
1575 | sc->sc_attached = 0; | 1575 | sc->sc_attached = 0; | |
1576 | 1576 | |||
1577 | splx(s); | 1577 | splx(s); | |
1578 | 1578 | |||
1579 | return 0; | 1579 | return 0; | |
1580 | } | 1580 | } | |
1581 | 1581 | |||
1582 | static int | 1582 | static int | |
1583 | urndis_activate(device_t self, enum devact act) | 1583 | urndis_activate(device_t self, enum devact act) | |
1584 | { | 1584 | { | |
1585 | struct urndis_softc *sc; | 1585 | struct urndis_softc *sc; | |
1586 | 1586 | |||
1587 | sc = device_private(self); | 1587 | sc = device_private(self); | |
1588 | 1588 | |||
1589 | switch (act) { | 1589 | switch (act) { | |
1590 | case DVACT_DEACTIVATE: | 1590 | case DVACT_DEACTIVATE: | |
1591 | sc->sc_dying = 1; | 1591 | sc->sc_dying = 1; | |
1592 | return 0; | 1592 | return 0; | |
1593 | } | 1593 | } | |
1594 | 1594 | |||
1595 | return EOPNOTSUPP; | 1595 | return EOPNOTSUPP; | |
1596 | } | 1596 | } | |
1597 | 1597 |
--- src/sys/dev/usb/Attic/if_urndisreg.h 2016/12/28 08:55:20 1.1.32.4
+++ src/sys/dev/usb/Attic/if_urndisreg.h 2017/01/26 12:40:16 1.1.32.5
@@ -1,313 +1,313 @@ | @@ -1,313 +1,313 @@ | |||
1 | /* $NetBSD: if_urndisreg.h,v 1.1.32.4 2016/12/28 08:55:20 skrll Exp $ */ | 1 | /* $NetBSD: if_urndisreg.h,v 1.1.32.5 2017/01/26 12:40:16 skrll Exp $ */ | |
2 | /* $OpenBSD: if_urndisreg.h,v 1.14 2010/07/08 18:22:01 ckuethe Exp $ */ | 2 | /* $OpenBSD: if_urndisreg.h,v 1.14 2010/07/08 18:22:01 ckuethe Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 2010 Jonathan Armani <armani@openbsd.org> | 5 | * Copyright (c) 2010 Jonathan Armani <armani@openbsd.org> | |
6 | * Copyright (c) 2010 Fabien Romano <fabien@openbsd.org> | 6 | * Copyright (c) 2010 Fabien Romano <fabien@openbsd.org> | |
7 | * Copyright (c) 2010 Michael Knudsen <mk@openbsd.org> | 7 | * Copyright (c) 2010 Michael Knudsen <mk@openbsd.org> | |
8 | * All rights reserved. | 8 | * All rights reserved. | |
9 | * | 9 | * | |
10 | * Permission to use, copy, modify, and distribute this software for any | 10 | * Permission to use, copy, modify, and distribute this software for any | |
11 | * purpose with or without fee is hereby granted, provided that the above | 11 | * purpose with or without fee is hereby granted, provided that the above | |
12 | * copyright notice and this permission notice appear in all copies. | 12 | * copyright notice and this permission notice appear in all copies. | |
13 | * | 13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 14 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
15 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 15 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
16 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 16 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
17 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 17 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
18 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 18 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
19 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 19 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
20 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 20 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
21 | */ | 21 | */ | |
22 | 22 | |||
23 | #define RNDIS_RX_LIST_CNT 1 | 23 | #define RNDIS_RX_LIST_CNT 1 | |
24 | #define RNDIS_TX_LIST_CNT 1 | 24 | #define RNDIS_TX_LIST_CNT 1 | |
25 | #define RNDIS_BUFSZ 1562 | 25 | #define RNDIS_BUFSZ 1562 | |
26 | 26 | |||
27 | struct urndis_chain { | 27 | struct urndis_chain { | |
28 | struct urndis_softc *sc_softc; | 28 | struct urndis_softc *sc_softc; | |
29 | struct usbd_xfer *sc_xfer; | 29 | struct usbd_xfer *sc_xfer; | |
30 | char *sc_buf; | 30 | char *sc_buf; | |
31 | struct mbuf *sc_mbuf; | 31 | struct mbuf *sc_mbuf; | |
32 | int sc_idx; | 32 | int sc_idx; | |
33 | }; | 33 | }; | |
34 | 34 | |||
35 | struct urndis_cdata { | 35 | struct urndis_cdata { | |
36 | struct urndis_chain sc_rx_chain[RNDIS_RX_LIST_CNT]; | 36 | struct urndis_chain sc_rx_chain[RNDIS_RX_LIST_CNT]; | |
37 | struct urndis_chain sc_tx_chain[RNDIS_TX_LIST_CNT]; | 37 | struct urndis_chain sc_tx_chain[RNDIS_TX_LIST_CNT]; | |
38 | int sc_tx_cnt; | 38 | int sc_tx_cnt; | |
39 | }; | 39 | }; | |
40 | 40 | |||
41 | #define GET_IFP(sc) (&(sc)->sc_ec.ec_if) | 41 | #define GET_IFP(sc) (&(sc)->sc_ec.ec_if) | |
42 | struct urndis_softc { | 42 | struct urndis_softc { | |
43 | device_t sc_dev; | 43 | device_t sc_dev; | |
44 | 44 | |||
45 | kmutex_t urndis_lock; | 45 | kmutex_t sc_lock; | |
46 | kmutex_t urndis_txlock; | 46 | kmutex_t sc_txlock; | |
47 | kmutex_t urndis_rxlock; | 47 | kmutex_t sc_rxlock; | |
48 | 48 | |||
49 | char sc_attached; | 49 | char sc_attached; | |
50 | int sc_dying; | 50 | int sc_dying; | |
51 | struct ethercom sc_ec; | 51 | struct ethercom sc_ec; | |
52 | 52 | |||
53 | /* RNDIS device info */ | 53 | /* RNDIS device info */ | |
54 | uint32_t sc_lim_pktsz; | 54 | uint32_t sc_lim_pktsz; | |
55 | uint32_t sc_filter; | 55 | uint32_t sc_filter; | |
56 | 56 | |||
57 | /* USB goo */ | 57 | /* USB goo */ | |
58 | struct usbd_device * sc_udev; | 58 | struct usbd_device * sc_udev; | |
59 | int sc_ifaceno_ctl; | 59 | int sc_ifaceno_ctl; | |
60 | struct usbd_interface * sc_iface_ctl; | 60 | struct usbd_interface * sc_iface_ctl; | |
61 | struct usbd_interface * sc_iface_data; | 61 | struct usbd_interface * sc_iface_data; | |
62 | 62 | |||
63 | struct timeval sc_rx_notice; | 63 | struct timeval sc_rx_notice; | |
64 | int sc_bulkin_no; | 64 | int sc_bulkin_no; | |
65 | struct usbd_pipe * sc_bulkin_pipe; | 65 | struct usbd_pipe * sc_bulkin_pipe; | |
66 | int sc_bulkout_no; | 66 | int sc_bulkout_no; | |
67 | struct usbd_pipe * sc_bulkout_pipe; | 67 | struct usbd_pipe * sc_bulkout_pipe; | |
68 | 68 | |||
69 | struct urndis_cdata sc_data; | 69 | struct urndis_cdata sc_data; | |
70 | 70 | |||
71 | struct if_percpuq * urndis_ipq; | 71 | struct if_percpuq * urndis_ipq; | |
72 | }; | 72 | }; | |
73 | 73 | |||
74 | #define RNDIS_STATUS_BUFFER_OVERFLOW 0x80000005L | 74 | #define RNDIS_STATUS_BUFFER_OVERFLOW 0x80000005L | |
75 | #define RNDIS_STATUS_FAILURE 0xC0000001L | 75 | #define RNDIS_STATUS_FAILURE 0xC0000001L | |
76 | #define RNDIS_STATUS_INVALID_DATA 0xC0010015L | 76 | #define RNDIS_STATUS_INVALID_DATA 0xC0010015L | |
77 | #define RNDIS_STATUS_MEDIA_CONNECT 0x4001000BL | 77 | #define RNDIS_STATUS_MEDIA_CONNECT 0x4001000BL | |
78 | #define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000CL | 78 | #define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000CL | |
79 | #define RNDIS_STATUS_NOT_SUPPORTED 0xC00000BBL | 79 | #define RNDIS_STATUS_NOT_SUPPORTED 0xC00000BBL | |
80 | #define RNDIS_STATUS_PENDING STATUS_PENDING /* XXX */ | 80 | #define RNDIS_STATUS_PENDING STATUS_PENDING /* XXX */ | |
81 | #define RNDIS_STATUS_RESOURCES 0xC000009AL | 81 | #define RNDIS_STATUS_RESOURCES 0xC000009AL | |
82 | #define RNDIS_STATUS_SUCCESS 0x00000000L | 82 | #define RNDIS_STATUS_SUCCESS 0x00000000L | |
83 | 83 | |||
84 | #define OID_GEN_SUPPORTED_LIST 0x00010101 | 84 | #define OID_GEN_SUPPORTED_LIST 0x00010101 | |
85 | #define OID_GEN_HARDWARE_STATUS 0x00010102 | 85 | #define OID_GEN_HARDWARE_STATUS 0x00010102 | |
86 | #define OID_GEN_MEDIA_SUPPORTED 0x00010103 | 86 | #define OID_GEN_MEDIA_SUPPORTED 0x00010103 | |
87 | #define OID_GEN_MEDIA_IN_USE 0x00010104 | 87 | #define OID_GEN_MEDIA_IN_USE 0x00010104 | |
88 | #define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 | 88 | #define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 | |
89 | #define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 | 89 | #define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 | |
90 | #define OID_GEN_LINK_SPEED 0x00010107 | 90 | #define OID_GEN_LINK_SPEED 0x00010107 | |
91 | #define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 | 91 | #define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 | |
92 | #define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 | 92 | #define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 | |
93 | #define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A | 93 | #define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A | |
94 | #define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B | 94 | #define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B | |
95 | #define OID_GEN_VENDOR_ID 0x0001010C | 95 | #define OID_GEN_VENDOR_ID 0x0001010C | |
96 | #define OID_GEN_VENDOR_DESCRIPTION 0x0001010D | 96 | #define OID_GEN_VENDOR_DESCRIPTION 0x0001010D | |
97 | #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E | 97 | #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E | |
98 | #define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F | 98 | #define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F | |
99 | #define OID_GEN_DRIVER_VERSION 0x00010110 | 99 | #define OID_GEN_DRIVER_VERSION 0x00010110 | |
100 | #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 | 100 | #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 | |
101 | #define OID_GEN_PROTOCOL_OPTIONS 0x00010112 | 101 | #define OID_GEN_PROTOCOL_OPTIONS 0x00010112 | |
102 | #define OID_GEN_MAC_OPTIONS 0x00010113 | 102 | #define OID_GEN_MAC_OPTIONS 0x00010113 | |
103 | #define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 | 103 | #define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 | |
104 | #define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 | 104 | #define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 | |
105 | #define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 | 105 | #define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 | |
106 | #define OID_GEN_SUPPORTED_GUIDS 0x00010117 | 106 | #define OID_GEN_SUPPORTED_GUIDS 0x00010117 | |
107 | #define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 | 107 | #define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 | |
108 | #define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 | 108 | #define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 | |
109 | #define OID_GEN_MACHINE_NAME 0x0001021A | 109 | #define OID_GEN_MACHINE_NAME 0x0001021A | |
110 | #define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B | 110 | #define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B | |
111 | #define OID_GEN_VLAN_ID 0x0001021C | 111 | #define OID_GEN_VLAN_ID 0x0001021C | |
112 | 112 | |||
113 | #define OID_802_3_PERMANENT_ADDRESS 0x01010101 | 113 | #define OID_802_3_PERMANENT_ADDRESS 0x01010101 | |
114 | #define OID_802_3_CURRENT_ADDRESS 0x01010102 | 114 | #define OID_802_3_CURRENT_ADDRESS 0x01010102 | |
115 | #define OID_802_3_MULTICAST_LIST 0x01010103 | 115 | #define OID_802_3_MULTICAST_LIST 0x01010103 | |
116 | #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 | 116 | #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 | |
117 | #define OID_802_3_MAC_OPTIONS 0x01010105 | 117 | #define OID_802_3_MAC_OPTIONS 0x01010105 | |
118 | #define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 | 118 | #define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 | |
119 | #define OID_802_3_XMIT_ONE_COLLISION 0x01020102 | 119 | #define OID_802_3_XMIT_ONE_COLLISION 0x01020102 | |
120 | #define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 | 120 | #define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 | |
121 | #define OID_802_3_XMIT_DEFERRED 0x01020201 | 121 | #define OID_802_3_XMIT_DEFERRED 0x01020201 | |
122 | #define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 | 122 | #define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 | |
123 | #define OID_802_3_RCV_OVERRUN 0x01020203 | 123 | #define OID_802_3_RCV_OVERRUN 0x01020203 | |
124 | #define OID_802_3_XMIT_UNDERRUN 0x01020204 | 124 | #define OID_802_3_XMIT_UNDERRUN 0x01020204 | |
125 | #define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 | 125 | #define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 | |
126 | #define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 | 126 | #define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 | |
127 | #define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 | 127 | #define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 | |
128 | 128 | |||
129 | #define RNDIS_MEDIUM_802_3 0x00000000 | 129 | #define RNDIS_MEDIUM_802_3 0x00000000 | |
130 | 130 | |||
131 | /* Device flags */ | 131 | /* Device flags */ | |
132 | #define RNDIS_DF_CONNECTIONLESS 0x00000001 | 132 | #define RNDIS_DF_CONNECTIONLESS 0x00000001 | |
133 | #define RNDIS_DF_CONNECTION_ORIENTED 0x00000002 | 133 | #define RNDIS_DF_CONNECTION_ORIENTED 0x00000002 | |
134 | 134 | |||
135 | /* | 135 | /* | |
136 | * RNDIS data message | 136 | * RNDIS data message | |
137 | */ | 137 | */ | |
138 | #define REMOTE_NDIS_PACKET_MSG 0x00000001 | 138 | #define REMOTE_NDIS_PACKET_MSG 0x00000001 | |
139 | 139 | |||
140 | 140 | |||
141 | struct urndis_packet_msg { | 141 | struct urndis_packet_msg { | |
142 | uint32_t rm_type; | 142 | uint32_t rm_type; | |
143 | uint32_t rm_len; | 143 | uint32_t rm_len; | |
144 | uint32_t rm_dataoffset; | 144 | uint32_t rm_dataoffset; | |
145 | uint32_t rm_datalen; | 145 | uint32_t rm_datalen; | |
146 | uint32_t rm_oobdataoffset; | 146 | uint32_t rm_oobdataoffset; | |
147 | uint32_t rm_oobdatalen; | 147 | uint32_t rm_oobdatalen; | |
148 | uint32_t rm_oobdataelements; | 148 | uint32_t rm_oobdataelements; | |
149 | uint32_t rm_pktinfooffset; | 149 | uint32_t rm_pktinfooffset; | |
150 | uint32_t rm_pktinfolen; | 150 | uint32_t rm_pktinfolen; | |
151 | uint32_t rm_vchandle; | 151 | uint32_t rm_vchandle; | |
152 | uint32_t rm_reserved; | 152 | uint32_t rm_reserved; | |
153 | }; | 153 | }; | |
154 | 154 | |||
155 | /* | 155 | /* | |
156 | * RNDIS control messages | 156 | * RNDIS control messages | |
157 | */ | 157 | */ | |
158 | struct urndis_comp_hdr { | 158 | struct urndis_comp_hdr { | |
159 | uint32_t rm_type; | 159 | uint32_t rm_type; | |
160 | uint32_t rm_len; | 160 | uint32_t rm_len; | |
161 | uint32_t rm_rid; | 161 | uint32_t rm_rid; | |
162 | uint32_t rm_status; | 162 | uint32_t rm_status; | |
163 | }; | 163 | }; | |
164 | 164 | |||
165 | /* Initialize the device. */ | 165 | /* Initialize the device. */ | |
166 | #define REMOTE_NDIS_INITIALIZE_MSG 0x00000002 | 166 | #define REMOTE_NDIS_INITIALIZE_MSG 0x00000002 | |
167 | #define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002 | 167 | #define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002 | |
168 | 168 | |||
169 | struct urndis_init_req { | 169 | struct urndis_init_req { | |
170 | uint32_t rm_type; | 170 | uint32_t rm_type; | |
171 | uint32_t rm_len; | 171 | uint32_t rm_len; | |
172 | uint32_t rm_rid; | 172 | uint32_t rm_rid; | |
173 | uint32_t rm_ver_major; | 173 | uint32_t rm_ver_major; | |
174 | uint32_t rm_ver_minor; | 174 | uint32_t rm_ver_minor; | |
175 | uint32_t rm_max_xfersz; | 175 | uint32_t rm_max_xfersz; | |
176 | }; | 176 | }; | |
177 | 177 | |||
178 | struct urndis_init_comp { | 178 | struct urndis_init_comp { | |
179 | uint32_t rm_type; | 179 | uint32_t rm_type; | |
180 | uint32_t rm_len; | 180 | uint32_t rm_len; | |
181 | uint32_t rm_rid; | 181 | uint32_t rm_rid; | |
182 | uint32_t rm_status; | 182 | uint32_t rm_status; | |
183 | uint32_t rm_ver_major; | 183 | uint32_t rm_ver_major; | |
184 | uint32_t rm_ver_minor; | 184 | uint32_t rm_ver_minor; | |
185 | uint32_t rm_devflags; | 185 | uint32_t rm_devflags; | |
186 | uint32_t rm_medium; | 186 | uint32_t rm_medium; | |
187 | uint32_t rm_pktmaxcnt; | 187 | uint32_t rm_pktmaxcnt; | |
188 | uint32_t rm_pktmaxsz; | 188 | uint32_t rm_pktmaxsz; | |
189 | uint32_t rm_align; | 189 | uint32_t rm_align; | |
190 | uint32_t rm_aflistoffset; | 190 | uint32_t rm_aflistoffset; | |
191 | uint32_t rm_aflistsz; | 191 | uint32_t rm_aflistsz; | |
192 | }; | 192 | }; | |
193 | 193 | |||
194 | /* Halt the device. No response sent. */ | 194 | /* Halt the device. No response sent. */ | |
195 | #define REMOTE_NDIS_HALT_MSG 0x00000003 | 195 | #define REMOTE_NDIS_HALT_MSG 0x00000003 | |
196 | 196 | |||
197 | struct urndis_halt_req { | 197 | struct urndis_halt_req { | |
198 | uint32_t rm_type; | 198 | uint32_t rm_type; | |
199 | uint32_t rm_len; | 199 | uint32_t rm_len; | |
200 | uint32_t rm_rid; | 200 | uint32_t rm_rid; | |
201 | }; | 201 | }; | |
202 | 202 | |||
203 | /* Send a query object. */ | 203 | /* Send a query object. */ | |
204 | #define REMOTE_NDIS_QUERY_MSG 0x00000004 | 204 | #define REMOTE_NDIS_QUERY_MSG 0x00000004 | |
205 | #define REMOTE_NDIS_QUERY_CMPLT 0x80000004 | 205 | #define REMOTE_NDIS_QUERY_CMPLT 0x80000004 | |
206 | 206 | |||
207 | struct urndis_query_req { | 207 | struct urndis_query_req { | |
208 | uint32_t rm_type; | 208 | uint32_t rm_type; | |
209 | uint32_t rm_len; | 209 | uint32_t rm_len; | |
210 | uint32_t rm_rid; | 210 | uint32_t rm_rid; | |
211 | uint32_t rm_oid; | 211 | uint32_t rm_oid; | |
212 | uint32_t rm_infobuflen; | 212 | uint32_t rm_infobuflen; | |
213 | uint32_t rm_infobufoffset; | 213 | uint32_t rm_infobufoffset; | |
214 | uint32_t rm_devicevchdl; | 214 | uint32_t rm_devicevchdl; | |
215 | }; | 215 | }; | |
216 | 216 | |||
217 | struct urndis_query_comp { | 217 | struct urndis_query_comp { | |
218 | uint32_t rm_type; | 218 | uint32_t rm_type; | |
219 | uint32_t rm_len; | 219 | uint32_t rm_len; | |
220 | uint32_t rm_rid; | 220 | uint32_t rm_rid; | |
221 | uint32_t rm_status; | 221 | uint32_t rm_status; | |
222 | uint32_t rm_infobuflen; | 222 | uint32_t rm_infobuflen; | |
223 | uint32_t rm_infobufoffset; | 223 | uint32_t rm_infobufoffset; | |
224 | }; | 224 | }; | |
225 | 225 | |||
226 | /* Send a set object request. */ | 226 | /* Send a set object request. */ | |
227 | #define REMOTE_NDIS_SET_MSG 0x00000005 | 227 | #define REMOTE_NDIS_SET_MSG 0x00000005 | |
228 | #define REMOTE_NDIS_SET_CMPLT 0x80000005 | 228 | #define REMOTE_NDIS_SET_CMPLT 0x80000005 | |
229 | 229 | |||
230 | struct urndis_set_req { | 230 | struct urndis_set_req { | |
231 | uint32_t rm_type; | 231 | uint32_t rm_type; | |
232 | uint32_t rm_len; | 232 | uint32_t rm_len; | |
233 | uint32_t rm_rid; | 233 | uint32_t rm_rid; | |
234 | uint32_t rm_oid; | 234 | uint32_t rm_oid; | |
235 | uint32_t rm_infobuflen; | 235 | uint32_t rm_infobuflen; | |
236 | uint32_t rm_infobufoffset; | 236 | uint32_t rm_infobufoffset; | |
237 | uint32_t rm_devicevchdl; | 237 | uint32_t rm_devicevchdl; | |
238 | }; | 238 | }; | |
239 | 239 | |||
240 | struct urndis_set_comp { | 240 | struct urndis_set_comp { | |
241 | uint32_t rm_type; | 241 | uint32_t rm_type; | |
242 | uint32_t rm_len; | 242 | uint32_t rm_len; | |
243 | uint32_t rm_rid; | 243 | uint32_t rm_rid; | |
244 | uint32_t rm_status; | 244 | uint32_t rm_status; | |
245 | }; | 245 | }; | |
246 | 246 | |||
247 | #define REMOTE_NDIS_SET_PARAM_NUMERIC 0x00000000 | 247 | #define REMOTE_NDIS_SET_PARAM_NUMERIC 0x00000000 | |
248 | #define REMOTE_NDIS_SET_PARAM_STRING 0x00000002 | 248 | #define REMOTE_NDIS_SET_PARAM_STRING 0x00000002 | |
249 | 249 | |||
250 | struct urndis_set_parameter { | 250 | struct urndis_set_parameter { | |
251 | uint32_t rm_nameoffset; | 251 | uint32_t rm_nameoffset; | |
252 | uint32_t rm_namelen; | 252 | uint32_t rm_namelen; | |
253 | uint32_t rm_type; | 253 | uint32_t rm_type; | |
254 | uint32_t rm_valueoffset; | 254 | uint32_t rm_valueoffset; | |
255 | uint32_t rm_valuelen; | 255 | uint32_t rm_valuelen; | |
256 | }; | 256 | }; | |
257 | 257 | |||
258 | /* Perform a soft reset on the device. */ | 258 | /* Perform a soft reset on the device. */ | |
259 | #define REMOTE_NDIS_RESET_MSG 0x00000006 | 259 | #define REMOTE_NDIS_RESET_MSG 0x00000006 | |
260 | #define REMOTE_NDIS_RESET_CMPLT 0x80000006 | 260 | #define REMOTE_NDIS_RESET_CMPLT 0x80000006 | |
261 | 261 | |||
262 | struct urndis_reset_req { | 262 | struct urndis_reset_req { | |
263 | uint32_t rm_type; | 263 | uint32_t rm_type; | |
264 | uint32_t rm_len; | 264 | uint32_t rm_len; | |
265 | uint32_t rm_rid; | 265 | uint32_t rm_rid; | |
266 | }; | 266 | }; | |
267 | 267 | |||
268 | struct urndis_reset_comp { | 268 | struct urndis_reset_comp { | |
269 | uint32_t rm_type; | 269 | uint32_t rm_type; | |
270 | uint32_t rm_len; | 270 | uint32_t rm_len; | |
271 | uint32_t rm_status; | 271 | uint32_t rm_status; | |
272 | uint32_t rm_adrreset; | 272 | uint32_t rm_adrreset; | |
273 | }; | 273 | }; | |
274 | 274 | |||
275 | /* 802.3 link-state or undefined message error. */ | 275 | /* 802.3 link-state or undefined message error. */ | |
276 | #define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007 | 276 | #define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007 | |
277 | 277 | |||
278 | /* Keepalive messsage. May be sent by device. */ | 278 | /* Keepalive messsage. May be sent by device. */ | |
279 | #define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008 | 279 | #define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008 | |
280 | #define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008 | 280 | #define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008 | |
281 | 281 | |||
282 | struct urndis_keepalive_req { | 282 | struct urndis_keepalive_req { | |
283 | uint32_t rm_type; | 283 | uint32_t rm_type; | |
284 | uint32_t rm_len; | 284 | uint32_t rm_len; | |
285 | uint32_t rm_rid; | 285 | uint32_t rm_rid; | |
286 | }; | 286 | }; | |
287 | 287 | |||
288 | struct urndis_keepalive_comp { | 288 | struct urndis_keepalive_comp { | |
289 | uint32_t rm_type; | 289 | uint32_t rm_type; | |
290 | uint32_t rm_len; | 290 | uint32_t rm_len; | |
291 | uint32_t rm_rid; | 291 | uint32_t rm_rid; | |
292 | uint32_t rm_status; | 292 | uint32_t rm_status; | |
293 | }; | 293 | }; | |
294 | 294 | |||
295 | /* packet filter bits used by OID_GEN_CURRENT_PACKET_FILTER */ | 295 | /* packet filter bits used by OID_GEN_CURRENT_PACKET_FILTER */ | |
296 | #define RNDIS_PACKET_TYPE_DIRECTED 0x00000001 | 296 | #define RNDIS_PACKET_TYPE_DIRECTED 0x00000001 | |
297 | #define RNDIS_PACKET_TYPE_MULTICAST 0x00000002 | 297 | #define RNDIS_PACKET_TYPE_MULTICAST 0x00000002 | |
298 | #define RNDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 | 298 | #define RNDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 | |
299 | #define RNDIS_PACKET_TYPE_BROADCAST 0x00000008 | 299 | #define RNDIS_PACKET_TYPE_BROADCAST 0x00000008 | |
300 | #define RNDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 | 300 | #define RNDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 | |
301 | #define RNDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 | 301 | #define RNDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 | |
302 | #define RNDIS_PACKET_TYPE_SMT 0x00000040 | 302 | #define RNDIS_PACKET_TYPE_SMT 0x00000040 | |
303 | #define RNDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 | 303 | #define RNDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 | |
304 | #define RNDIS_PACKET_TYPE_GROUP 0x00001000 | 304 | #define RNDIS_PACKET_TYPE_GROUP 0x00001000 | |
305 | #define RNDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00002000 | 305 | #define RNDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00002000 | |
306 | #define RNDIS_PACKET_TYPE_FUNCTIONAL 0x00004000 | 306 | #define RNDIS_PACKET_TYPE_FUNCTIONAL 0x00004000 | |
307 | #define RNDIS_PACKET_TYPE_MAC_FRAME 0x00008000 | 307 | #define RNDIS_PACKET_TYPE_MAC_FRAME 0x00008000 | |
308 | 308 | |||
309 | /* Rndis offsets */ | 309 | /* Rndis offsets */ | |
310 | #define RNDIS_HEADER_OFFSET (sizeof(uint32_t) * 2) | 310 | #define RNDIS_HEADER_OFFSET (sizeof(uint32_t) * 2) | |
311 | #define RNDIS_DATA_OFFSET (sizeof(struct urndis_packet_msg) - \ | 311 | #define RNDIS_DATA_OFFSET (sizeof(struct urndis_packet_msg) - \ | |
312 | offsetof(struct urndis_packet_msg, \ | 312 | offsetof(struct urndis_packet_msg, \ | |
313 | rm_dataoffset)) | 313 | rm_dataoffset)) |