if_cdce.c revision 1.4.2.2 1 1.4.2.2 skrll /* $NetBSD: if_cdce.c,v 1.4.2.2 2004/11/02 07:53:02 skrll Exp $ */
2 1.4.2.2 skrll
3 1.4.2.2 skrll /*
4 1.4.2.2 skrll * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul (at) windriver.com>
5 1.4.2.2 skrll * Copyright (c) 2003 Craig Boston
6 1.4.2.2 skrll * Copyright (c) 2004 Daniel Hartmeier
7 1.4.2.2 skrll * All rights reserved.
8 1.4.2.2 skrll *
9 1.4.2.2 skrll * Redistribution and use in source and binary forms, with or without
10 1.4.2.2 skrll * modification, are permitted provided that the following conditions
11 1.4.2.2 skrll * are met:
12 1.4.2.2 skrll * 1. Redistributions of source code must retain the above copyright
13 1.4.2.2 skrll * notice, this list of conditions and the following disclaimer.
14 1.4.2.2 skrll * 2. Redistributions in binary form must reproduce the above copyright
15 1.4.2.2 skrll * notice, this list of conditions and the following disclaimer in the
16 1.4.2.2 skrll * documentation and/or other materials provided with the distribution.
17 1.4.2.2 skrll * 3. All advertising materials mentioning features or use of this software
18 1.4.2.2 skrll * must display the following acknowledgement:
19 1.4.2.2 skrll * This product includes software developed by Bill Paul.
20 1.4.2.2 skrll * 4. Neither the name of the author nor the names of any co-contributors
21 1.4.2.2 skrll * may be used to endorse or promote products derived from this software
22 1.4.2.2 skrll * without specific prior written permission.
23 1.4.2.2 skrll *
24 1.4.2.2 skrll * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
25 1.4.2.2 skrll * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 1.4.2.2 skrll * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 1.4.2.2 skrll * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul, THE VOICES IN HIS HEAD OR
28 1.4.2.2 skrll * THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 1.4.2.2 skrll * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 1.4.2.2 skrll * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
31 1.4.2.2 skrll * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 1.4.2.2 skrll * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33 1.4.2.2 skrll * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
34 1.4.2.2 skrll * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 1.4.2.2 skrll */
36 1.4.2.2 skrll
37 1.4.2.2 skrll /*
38 1.4.2.2 skrll * USB Communication Device Class (Ethernet Networking Control Model)
39 1.4.2.2 skrll * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
40 1.4.2.2 skrll *
41 1.4.2.2 skrll */
42 1.4.2.2 skrll
43 1.4.2.2 skrll #include <sys/cdefs.h>
44 1.4.2.2 skrll __KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.4.2.2 2004/11/02 07:53:02 skrll Exp $");
45 1.4.2.2 skrll #include "bpfilter.h"
46 1.4.2.2 skrll
47 1.4.2.2 skrll #include <sys/param.h>
48 1.4.2.2 skrll #include <sys/systm.h>
49 1.4.2.2 skrll #include <sys/sockio.h>
50 1.4.2.2 skrll #include <sys/mbuf.h>
51 1.4.2.2 skrll #include <sys/malloc.h>
52 1.4.2.2 skrll #include <sys/kernel.h>
53 1.4.2.2 skrll #include <sys/socket.h>
54 1.4.2.2 skrll #include <sys/device.h>
55 1.4.2.2 skrll #if defined(__OpenBSD__)
56 1.4.2.2 skrll #include <sys/proc.h>
57 1.4.2.2 skrll #endif
58 1.4.2.2 skrll
59 1.4.2.2 skrll #if NRND > 0
60 1.4.2.2 skrll #include <sys/rnd.h>
61 1.4.2.2 skrll #endif
62 1.4.2.2 skrll
63 1.4.2.2 skrll #include <net/if.h>
64 1.4.2.2 skrll #if defined(__NetBSD__)
65 1.4.2.2 skrll #include <net/if_arp.h>
66 1.4.2.2 skrll #endif
67 1.4.2.2 skrll #include <net/if_dl.h>
68 1.4.2.2 skrll #include <net/if_media.h>
69 1.4.2.2 skrll
70 1.4.2.2 skrll #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
71 1.4.2.2 skrll
72 1.4.2.2 skrll #if NBPFILTER > 0
73 1.4.2.2 skrll #include <net/bpf.h>
74 1.4.2.2 skrll #endif
75 1.4.2.2 skrll
76 1.4.2.2 skrll #if defined(__NetBSD__)
77 1.4.2.2 skrll #include <net/if_ether.h>
78 1.4.2.2 skrll #ifdef INET
79 1.4.2.2 skrll #include <netinet/in.h>
80 1.4.2.2 skrll #include <netinet/if_inarp.h>
81 1.4.2.2 skrll #endif
82 1.4.2.2 skrll #endif /* defined(__NetBSD__) */
83 1.4.2.2 skrll
84 1.4.2.2 skrll #if defined(__OpenBSD__)
85 1.4.2.2 skrll #ifdef INET
86 1.4.2.2 skrll #include <netinet/in.h>
87 1.4.2.2 skrll #include <netinet/in_systm.h>
88 1.4.2.2 skrll #include <netinet/in_var.h>
89 1.4.2.2 skrll #include <netinet/ip.h>
90 1.4.2.2 skrll #include <netinet/if_ether.h>
91 1.4.2.2 skrll #endif
92 1.4.2.2 skrll #endif /* defined(__OpenBSD__) */
93 1.4.2.2 skrll
94 1.4.2.2 skrll #ifdef NS
95 1.4.2.2 skrll #include <netns/ns.h>
96 1.4.2.2 skrll #include <netns/ns_if.h>
97 1.4.2.2 skrll #endif
98 1.4.2.2 skrll
99 1.4.2.2 skrll #include <dev/usb/usb.h>
100 1.4.2.2 skrll #include <dev/usb/usbdi.h>
101 1.4.2.2 skrll #include <dev/usb/usbdi_util.h>
102 1.4.2.2 skrll #include <dev/usb/usbdevs.h>
103 1.4.2.2 skrll #include <dev/usb/usbcdc.h>
104 1.4.2.2 skrll
105 1.4.2.2 skrll #include <dev/usb/if_cdcereg.h>
106 1.4.2.2 skrll
107 1.4.2.2 skrll Static int cdce_tx_list_init(struct cdce_softc *);
108 1.4.2.2 skrll Static int cdce_rx_list_init(struct cdce_softc *);
109 1.4.2.2 skrll Static int cdce_newbuf(struct cdce_softc *, struct cdce_chain *,
110 1.4.2.2 skrll struct mbuf *);
111 1.4.2.2 skrll Static int cdce_encap(struct cdce_softc *, struct mbuf *, int);
112 1.4.2.2 skrll Static void cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
113 1.4.2.2 skrll Static void cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
114 1.4.2.2 skrll Static void cdce_start(struct ifnet *);
115 1.4.2.2 skrll Static int cdce_ioctl(struct ifnet *, u_long, caddr_t);
116 1.4.2.2 skrll Static void cdce_init(void *);
117 1.4.2.2 skrll Static void cdce_watchdog(struct ifnet *);
118 1.4.2.2 skrll Static void cdce_stop(struct cdce_softc *);
119 1.4.2.2 skrll Static uint32_t cdce_crc32(const void *, size_t);
120 1.4.2.2 skrll
121 1.4.2.2 skrll Static const struct cdce_type cdce_devs[] = {
122 1.4.2.2 skrll {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, CDCE_NO_UNION },
123 1.4.2.2 skrll {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_ZAURUS },
124 1.4.2.2 skrll {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_ZAURUS | CDCE_NO_UNION },
125 1.4.2.2 skrll {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS | CDCE_NO_UNION },
126 1.4.2.2 skrll {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_ZAURUS | CDCE_NO_UNION },
127 1.4.2.2 skrll {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_ZAURUS | CDCE_NO_UNION },
128 1.4.2.2 skrll };
129 1.4.2.2 skrll #define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p))
130 1.4.2.2 skrll
131 1.4.2.2 skrll USB_DECLARE_DRIVER(cdce);
132 1.4.2.2 skrll
133 1.4.2.2 skrll USB_MATCH(cdce)
134 1.4.2.2 skrll {
135 1.4.2.2 skrll USB_MATCH_START(cdce, uaa);
136 1.4.2.2 skrll usb_interface_descriptor_t *id;
137 1.4.2.2 skrll
138 1.4.2.2 skrll if (uaa->iface == NULL)
139 1.4.2.2 skrll return (UMATCH_NONE);
140 1.4.2.2 skrll
141 1.4.2.2 skrll id = usbd_get_interface_descriptor(uaa->iface);
142 1.4.2.2 skrll if (id == NULL)
143 1.4.2.2 skrll return (UMATCH_NONE);
144 1.4.2.2 skrll
145 1.4.2.2 skrll if (cdce_lookup(uaa->vendor, uaa->product) != NULL)
146 1.4.2.2 skrll return (UMATCH_VENDOR_PRODUCT);
147 1.4.2.2 skrll
148 1.4.2.2 skrll if (id->bInterfaceClass == UICLASS_CDC && id->bInterfaceSubClass ==
149 1.4.2.2 skrll UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
150 1.4.2.2 skrll return (UMATCH_IFACECLASS_GENERIC);
151 1.4.2.2 skrll
152 1.4.2.2 skrll return (UMATCH_NONE);
153 1.4.2.2 skrll }
154 1.4.2.2 skrll
155 1.4.2.2 skrll USB_ATTACH(cdce)
156 1.4.2.2 skrll {
157 1.4.2.2 skrll USB_ATTACH_START(cdce, sc, uaa);
158 1.4.2.2 skrll char devinfo[1024];
159 1.4.2.2 skrll int s;
160 1.4.2.2 skrll struct ifnet *ifp;
161 1.4.2.2 skrll usbd_device_handle dev = uaa->device;
162 1.4.2.2 skrll const struct cdce_type *t;
163 1.4.2.2 skrll usb_interface_descriptor_t *id;
164 1.4.2.2 skrll usb_endpoint_descriptor_t *ed;
165 1.4.2.2 skrll const usb_cdc_union_descriptor_t *ud;
166 1.4.2.2 skrll int data_ifcno;
167 1.4.2.2 skrll int i;
168 1.4.2.2 skrll u_char eaddr[ETHER_ADDR_LEN];
169 1.4.2.2 skrll const usb_cdc_ethernet_descriptor_t *ue;
170 1.4.2.2 skrll char eaddr_str[USB_MAX_STRING_LEN];
171 1.4.2.2 skrll
172 1.4.2.2 skrll usbd_devinfo(dev, 0, devinfo, sizeof devinfo);
173 1.4.2.2 skrll USB_ATTACH_SETUP;
174 1.4.2.2 skrll printf("%s: %s\n", USBDEVNAME(sc->cdce_dev), devinfo);
175 1.4.2.2 skrll
176 1.4.2.2 skrll sc->cdce_udev = uaa->device;
177 1.4.2.2 skrll sc->cdce_ctl_iface = uaa->iface;
178 1.4.2.2 skrll
179 1.4.2.2 skrll t = cdce_lookup(uaa->vendor, uaa->product);
180 1.4.2.2 skrll if (t)
181 1.4.2.2 skrll sc->cdce_flags = t->cdce_flags;
182 1.4.2.2 skrll
183 1.4.2.2 skrll if (sc->cdce_flags & CDCE_NO_UNION)
184 1.4.2.2 skrll sc->cdce_data_iface = sc->cdce_ctl_iface;
185 1.4.2.2 skrll else {
186 1.4.2.2 skrll ud = (usb_cdc_union_descriptor_t *)usb_find_desc(sc->cdce_udev,
187 1.4.2.2 skrll UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION);
188 1.4.2.2 skrll if (ud == NULL) {
189 1.4.2.2 skrll printf("%s: no union descriptor\n",
190 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev));
191 1.4.2.2 skrll USB_ATTACH_ERROR_RETURN;
192 1.4.2.2 skrll }
193 1.4.2.2 skrll data_ifcno = ud->bSlaveInterface[0];
194 1.4.2.2 skrll
195 1.4.2.2 skrll for (i = 0; i < uaa->nifaces; i++) {
196 1.4.2.2 skrll if (uaa->ifaces[i] != NULL) {
197 1.4.2.2 skrll id = usbd_get_interface_descriptor(
198 1.4.2.2 skrll uaa->ifaces[i]);
199 1.4.2.2 skrll if (id != NULL && id->bInterfaceNumber ==
200 1.4.2.2 skrll data_ifcno) {
201 1.4.2.2 skrll sc->cdce_data_iface = uaa->ifaces[i];
202 1.4.2.2 skrll uaa->ifaces[i] = NULL;
203 1.4.2.2 skrll }
204 1.4.2.2 skrll }
205 1.4.2.2 skrll }
206 1.4.2.2 skrll }
207 1.4.2.2 skrll
208 1.4.2.2 skrll if (sc->cdce_data_iface == NULL) {
209 1.4.2.2 skrll printf("%s: no data interface\n", USBDEVNAME(sc->cdce_dev));
210 1.4.2.2 skrll USB_ATTACH_ERROR_RETURN;
211 1.4.2.2 skrll }
212 1.4.2.2 skrll
213 1.4.2.2 skrll /* Find endpoints. */
214 1.4.2.2 skrll id = usbd_get_interface_descriptor(sc->cdce_data_iface);
215 1.4.2.2 skrll sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1;
216 1.4.2.2 skrll for (i = 0; i < id->bNumEndpoints; i++) {
217 1.4.2.2 skrll ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i);
218 1.4.2.2 skrll if (!ed) {
219 1.4.2.2 skrll printf("%s: could not read endpoint descriptor\n",
220 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev));
221 1.4.2.2 skrll USB_ATTACH_ERROR_RETURN;
222 1.4.2.2 skrll }
223 1.4.2.2 skrll if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
224 1.4.2.2 skrll UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
225 1.4.2.2 skrll sc->cdce_bulkin_no = ed->bEndpointAddress;
226 1.4.2.2 skrll } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
227 1.4.2.2 skrll UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
228 1.4.2.2 skrll sc->cdce_bulkout_no = ed->bEndpointAddress;
229 1.4.2.2 skrll } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
230 1.4.2.2 skrll UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
231 1.4.2.2 skrll /* XXX: CDC spec defines an interrupt pipe, but it is not
232 1.4.2.2 skrll * needed for simple host-to-host applications. */
233 1.4.2.2 skrll } else {
234 1.4.2.2 skrll printf("%s: unexpected endpoint\n",
235 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev));
236 1.4.2.2 skrll }
237 1.4.2.2 skrll }
238 1.4.2.2 skrll
239 1.4.2.2 skrll if (sc->cdce_bulkin_no == -1) {
240 1.4.2.2 skrll printf("%s: could not find data bulk in\n",
241 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev));
242 1.4.2.2 skrll USB_ATTACH_ERROR_RETURN;
243 1.4.2.2 skrll }
244 1.4.2.2 skrll if (sc->cdce_bulkout_no == -1 ) {
245 1.4.2.2 skrll printf("%s: could not find data bulk out\n",
246 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev));
247 1.4.2.2 skrll USB_ATTACH_ERROR_RETURN;
248 1.4.2.2 skrll }
249 1.4.2.2 skrll
250 1.4.2.2 skrll ue = (usb_cdc_ethernet_descriptor_t *)usb_find_desc(dev,
251 1.4.2.2 skrll UDESC_INTERFACE, UDESCSUB_CDC_ENF);
252 1.4.2.2 skrll if (!ue || usbd_get_string(dev, ue->iMacAddress, eaddr_str)) {
253 1.4.2.2 skrll printf("%s: faking address\n", USBDEVNAME(sc->cdce_dev));
254 1.4.2.2 skrll eaddr[0]= 0x2a;
255 1.4.2.2 skrll memcpy(&eaddr[1], &hardclock_ticks, sizeof(u_int32_t));
256 1.4.2.2 skrll eaddr[5] = (u_int8_t)(sc->cdce_dev.dv_unit);
257 1.4.2.2 skrll } else {
258 1.4.2.2 skrll int i;
259 1.4.2.2 skrll
260 1.4.2.2 skrll memset(eaddr, 0, ETHER_ADDR_LEN);
261 1.4.2.2 skrll for (i = 0; i < ETHER_ADDR_LEN * 2; i++) {
262 1.4.2.2 skrll int c = eaddr_str[i];
263 1.4.2.2 skrll
264 1.4.2.2 skrll if ('0' <= c && c <= '9')
265 1.4.2.2 skrll c -= '0';
266 1.4.2.2 skrll else
267 1.4.2.2 skrll c -= 'A' - 10;
268 1.4.2.2 skrll c &= 0xf;
269 1.4.2.2 skrll if (c%2 == 0)
270 1.4.2.2 skrll c <<= 4;
271 1.4.2.2 skrll eaddr[i / 2] |= c;
272 1.4.2.2 skrll }
273 1.4.2.2 skrll }
274 1.4.2.2 skrll
275 1.4.2.2 skrll s = splnet();
276 1.4.2.2 skrll
277 1.4.2.2 skrll printf("%s: address %s\n", USBDEVNAME(sc->cdce_dev),
278 1.4.2.2 skrll ether_sprintf(eaddr));
279 1.4.2.2 skrll
280 1.4.2.2 skrll ifp = GET_IFP(sc);
281 1.4.2.2 skrll ifp->if_softc = sc;
282 1.4.2.2 skrll ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
283 1.4.2.2 skrll ifp->if_ioctl = cdce_ioctl;
284 1.4.2.2 skrll ifp->if_start = cdce_start;
285 1.4.2.2 skrll ifp->if_watchdog = cdce_watchdog;
286 1.4.2.2 skrll strncpy(ifp->if_xname, USBDEVNAME(sc->cdce_dev), IFNAMSIZ);
287 1.4.2.2 skrll
288 1.4.2.2 skrll IFQ_SET_READY(&ifp->if_snd);
289 1.4.2.2 skrll
290 1.4.2.2 skrll if_attach(ifp);
291 1.4.2.2 skrll Ether_ifattach(ifp, eaddr);
292 1.4.2.2 skrll
293 1.4.2.2 skrll sc->cdce_attached = 1;
294 1.4.2.2 skrll splx(s);
295 1.4.2.2 skrll
296 1.4.2.2 skrll usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev,
297 1.4.2.2 skrll USBDEV(sc->cdce_dev));
298 1.4.2.2 skrll
299 1.4.2.2 skrll USB_ATTACH_SUCCESS_RETURN;
300 1.4.2.2 skrll }
301 1.4.2.2 skrll
302 1.4.2.2 skrll USB_DETACH(cdce)
303 1.4.2.2 skrll {
304 1.4.2.2 skrll USB_DETACH_START(cdce, sc);
305 1.4.2.2 skrll struct ifnet *ifp = GET_IFP(sc);
306 1.4.2.2 skrll int s;
307 1.4.2.2 skrll
308 1.4.2.2 skrll s = splusb();
309 1.4.2.2 skrll
310 1.4.2.2 skrll if (!sc->cdce_attached) {
311 1.4.2.2 skrll splx(s);
312 1.4.2.2 skrll return (0);
313 1.4.2.2 skrll }
314 1.4.2.2 skrll
315 1.4.2.2 skrll if (ifp->if_flags & IFF_RUNNING)
316 1.4.2.2 skrll cdce_stop(sc);
317 1.4.2.2 skrll
318 1.4.2.2 skrll ether_ifdetach(ifp);
319 1.4.2.2 skrll
320 1.4.2.2 skrll if_detach(ifp);
321 1.4.2.2 skrll
322 1.4.2.2 skrll sc->cdce_attached = 0;
323 1.4.2.2 skrll splx(s);
324 1.4.2.2 skrll
325 1.4.2.2 skrll return (0);
326 1.4.2.2 skrll }
327 1.4.2.2 skrll
328 1.4.2.2 skrll Static void
329 1.4.2.2 skrll cdce_start(struct ifnet *ifp)
330 1.4.2.2 skrll {
331 1.4.2.2 skrll struct cdce_softc *sc = ifp->if_softc;
332 1.4.2.2 skrll struct mbuf *m_head = NULL;
333 1.4.2.2 skrll
334 1.4.2.2 skrll if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE))
335 1.4.2.2 skrll return;
336 1.4.2.2 skrll
337 1.4.2.2 skrll IFQ_POLL(&ifp->if_snd, m_head);
338 1.4.2.2 skrll if (m_head == NULL)
339 1.4.2.2 skrll return;
340 1.4.2.2 skrll
341 1.4.2.2 skrll if (cdce_encap(sc, m_head, 0)) {
342 1.4.2.2 skrll ifp->if_flags |= IFF_OACTIVE;
343 1.4.2.2 skrll return;
344 1.4.2.2 skrll }
345 1.4.2.2 skrll
346 1.4.2.2 skrll IFQ_DEQUEUE(&ifp->if_snd, m_head);
347 1.4.2.2 skrll
348 1.4.2.2 skrll #if NBPFILTER > 0
349 1.4.2.2 skrll if (ifp->if_bpf)
350 1.4.2.2 skrll BPF_MTAP(ifp, m_head);
351 1.4.2.2 skrll #endif
352 1.4.2.2 skrll
353 1.4.2.2 skrll ifp->if_flags |= IFF_OACTIVE;
354 1.4.2.2 skrll
355 1.4.2.2 skrll ifp->if_timer = 6;
356 1.4.2.2 skrll }
357 1.4.2.2 skrll
358 1.4.2.2 skrll Static int
359 1.4.2.2 skrll cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx)
360 1.4.2.2 skrll {
361 1.4.2.2 skrll struct cdce_chain *c;
362 1.4.2.2 skrll usbd_status err;
363 1.4.2.2 skrll int extra = 0;
364 1.4.2.2 skrll
365 1.4.2.2 skrll c = &sc->cdce_cdata.cdce_tx_chain[idx];
366 1.4.2.2 skrll
367 1.4.2.2 skrll m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf);
368 1.4.2.2 skrll if (sc->cdce_flags & CDCE_ZAURUS) {
369 1.4.2.2 skrll /* Zaurus wants a 32-bit CRC appended to every frame */
370 1.4.2.2 skrll u_int32_t crc;
371 1.4.2.2 skrll
372 1.4.2.2 skrll crc = cdce_crc32(c->cdce_buf, m->m_pkthdr.len);
373 1.4.2.2 skrll bcopy(&crc, c->cdce_buf + m->m_pkthdr.len, 4);
374 1.4.2.2 skrll extra = 4;
375 1.4.2.2 skrll }
376 1.4.2.2 skrll c->cdce_mbuf = m;
377 1.4.2.2 skrll
378 1.4.2.2 skrll usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf,
379 1.4.2.2 skrll m->m_pkthdr.len + extra, USBD_NO_COPY, 10000, cdce_txeof);
380 1.4.2.2 skrll err = usbd_transfer(c->cdce_xfer);
381 1.4.2.2 skrll if (err != USBD_IN_PROGRESS) {
382 1.4.2.2 skrll cdce_stop(sc);
383 1.4.2.2 skrll return (EIO);
384 1.4.2.2 skrll }
385 1.4.2.2 skrll
386 1.4.2.2 skrll sc->cdce_cdata.cdce_tx_cnt++;
387 1.4.2.2 skrll
388 1.4.2.2 skrll return (0);
389 1.4.2.2 skrll }
390 1.4.2.2 skrll
391 1.4.2.2 skrll Static void
392 1.4.2.2 skrll cdce_stop(struct cdce_softc *sc)
393 1.4.2.2 skrll {
394 1.4.2.2 skrll usbd_status err;
395 1.4.2.2 skrll struct ifnet *ifp = GET_IFP(sc);
396 1.4.2.2 skrll int i;
397 1.4.2.2 skrll
398 1.4.2.2 skrll ifp->if_timer = 0;
399 1.4.2.2 skrll
400 1.4.2.2 skrll if (sc->cdce_bulkin_pipe != NULL) {
401 1.4.2.2 skrll err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
402 1.4.2.2 skrll if (err)
403 1.4.2.2 skrll printf("%s: abort rx pipe failed: %s\n",
404 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
405 1.4.2.2 skrll err = usbd_close_pipe(sc->cdce_bulkin_pipe);
406 1.4.2.2 skrll if (err)
407 1.4.2.2 skrll printf("%s: close rx pipe failed: %s\n",
408 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
409 1.4.2.2 skrll sc->cdce_bulkin_pipe = NULL;
410 1.4.2.2 skrll }
411 1.4.2.2 skrll
412 1.4.2.2 skrll if (sc->cdce_bulkout_pipe != NULL) {
413 1.4.2.2 skrll err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
414 1.4.2.2 skrll if (err)
415 1.4.2.2 skrll printf("%s: abort tx pipe failed: %s\n",
416 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
417 1.4.2.2 skrll err = usbd_close_pipe(sc->cdce_bulkout_pipe);
418 1.4.2.2 skrll if (err)
419 1.4.2.2 skrll printf("%s: close tx pipe failed: %s\n",
420 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
421 1.4.2.2 skrll sc->cdce_bulkout_pipe = NULL;
422 1.4.2.2 skrll }
423 1.4.2.2 skrll
424 1.4.2.2 skrll for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
425 1.4.2.2 skrll if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) {
426 1.4.2.2 skrll m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf);
427 1.4.2.2 skrll sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL;
428 1.4.2.2 skrll }
429 1.4.2.2 skrll if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) {
430 1.4.2.2 skrll usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer);
431 1.4.2.2 skrll sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL;
432 1.4.2.2 skrll }
433 1.4.2.2 skrll }
434 1.4.2.2 skrll
435 1.4.2.2 skrll for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
436 1.4.2.2 skrll if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) {
437 1.4.2.2 skrll m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf);
438 1.4.2.2 skrll sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL;
439 1.4.2.2 skrll }
440 1.4.2.2 skrll if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) {
441 1.4.2.2 skrll usbd_free_xfer(sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer);
442 1.4.2.2 skrll sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL;
443 1.4.2.2 skrll }
444 1.4.2.2 skrll }
445 1.4.2.2 skrll
446 1.4.2.2 skrll ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
447 1.4.2.2 skrll }
448 1.4.2.2 skrll
449 1.4.2.2 skrll Static int
450 1.4.2.2 skrll cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
451 1.4.2.2 skrll {
452 1.4.2.2 skrll struct cdce_softc *sc = ifp->if_softc;
453 1.4.2.2 skrll struct ifaddr *ifa = (struct ifaddr *)data;
454 1.4.2.2 skrll struct ifreq *ifr = (struct ifreq *)data;
455 1.4.2.2 skrll int s, error = 0;
456 1.4.2.2 skrll
457 1.4.2.2 skrll if (sc->cdce_dying)
458 1.4.2.2 skrll return (EIO);
459 1.4.2.2 skrll
460 1.4.2.2 skrll s = splnet();
461 1.4.2.2 skrll
462 1.4.2.2 skrll switch(command) {
463 1.4.2.2 skrll case SIOCSIFADDR:
464 1.4.2.2 skrll ifp->if_flags |= IFF_UP;
465 1.4.2.2 skrll cdce_init(sc);
466 1.4.2.2 skrll switch (ifa->ifa_addr->sa_family) {
467 1.4.2.2 skrll #ifdef INET
468 1.4.2.2 skrll case AF_INET:
469 1.4.2.2 skrll #if defined(__NetBSD__)
470 1.4.2.2 skrll arp_ifinit(ifp, ifa);
471 1.4.2.2 skrll #else
472 1.4.2.2 skrll arp_ifinit(&sc->arpcom, ifa);
473 1.4.2.2 skrll #endif
474 1.4.2.2 skrll break;
475 1.4.2.2 skrll #endif /* INET */
476 1.4.2.2 skrll #ifdef NS
477 1.4.2.2 skrll case AF_NS:
478 1.4.2.2 skrll {
479 1.4.2.2 skrll struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
480 1.4.2.2 skrll
481 1.4.2.2 skrll if (ns_nullhost(*ina))
482 1.4.2.2 skrll ina->x_host = *(union ns_host *)
483 1.4.2.2 skrll LLADDR(ifp->if_sadl);
484 1.4.2.2 skrll else
485 1.4.2.2 skrll memcpy(LLADDR(ifp->if_sadl),
486 1.4.2.2 skrll ina->x_host.c_host,
487 1.4.2.2 skrll ifp->if_addrlen);
488 1.4.2.2 skrll break;
489 1.4.2.2 skrll }
490 1.4.2.2 skrll #endif /* NS */
491 1.4.2.2 skrll }
492 1.4.2.2 skrll break;
493 1.4.2.2 skrll
494 1.4.2.2 skrll case SIOCSIFMTU:
495 1.4.2.2 skrll if (ifr->ifr_mtu > ETHERMTU)
496 1.4.2.2 skrll error = EINVAL;
497 1.4.2.2 skrll else
498 1.4.2.2 skrll ifp->if_mtu = ifr->ifr_mtu;
499 1.4.2.2 skrll break;
500 1.4.2.2 skrll
501 1.4.2.2 skrll case SIOCSIFFLAGS:
502 1.4.2.2 skrll if (ifp->if_flags & IFF_UP) {
503 1.4.2.2 skrll if (!(ifp->if_flags & IFF_RUNNING))
504 1.4.2.2 skrll cdce_init(sc);
505 1.4.2.2 skrll } else {
506 1.4.2.2 skrll if (ifp->if_flags & IFF_RUNNING)
507 1.4.2.2 skrll cdce_stop(sc);
508 1.4.2.2 skrll }
509 1.4.2.2 skrll error = 0;
510 1.4.2.2 skrll break;
511 1.4.2.2 skrll
512 1.4.2.2 skrll default:
513 1.4.2.2 skrll error = EINVAL;
514 1.4.2.2 skrll break;
515 1.4.2.2 skrll }
516 1.4.2.2 skrll
517 1.4.2.2 skrll splx(s);
518 1.4.2.2 skrll
519 1.4.2.2 skrll return (error);
520 1.4.2.2 skrll }
521 1.4.2.2 skrll
522 1.4.2.2 skrll Static void
523 1.4.2.2 skrll cdce_watchdog(struct ifnet *ifp)
524 1.4.2.2 skrll {
525 1.4.2.2 skrll struct cdce_softc *sc = ifp->if_softc;
526 1.4.2.2 skrll
527 1.4.2.2 skrll if (sc->cdce_dying)
528 1.4.2.2 skrll return;
529 1.4.2.2 skrll
530 1.4.2.2 skrll ifp->if_oerrors++;
531 1.4.2.2 skrll printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev));
532 1.4.2.2 skrll }
533 1.4.2.2 skrll
534 1.4.2.2 skrll Static void
535 1.4.2.2 skrll cdce_init(void *xsc)
536 1.4.2.2 skrll {
537 1.4.2.2 skrll struct cdce_softc *sc = xsc;
538 1.4.2.2 skrll struct ifnet *ifp = GET_IFP(sc);
539 1.4.2.2 skrll struct cdce_chain *c;
540 1.4.2.2 skrll usbd_status err;
541 1.4.2.2 skrll int s, i;
542 1.4.2.2 skrll
543 1.4.2.2 skrll if (ifp->if_flags & IFF_RUNNING)
544 1.4.2.2 skrll return;
545 1.4.2.2 skrll
546 1.4.2.2 skrll s = splnet();
547 1.4.2.2 skrll
548 1.4.2.2 skrll if (cdce_tx_list_init(sc) == ENOBUFS) {
549 1.4.2.2 skrll printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
550 1.4.2.2 skrll splx(s);
551 1.4.2.2 skrll return;
552 1.4.2.2 skrll }
553 1.4.2.2 skrll
554 1.4.2.2 skrll if (cdce_rx_list_init(sc) == ENOBUFS) {
555 1.4.2.2 skrll printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
556 1.4.2.2 skrll splx(s);
557 1.4.2.2 skrll return;
558 1.4.2.2 skrll }
559 1.4.2.2 skrll
560 1.4.2.2 skrll /* Maybe set multicast / broadcast here??? */
561 1.4.2.2 skrll
562 1.4.2.2 skrll err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
563 1.4.2.2 skrll USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
564 1.4.2.2 skrll if (err) {
565 1.4.2.2 skrll printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
566 1.4.2.2 skrll usbd_errstr(err));
567 1.4.2.2 skrll splx(s);
568 1.4.2.2 skrll return;
569 1.4.2.2 skrll }
570 1.4.2.2 skrll
571 1.4.2.2 skrll err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
572 1.4.2.2 skrll USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
573 1.4.2.2 skrll if (err) {
574 1.4.2.2 skrll printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
575 1.4.2.2 skrll usbd_errstr(err));
576 1.4.2.2 skrll splx(s);
577 1.4.2.2 skrll return;
578 1.4.2.2 skrll }
579 1.4.2.2 skrll
580 1.4.2.2 skrll for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
581 1.4.2.2 skrll c = &sc->cdce_cdata.cdce_rx_chain[i];
582 1.4.2.2 skrll usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c,
583 1.4.2.2 skrll c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
584 1.4.2.2 skrll USBD_NO_TIMEOUT, cdce_rxeof);
585 1.4.2.2 skrll usbd_transfer(c->cdce_xfer);
586 1.4.2.2 skrll }
587 1.4.2.2 skrll
588 1.4.2.2 skrll ifp->if_flags |= IFF_RUNNING;
589 1.4.2.2 skrll ifp->if_flags &= ~IFF_OACTIVE;
590 1.4.2.2 skrll
591 1.4.2.2 skrll splx(s);
592 1.4.2.2 skrll }
593 1.4.2.2 skrll
594 1.4.2.2 skrll Static int
595 1.4.2.2 skrll cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m)
596 1.4.2.2 skrll {
597 1.4.2.2 skrll struct mbuf *m_new = NULL;
598 1.4.2.2 skrll
599 1.4.2.2 skrll if (m == NULL) {
600 1.4.2.2 skrll MGETHDR(m_new, M_DONTWAIT, MT_DATA);
601 1.4.2.2 skrll if (m_new == NULL) {
602 1.4.2.2 skrll printf("%s: no memory for rx list "
603 1.4.2.2 skrll "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
604 1.4.2.2 skrll return (ENOBUFS);
605 1.4.2.2 skrll }
606 1.4.2.2 skrll MCLGET(m_new, M_DONTWAIT);
607 1.4.2.2 skrll if (!(m_new->m_flags & M_EXT)) {
608 1.4.2.2 skrll printf("%s: no memory for rx list "
609 1.4.2.2 skrll "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
610 1.4.2.2 skrll m_freem(m_new);
611 1.4.2.2 skrll return (ENOBUFS);
612 1.4.2.2 skrll }
613 1.4.2.2 skrll m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
614 1.4.2.2 skrll } else {
615 1.4.2.2 skrll m_new = m;
616 1.4.2.2 skrll m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
617 1.4.2.2 skrll m_new->m_data = m_new->m_ext.ext_buf;
618 1.4.2.2 skrll }
619 1.4.2.2 skrll c->cdce_mbuf = m_new;
620 1.4.2.2 skrll return (0);
621 1.4.2.2 skrll }
622 1.4.2.2 skrll
623 1.4.2.2 skrll Static int
624 1.4.2.2 skrll cdce_rx_list_init(struct cdce_softc *sc)
625 1.4.2.2 skrll {
626 1.4.2.2 skrll struct cdce_cdata *cd;
627 1.4.2.2 skrll struct cdce_chain *c;
628 1.4.2.2 skrll int i;
629 1.4.2.2 skrll
630 1.4.2.2 skrll cd = &sc->cdce_cdata;
631 1.4.2.2 skrll for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
632 1.4.2.2 skrll c = &cd->cdce_rx_chain[i];
633 1.4.2.2 skrll c->cdce_sc = sc;
634 1.4.2.2 skrll c->cdce_idx = i;
635 1.4.2.2 skrll if (cdce_newbuf(sc, c, NULL) == ENOBUFS)
636 1.4.2.2 skrll return (ENOBUFS);
637 1.4.2.2 skrll if (c->cdce_xfer == NULL) {
638 1.4.2.2 skrll c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev);
639 1.4.2.2 skrll if (c->cdce_xfer == NULL)
640 1.4.2.2 skrll return (ENOBUFS);
641 1.4.2.2 skrll c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ);
642 1.4.2.2 skrll if (c->cdce_buf == NULL)
643 1.4.2.2 skrll return (ENOBUFS);
644 1.4.2.2 skrll }
645 1.4.2.2 skrll }
646 1.4.2.2 skrll
647 1.4.2.2 skrll return (0);
648 1.4.2.2 skrll }
649 1.4.2.2 skrll
650 1.4.2.2 skrll Static int
651 1.4.2.2 skrll cdce_tx_list_init(struct cdce_softc *sc)
652 1.4.2.2 skrll {
653 1.4.2.2 skrll struct cdce_cdata *cd;
654 1.4.2.2 skrll struct cdce_chain *c;
655 1.4.2.2 skrll int i;
656 1.4.2.2 skrll
657 1.4.2.2 skrll cd = &sc->cdce_cdata;
658 1.4.2.2 skrll for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
659 1.4.2.2 skrll c = &cd->cdce_tx_chain[i];
660 1.4.2.2 skrll c->cdce_sc = sc;
661 1.4.2.2 skrll c->cdce_idx = i;
662 1.4.2.2 skrll c->cdce_mbuf = NULL;
663 1.4.2.2 skrll if (c->cdce_xfer == NULL) {
664 1.4.2.2 skrll c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev);
665 1.4.2.2 skrll if (c->cdce_xfer == NULL)
666 1.4.2.2 skrll return (ENOBUFS);
667 1.4.2.2 skrll c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ);
668 1.4.2.2 skrll if (c->cdce_buf == NULL)
669 1.4.2.2 skrll return (ENOBUFS);
670 1.4.2.2 skrll }
671 1.4.2.2 skrll }
672 1.4.2.2 skrll
673 1.4.2.2 skrll return (0);
674 1.4.2.2 skrll }
675 1.4.2.2 skrll
676 1.4.2.2 skrll Static void
677 1.4.2.2 skrll cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
678 1.4.2.2 skrll {
679 1.4.2.2 skrll struct cdce_chain *c = priv;
680 1.4.2.2 skrll struct cdce_softc *sc = c->cdce_sc;
681 1.4.2.2 skrll struct ifnet *ifp = GET_IFP(sc);
682 1.4.2.2 skrll struct mbuf *m;
683 1.4.2.2 skrll int total_len = 0;
684 1.4.2.2 skrll int s;
685 1.4.2.2 skrll
686 1.4.2.2 skrll if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
687 1.4.2.2 skrll return;
688 1.4.2.2 skrll
689 1.4.2.2 skrll if (status != USBD_NORMAL_COMPLETION) {
690 1.4.2.2 skrll if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
691 1.4.2.2 skrll return;
692 1.4.2.2 skrll if (sc->cdce_rxeof_errors == 0)
693 1.4.2.2 skrll printf("%s: usb error on rx: %s\n",
694 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev), usbd_errstr(status));
695 1.4.2.2 skrll if (status == USBD_STALLED)
696 1.4.2.2 skrll usbd_clear_endpoint_stall(sc->cdce_bulkin_pipe);
697 1.4.2.2 skrll DELAY(sc->cdce_rxeof_errors * 10000);
698 1.4.2.2 skrll sc->cdce_rxeof_errors++;
699 1.4.2.2 skrll goto done;
700 1.4.2.2 skrll }
701 1.4.2.2 skrll
702 1.4.2.2 skrll sc->cdce_rxeof_errors = 0;
703 1.4.2.2 skrll
704 1.4.2.2 skrll usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
705 1.4.2.2 skrll if (sc->cdce_flags & CDCE_ZAURUS)
706 1.4.2.2 skrll total_len -= 4; /* Strip off CRC added by Zaurus */
707 1.4.2.2 skrll if (total_len <= 1)
708 1.4.2.2 skrll goto done;
709 1.4.2.2 skrll
710 1.4.2.2 skrll m = c->cdce_mbuf;
711 1.4.2.2 skrll memcpy(mtod(m, char *), c->cdce_buf, total_len);
712 1.4.2.2 skrll
713 1.4.2.2 skrll if (total_len < sizeof(struct ether_header)) {
714 1.4.2.2 skrll ifp->if_ierrors++;
715 1.4.2.2 skrll goto done;
716 1.4.2.2 skrll }
717 1.4.2.2 skrll
718 1.4.2.2 skrll ifp->if_ipackets++;
719 1.4.2.2 skrll m->m_pkthdr.len = m->m_len = total_len;
720 1.4.2.2 skrll m->m_pkthdr.rcvif = ifp;
721 1.4.2.2 skrll
722 1.4.2.2 skrll s = splnet();
723 1.4.2.2 skrll
724 1.4.2.2 skrll if (cdce_newbuf(sc, c, NULL) == ENOBUFS) {
725 1.4.2.2 skrll ifp->if_ierrors++;
726 1.4.2.2 skrll goto done1;
727 1.4.2.2 skrll }
728 1.4.2.2 skrll
729 1.4.2.2 skrll #if NBPFILTER > 0
730 1.4.2.2 skrll if (ifp->if_bpf)
731 1.4.2.2 skrll BPF_MTAP(ifp, m);
732 1.4.2.2 skrll #endif
733 1.4.2.2 skrll
734 1.4.2.2 skrll IF_INPUT(ifp, m);
735 1.4.2.2 skrll
736 1.4.2.2 skrll done1:
737 1.4.2.2 skrll splx(s);
738 1.4.2.2 skrll
739 1.4.2.2 skrll done:
740 1.4.2.2 skrll /* Setup new transfer. */
741 1.4.2.2 skrll usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf,
742 1.4.2.2 skrll CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
743 1.4.2.2 skrll cdce_rxeof);
744 1.4.2.2 skrll usbd_transfer(c->cdce_xfer);
745 1.4.2.2 skrll }
746 1.4.2.2 skrll
747 1.4.2.2 skrll Static void
748 1.4.2.2 skrll cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
749 1.4.2.2 skrll {
750 1.4.2.2 skrll struct cdce_chain *c = priv;
751 1.4.2.2 skrll struct cdce_softc *sc = c->cdce_sc;
752 1.4.2.2 skrll struct ifnet *ifp = GET_IFP(sc);
753 1.4.2.2 skrll usbd_status err;
754 1.4.2.2 skrll int s;
755 1.4.2.2 skrll
756 1.4.2.2 skrll if (sc->cdce_dying)
757 1.4.2.2 skrll return;
758 1.4.2.2 skrll
759 1.4.2.2 skrll s = splnet();
760 1.4.2.2 skrll
761 1.4.2.2 skrll ifp->if_timer = 0;
762 1.4.2.2 skrll ifp->if_flags &= ~IFF_OACTIVE;
763 1.4.2.2 skrll
764 1.4.2.2 skrll if (status != USBD_NORMAL_COMPLETION) {
765 1.4.2.2 skrll if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
766 1.4.2.2 skrll splx(s);
767 1.4.2.2 skrll return;
768 1.4.2.2 skrll }
769 1.4.2.2 skrll ifp->if_oerrors++;
770 1.4.2.2 skrll printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cdce_dev),
771 1.4.2.2 skrll usbd_errstr(status));
772 1.4.2.2 skrll if (status == USBD_STALLED)
773 1.4.2.2 skrll usbd_clear_endpoint_stall(sc->cdce_bulkout_pipe);
774 1.4.2.2 skrll splx(s);
775 1.4.2.2 skrll return;
776 1.4.2.2 skrll }
777 1.4.2.2 skrll
778 1.4.2.2 skrll usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err);
779 1.4.2.2 skrll
780 1.4.2.2 skrll if (c->cdce_mbuf != NULL) {
781 1.4.2.2 skrll m_freem(c->cdce_mbuf);
782 1.4.2.2 skrll c->cdce_mbuf = NULL;
783 1.4.2.2 skrll }
784 1.4.2.2 skrll
785 1.4.2.2 skrll if (err)
786 1.4.2.2 skrll ifp->if_oerrors++;
787 1.4.2.2 skrll else
788 1.4.2.2 skrll ifp->if_opackets++;
789 1.4.2.2 skrll
790 1.4.2.2 skrll if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
791 1.4.2.2 skrll cdce_start(ifp);
792 1.4.2.2 skrll
793 1.4.2.2 skrll splx(s);
794 1.4.2.2 skrll }
795 1.4.2.2 skrll
796 1.4.2.2 skrll int
797 1.4.2.2 skrll cdce_activate(device_ptr_t self, enum devact act)
798 1.4.2.2 skrll {
799 1.4.2.2 skrll struct cdce_softc *sc = (struct cdce_softc *)self;
800 1.4.2.2 skrll
801 1.4.2.2 skrll switch (act) {
802 1.4.2.2 skrll case DVACT_ACTIVATE:
803 1.4.2.2 skrll return (EOPNOTSUPP);
804 1.4.2.2 skrll break;
805 1.4.2.2 skrll
806 1.4.2.2 skrll case DVACT_DEACTIVATE:
807 1.4.2.2 skrll if_deactivate(GET_IFP(sc));
808 1.4.2.2 skrll sc->cdce_dying = 1;
809 1.4.2.2 skrll break;
810 1.4.2.2 skrll }
811 1.4.2.2 skrll return (0);
812 1.4.2.2 skrll }
813 1.4.2.2 skrll
814 1.4.2.2 skrll
815 1.4.2.2 skrll /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
816 1.4.2.2 skrll * code or tables extracted from it, as desired without restriction.
817 1.4.2.2 skrll */
818 1.4.2.2 skrll
819 1.4.2.2 skrll static uint32_t cdce_crc32_tab[] = {
820 1.4.2.2 skrll 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
821 1.4.2.2 skrll 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
822 1.4.2.2 skrll 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
823 1.4.2.2 skrll 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
824 1.4.2.2 skrll 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
825 1.4.2.2 skrll 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
826 1.4.2.2 skrll 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
827 1.4.2.2 skrll 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
828 1.4.2.2 skrll 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
829 1.4.2.2 skrll 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
830 1.4.2.2 skrll 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
831 1.4.2.2 skrll 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
832 1.4.2.2 skrll 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
833 1.4.2.2 skrll 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
834 1.4.2.2 skrll 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
835 1.4.2.2 skrll 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
836 1.4.2.2 skrll 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
837 1.4.2.2 skrll 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
838 1.4.2.2 skrll 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
839 1.4.2.2 skrll 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
840 1.4.2.2 skrll 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
841 1.4.2.2 skrll 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
842 1.4.2.2 skrll 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
843 1.4.2.2 skrll 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
844 1.4.2.2 skrll 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
845 1.4.2.2 skrll 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
846 1.4.2.2 skrll 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
847 1.4.2.2 skrll 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
848 1.4.2.2 skrll 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
849 1.4.2.2 skrll 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
850 1.4.2.2 skrll 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
851 1.4.2.2 skrll 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
852 1.4.2.2 skrll 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
853 1.4.2.2 skrll 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
854 1.4.2.2 skrll 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
855 1.4.2.2 skrll 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
856 1.4.2.2 skrll 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
857 1.4.2.2 skrll 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
858 1.4.2.2 skrll 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
859 1.4.2.2 skrll 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
860 1.4.2.2 skrll 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
861 1.4.2.2 skrll 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
862 1.4.2.2 skrll 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
863 1.4.2.2 skrll };
864 1.4.2.2 skrll
865 1.4.2.2 skrll Static uint32_t
866 1.4.2.2 skrll cdce_crc32(const void *buf, size_t size)
867 1.4.2.2 skrll {
868 1.4.2.2 skrll const uint8_t *p;
869 1.4.2.2 skrll uint32_t crc;
870 1.4.2.2 skrll
871 1.4.2.2 skrll p = buf;
872 1.4.2.2 skrll crc = ~0U;
873 1.4.2.2 skrll
874 1.4.2.2 skrll while (size--)
875 1.4.2.2 skrll crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
876 1.4.2.2 skrll
877 1.4.2.2 skrll return (crc ^ ~0U);
878 1.4.2.2 skrll }
879