if_cdce.c revision 1.4.2.4 1 1.4.2.4 christos /* $NetBSD: if_cdce.c,v 1.4.2.4 2005/12/11 10:29:05 christos 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.4 christos __KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.4.2.4 2005/12/11 10:29:05 christos 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.3 skrll char *devinfop;
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.3 skrll char eaddr_str[USB_MAX_ENCODED_STRING_LEN];
171 1.4.2.2 skrll
172 1.4.2.3 skrll devinfop = usbd_devinfo_alloc(dev, 0);
173 1.4.2.2 skrll USB_ATTACH_SETUP;
174 1.4.2.3 skrll printf("%s: %s\n", USBDEVNAME(sc->cdce_dev), devinfop);
175 1.4.2.3 skrll usbd_devinfo_free(devinfop);
176 1.4.2.2 skrll
177 1.4.2.2 skrll sc->cdce_udev = uaa->device;
178 1.4.2.2 skrll sc->cdce_ctl_iface = uaa->iface;
179 1.4.2.2 skrll
180 1.4.2.2 skrll t = cdce_lookup(uaa->vendor, uaa->product);
181 1.4.2.2 skrll if (t)
182 1.4.2.2 skrll sc->cdce_flags = t->cdce_flags;
183 1.4.2.2 skrll
184 1.4.2.2 skrll if (sc->cdce_flags & CDCE_NO_UNION)
185 1.4.2.2 skrll sc->cdce_data_iface = sc->cdce_ctl_iface;
186 1.4.2.2 skrll else {
187 1.4.2.3 skrll ud = (const usb_cdc_union_descriptor_t *)usb_find_desc(sc->cdce_udev,
188 1.4.2.2 skrll UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION);
189 1.4.2.2 skrll if (ud == NULL) {
190 1.4.2.2 skrll printf("%s: no union descriptor\n",
191 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev));
192 1.4.2.2 skrll USB_ATTACH_ERROR_RETURN;
193 1.4.2.2 skrll }
194 1.4.2.2 skrll data_ifcno = ud->bSlaveInterface[0];
195 1.4.2.2 skrll
196 1.4.2.2 skrll for (i = 0; i < uaa->nifaces; i++) {
197 1.4.2.2 skrll if (uaa->ifaces[i] != NULL) {
198 1.4.2.2 skrll id = usbd_get_interface_descriptor(
199 1.4.2.2 skrll uaa->ifaces[i]);
200 1.4.2.2 skrll if (id != NULL && id->bInterfaceNumber ==
201 1.4.2.2 skrll data_ifcno) {
202 1.4.2.2 skrll sc->cdce_data_iface = uaa->ifaces[i];
203 1.4.2.2 skrll uaa->ifaces[i] = NULL;
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
209 1.4.2.2 skrll if (sc->cdce_data_iface == NULL) {
210 1.4.2.2 skrll printf("%s: no data interface\n", USBDEVNAME(sc->cdce_dev));
211 1.4.2.2 skrll USB_ATTACH_ERROR_RETURN;
212 1.4.2.2 skrll }
213 1.4.2.2 skrll
214 1.4.2.2 skrll /* Find endpoints. */
215 1.4.2.2 skrll id = usbd_get_interface_descriptor(sc->cdce_data_iface);
216 1.4.2.2 skrll sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1;
217 1.4.2.2 skrll for (i = 0; i < id->bNumEndpoints; i++) {
218 1.4.2.2 skrll ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i);
219 1.4.2.2 skrll if (!ed) {
220 1.4.2.2 skrll printf("%s: could not read endpoint descriptor\n",
221 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev));
222 1.4.2.2 skrll USB_ATTACH_ERROR_RETURN;
223 1.4.2.2 skrll }
224 1.4.2.2 skrll if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
225 1.4.2.2 skrll UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
226 1.4.2.2 skrll sc->cdce_bulkin_no = ed->bEndpointAddress;
227 1.4.2.2 skrll } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
228 1.4.2.2 skrll UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
229 1.4.2.2 skrll sc->cdce_bulkout_no = ed->bEndpointAddress;
230 1.4.2.2 skrll } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
231 1.4.2.2 skrll UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
232 1.4.2.2 skrll /* XXX: CDC spec defines an interrupt pipe, but it is not
233 1.4.2.2 skrll * needed for simple host-to-host applications. */
234 1.4.2.2 skrll } else {
235 1.4.2.2 skrll printf("%s: unexpected endpoint\n",
236 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev));
237 1.4.2.2 skrll }
238 1.4.2.2 skrll }
239 1.4.2.2 skrll
240 1.4.2.2 skrll if (sc->cdce_bulkin_no == -1) {
241 1.4.2.2 skrll printf("%s: could not find data bulk in\n",
242 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev));
243 1.4.2.2 skrll USB_ATTACH_ERROR_RETURN;
244 1.4.2.2 skrll }
245 1.4.2.2 skrll if (sc->cdce_bulkout_no == -1 ) {
246 1.4.2.2 skrll printf("%s: could not find data bulk out\n",
247 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev));
248 1.4.2.2 skrll USB_ATTACH_ERROR_RETURN;
249 1.4.2.2 skrll }
250 1.4.2.2 skrll
251 1.4.2.3 skrll ue = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc(dev,
252 1.4.2.2 skrll UDESC_INTERFACE, UDESCSUB_CDC_ENF);
253 1.4.2.2 skrll if (!ue || usbd_get_string(dev, ue->iMacAddress, eaddr_str)) {
254 1.4.2.2 skrll printf("%s: faking address\n", USBDEVNAME(sc->cdce_dev));
255 1.4.2.2 skrll eaddr[0]= 0x2a;
256 1.4.2.2 skrll memcpy(&eaddr[1], &hardclock_ticks, sizeof(u_int32_t));
257 1.4.2.2 skrll eaddr[5] = (u_int8_t)(sc->cdce_dev.dv_unit);
258 1.4.2.2 skrll } else {
259 1.4.2.3 skrll int j;
260 1.4.2.2 skrll
261 1.4.2.2 skrll memset(eaddr, 0, ETHER_ADDR_LEN);
262 1.4.2.3 skrll for (j = 0; j < ETHER_ADDR_LEN * 2; j++) {
263 1.4.2.3 skrll int c = eaddr_str[j];
264 1.4.2.2 skrll
265 1.4.2.2 skrll if ('0' <= c && c <= '9')
266 1.4.2.2 skrll c -= '0';
267 1.4.2.2 skrll else
268 1.4.2.2 skrll c -= 'A' - 10;
269 1.4.2.2 skrll c &= 0xf;
270 1.4.2.2 skrll if (c%2 == 0)
271 1.4.2.2 skrll c <<= 4;
272 1.4.2.3 skrll eaddr[j / 2] |= c;
273 1.4.2.2 skrll }
274 1.4.2.2 skrll }
275 1.4.2.2 skrll
276 1.4.2.2 skrll s = splnet();
277 1.4.2.2 skrll
278 1.4.2.2 skrll printf("%s: address %s\n", USBDEVNAME(sc->cdce_dev),
279 1.4.2.2 skrll ether_sprintf(eaddr));
280 1.4.2.2 skrll
281 1.4.2.2 skrll ifp = GET_IFP(sc);
282 1.4.2.2 skrll ifp->if_softc = sc;
283 1.4.2.2 skrll ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
284 1.4.2.2 skrll ifp->if_ioctl = cdce_ioctl;
285 1.4.2.2 skrll ifp->if_start = cdce_start;
286 1.4.2.2 skrll ifp->if_watchdog = cdce_watchdog;
287 1.4.2.2 skrll strncpy(ifp->if_xname, USBDEVNAME(sc->cdce_dev), IFNAMSIZ);
288 1.4.2.2 skrll
289 1.4.2.2 skrll IFQ_SET_READY(&ifp->if_snd);
290 1.4.2.2 skrll
291 1.4.2.2 skrll if_attach(ifp);
292 1.4.2.2 skrll Ether_ifattach(ifp, eaddr);
293 1.4.2.2 skrll
294 1.4.2.2 skrll sc->cdce_attached = 1;
295 1.4.2.2 skrll splx(s);
296 1.4.2.2 skrll
297 1.4.2.2 skrll usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev,
298 1.4.2.2 skrll USBDEV(sc->cdce_dev));
299 1.4.2.2 skrll
300 1.4.2.2 skrll USB_ATTACH_SUCCESS_RETURN;
301 1.4.2.2 skrll }
302 1.4.2.2 skrll
303 1.4.2.2 skrll USB_DETACH(cdce)
304 1.4.2.2 skrll {
305 1.4.2.2 skrll USB_DETACH_START(cdce, sc);
306 1.4.2.2 skrll struct ifnet *ifp = GET_IFP(sc);
307 1.4.2.2 skrll int s;
308 1.4.2.2 skrll
309 1.4.2.2 skrll s = splusb();
310 1.4.2.2 skrll
311 1.4.2.2 skrll if (!sc->cdce_attached) {
312 1.4.2.2 skrll splx(s);
313 1.4.2.2 skrll return (0);
314 1.4.2.2 skrll }
315 1.4.2.2 skrll
316 1.4.2.2 skrll if (ifp->if_flags & IFF_RUNNING)
317 1.4.2.2 skrll cdce_stop(sc);
318 1.4.2.2 skrll
319 1.4.2.2 skrll ether_ifdetach(ifp);
320 1.4.2.2 skrll
321 1.4.2.2 skrll if_detach(ifp);
322 1.4.2.2 skrll
323 1.4.2.2 skrll sc->cdce_attached = 0;
324 1.4.2.2 skrll splx(s);
325 1.4.2.2 skrll
326 1.4.2.2 skrll return (0);
327 1.4.2.2 skrll }
328 1.4.2.2 skrll
329 1.4.2.2 skrll Static void
330 1.4.2.2 skrll cdce_start(struct ifnet *ifp)
331 1.4.2.2 skrll {
332 1.4.2.2 skrll struct cdce_softc *sc = ifp->if_softc;
333 1.4.2.2 skrll struct mbuf *m_head = NULL;
334 1.4.2.2 skrll
335 1.4.2.2 skrll if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE))
336 1.4.2.2 skrll return;
337 1.4.2.2 skrll
338 1.4.2.2 skrll IFQ_POLL(&ifp->if_snd, m_head);
339 1.4.2.2 skrll if (m_head == NULL)
340 1.4.2.2 skrll return;
341 1.4.2.2 skrll
342 1.4.2.2 skrll if (cdce_encap(sc, m_head, 0)) {
343 1.4.2.2 skrll ifp->if_flags |= IFF_OACTIVE;
344 1.4.2.2 skrll return;
345 1.4.2.2 skrll }
346 1.4.2.2 skrll
347 1.4.2.2 skrll IFQ_DEQUEUE(&ifp->if_snd, m_head);
348 1.4.2.2 skrll
349 1.4.2.2 skrll #if NBPFILTER > 0
350 1.4.2.2 skrll if (ifp->if_bpf)
351 1.4.2.2 skrll BPF_MTAP(ifp, m_head);
352 1.4.2.2 skrll #endif
353 1.4.2.2 skrll
354 1.4.2.2 skrll ifp->if_flags |= IFF_OACTIVE;
355 1.4.2.2 skrll
356 1.4.2.2 skrll ifp->if_timer = 6;
357 1.4.2.2 skrll }
358 1.4.2.2 skrll
359 1.4.2.2 skrll Static int
360 1.4.2.2 skrll cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx)
361 1.4.2.2 skrll {
362 1.4.2.2 skrll struct cdce_chain *c;
363 1.4.2.2 skrll usbd_status err;
364 1.4.2.2 skrll int extra = 0;
365 1.4.2.2 skrll
366 1.4.2.2 skrll c = &sc->cdce_cdata.cdce_tx_chain[idx];
367 1.4.2.2 skrll
368 1.4.2.2 skrll m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf);
369 1.4.2.2 skrll if (sc->cdce_flags & CDCE_ZAURUS) {
370 1.4.2.2 skrll /* Zaurus wants a 32-bit CRC appended to every frame */
371 1.4.2.2 skrll u_int32_t crc;
372 1.4.2.2 skrll
373 1.4.2.2 skrll crc = cdce_crc32(c->cdce_buf, m->m_pkthdr.len);
374 1.4.2.2 skrll bcopy(&crc, c->cdce_buf + m->m_pkthdr.len, 4);
375 1.4.2.2 skrll extra = 4;
376 1.4.2.2 skrll }
377 1.4.2.2 skrll c->cdce_mbuf = m;
378 1.4.2.2 skrll
379 1.4.2.2 skrll usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf,
380 1.4.2.2 skrll m->m_pkthdr.len + extra, USBD_NO_COPY, 10000, cdce_txeof);
381 1.4.2.2 skrll err = usbd_transfer(c->cdce_xfer);
382 1.4.2.2 skrll if (err != USBD_IN_PROGRESS) {
383 1.4.2.2 skrll cdce_stop(sc);
384 1.4.2.2 skrll return (EIO);
385 1.4.2.2 skrll }
386 1.4.2.2 skrll
387 1.4.2.2 skrll sc->cdce_cdata.cdce_tx_cnt++;
388 1.4.2.2 skrll
389 1.4.2.2 skrll return (0);
390 1.4.2.2 skrll }
391 1.4.2.2 skrll
392 1.4.2.2 skrll Static void
393 1.4.2.2 skrll cdce_stop(struct cdce_softc *sc)
394 1.4.2.2 skrll {
395 1.4.2.2 skrll usbd_status err;
396 1.4.2.2 skrll struct ifnet *ifp = GET_IFP(sc);
397 1.4.2.2 skrll int i;
398 1.4.2.2 skrll
399 1.4.2.2 skrll ifp->if_timer = 0;
400 1.4.2.2 skrll
401 1.4.2.2 skrll if (sc->cdce_bulkin_pipe != NULL) {
402 1.4.2.2 skrll err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
403 1.4.2.2 skrll if (err)
404 1.4.2.2 skrll printf("%s: abort rx pipe failed: %s\n",
405 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
406 1.4.2.2 skrll err = usbd_close_pipe(sc->cdce_bulkin_pipe);
407 1.4.2.2 skrll if (err)
408 1.4.2.2 skrll printf("%s: close rx pipe failed: %s\n",
409 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
410 1.4.2.2 skrll sc->cdce_bulkin_pipe = NULL;
411 1.4.2.2 skrll }
412 1.4.2.2 skrll
413 1.4.2.2 skrll if (sc->cdce_bulkout_pipe != NULL) {
414 1.4.2.2 skrll err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
415 1.4.2.2 skrll if (err)
416 1.4.2.2 skrll printf("%s: abort tx pipe failed: %s\n",
417 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
418 1.4.2.2 skrll err = usbd_close_pipe(sc->cdce_bulkout_pipe);
419 1.4.2.2 skrll if (err)
420 1.4.2.2 skrll printf("%s: close tx pipe failed: %s\n",
421 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
422 1.4.2.2 skrll sc->cdce_bulkout_pipe = NULL;
423 1.4.2.2 skrll }
424 1.4.2.2 skrll
425 1.4.2.2 skrll for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
426 1.4.2.2 skrll if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) {
427 1.4.2.2 skrll m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf);
428 1.4.2.2 skrll sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL;
429 1.4.2.2 skrll }
430 1.4.2.2 skrll if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) {
431 1.4.2.2 skrll usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer);
432 1.4.2.2 skrll sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL;
433 1.4.2.2 skrll }
434 1.4.2.2 skrll }
435 1.4.2.2 skrll
436 1.4.2.2 skrll for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
437 1.4.2.2 skrll if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) {
438 1.4.2.2 skrll m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf);
439 1.4.2.2 skrll sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL;
440 1.4.2.2 skrll }
441 1.4.2.2 skrll if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) {
442 1.4.2.2 skrll usbd_free_xfer(sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer);
443 1.4.2.2 skrll sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL;
444 1.4.2.2 skrll }
445 1.4.2.2 skrll }
446 1.4.2.2 skrll
447 1.4.2.2 skrll ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
448 1.4.2.2 skrll }
449 1.4.2.2 skrll
450 1.4.2.2 skrll Static int
451 1.4.2.2 skrll cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
452 1.4.2.2 skrll {
453 1.4.2.2 skrll struct cdce_softc *sc = ifp->if_softc;
454 1.4.2.2 skrll struct ifaddr *ifa = (struct ifaddr *)data;
455 1.4.2.2 skrll struct ifreq *ifr = (struct ifreq *)data;
456 1.4.2.2 skrll int s, error = 0;
457 1.4.2.2 skrll
458 1.4.2.2 skrll if (sc->cdce_dying)
459 1.4.2.2 skrll return (EIO);
460 1.4.2.2 skrll
461 1.4.2.2 skrll s = splnet();
462 1.4.2.2 skrll
463 1.4.2.2 skrll switch(command) {
464 1.4.2.2 skrll case SIOCSIFADDR:
465 1.4.2.2 skrll ifp->if_flags |= IFF_UP;
466 1.4.2.2 skrll cdce_init(sc);
467 1.4.2.2 skrll switch (ifa->ifa_addr->sa_family) {
468 1.4.2.2 skrll #ifdef INET
469 1.4.2.2 skrll case AF_INET:
470 1.4.2.2 skrll #if defined(__NetBSD__)
471 1.4.2.2 skrll arp_ifinit(ifp, ifa);
472 1.4.2.2 skrll #else
473 1.4.2.2 skrll arp_ifinit(&sc->arpcom, ifa);
474 1.4.2.2 skrll #endif
475 1.4.2.2 skrll break;
476 1.4.2.2 skrll #endif /* INET */
477 1.4.2.2 skrll #ifdef NS
478 1.4.2.2 skrll case AF_NS:
479 1.4.2.2 skrll {
480 1.4.2.2 skrll struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
481 1.4.2.2 skrll
482 1.4.2.2 skrll if (ns_nullhost(*ina))
483 1.4.2.2 skrll ina->x_host = *(union ns_host *)
484 1.4.2.2 skrll LLADDR(ifp->if_sadl);
485 1.4.2.2 skrll else
486 1.4.2.2 skrll memcpy(LLADDR(ifp->if_sadl),
487 1.4.2.2 skrll ina->x_host.c_host,
488 1.4.2.2 skrll ifp->if_addrlen);
489 1.4.2.2 skrll break;
490 1.4.2.2 skrll }
491 1.4.2.2 skrll #endif /* NS */
492 1.4.2.2 skrll }
493 1.4.2.2 skrll break;
494 1.4.2.2 skrll
495 1.4.2.2 skrll case SIOCSIFMTU:
496 1.4.2.2 skrll if (ifr->ifr_mtu > ETHERMTU)
497 1.4.2.2 skrll error = EINVAL;
498 1.4.2.2 skrll else
499 1.4.2.2 skrll ifp->if_mtu = ifr->ifr_mtu;
500 1.4.2.2 skrll break;
501 1.4.2.2 skrll
502 1.4.2.2 skrll case SIOCSIFFLAGS:
503 1.4.2.2 skrll if (ifp->if_flags & IFF_UP) {
504 1.4.2.2 skrll if (!(ifp->if_flags & IFF_RUNNING))
505 1.4.2.2 skrll cdce_init(sc);
506 1.4.2.2 skrll } else {
507 1.4.2.2 skrll if (ifp->if_flags & IFF_RUNNING)
508 1.4.2.2 skrll cdce_stop(sc);
509 1.4.2.2 skrll }
510 1.4.2.2 skrll error = 0;
511 1.4.2.2 skrll break;
512 1.4.2.2 skrll
513 1.4.2.2 skrll default:
514 1.4.2.2 skrll error = EINVAL;
515 1.4.2.2 skrll break;
516 1.4.2.2 skrll }
517 1.4.2.2 skrll
518 1.4.2.2 skrll splx(s);
519 1.4.2.2 skrll
520 1.4.2.2 skrll return (error);
521 1.4.2.2 skrll }
522 1.4.2.2 skrll
523 1.4.2.2 skrll Static void
524 1.4.2.2 skrll cdce_watchdog(struct ifnet *ifp)
525 1.4.2.2 skrll {
526 1.4.2.2 skrll struct cdce_softc *sc = ifp->if_softc;
527 1.4.2.2 skrll
528 1.4.2.2 skrll if (sc->cdce_dying)
529 1.4.2.2 skrll return;
530 1.4.2.2 skrll
531 1.4.2.2 skrll ifp->if_oerrors++;
532 1.4.2.2 skrll printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev));
533 1.4.2.2 skrll }
534 1.4.2.2 skrll
535 1.4.2.2 skrll Static void
536 1.4.2.2 skrll cdce_init(void *xsc)
537 1.4.2.2 skrll {
538 1.4.2.2 skrll struct cdce_softc *sc = xsc;
539 1.4.2.2 skrll struct ifnet *ifp = GET_IFP(sc);
540 1.4.2.2 skrll struct cdce_chain *c;
541 1.4.2.2 skrll usbd_status err;
542 1.4.2.2 skrll int s, i;
543 1.4.2.2 skrll
544 1.4.2.2 skrll if (ifp->if_flags & IFF_RUNNING)
545 1.4.2.2 skrll return;
546 1.4.2.2 skrll
547 1.4.2.2 skrll s = splnet();
548 1.4.2.2 skrll
549 1.4.2.2 skrll if (cdce_tx_list_init(sc) == ENOBUFS) {
550 1.4.2.2 skrll printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
551 1.4.2.2 skrll splx(s);
552 1.4.2.2 skrll return;
553 1.4.2.2 skrll }
554 1.4.2.2 skrll
555 1.4.2.2 skrll if (cdce_rx_list_init(sc) == ENOBUFS) {
556 1.4.2.2 skrll printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
557 1.4.2.2 skrll splx(s);
558 1.4.2.2 skrll return;
559 1.4.2.2 skrll }
560 1.4.2.2 skrll
561 1.4.2.2 skrll /* Maybe set multicast / broadcast here??? */
562 1.4.2.2 skrll
563 1.4.2.2 skrll err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
564 1.4.2.2 skrll USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
565 1.4.2.2 skrll if (err) {
566 1.4.2.2 skrll printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
567 1.4.2.2 skrll usbd_errstr(err));
568 1.4.2.2 skrll splx(s);
569 1.4.2.2 skrll return;
570 1.4.2.2 skrll }
571 1.4.2.2 skrll
572 1.4.2.2 skrll err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
573 1.4.2.2 skrll USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
574 1.4.2.2 skrll if (err) {
575 1.4.2.2 skrll printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
576 1.4.2.2 skrll usbd_errstr(err));
577 1.4.2.2 skrll splx(s);
578 1.4.2.2 skrll return;
579 1.4.2.2 skrll }
580 1.4.2.2 skrll
581 1.4.2.2 skrll for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
582 1.4.2.2 skrll c = &sc->cdce_cdata.cdce_rx_chain[i];
583 1.4.2.2 skrll usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c,
584 1.4.2.2 skrll c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
585 1.4.2.2 skrll USBD_NO_TIMEOUT, cdce_rxeof);
586 1.4.2.2 skrll usbd_transfer(c->cdce_xfer);
587 1.4.2.2 skrll }
588 1.4.2.2 skrll
589 1.4.2.2 skrll ifp->if_flags |= IFF_RUNNING;
590 1.4.2.2 skrll ifp->if_flags &= ~IFF_OACTIVE;
591 1.4.2.2 skrll
592 1.4.2.2 skrll splx(s);
593 1.4.2.2 skrll }
594 1.4.2.2 skrll
595 1.4.2.2 skrll Static int
596 1.4.2.2 skrll cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m)
597 1.4.2.2 skrll {
598 1.4.2.2 skrll struct mbuf *m_new = NULL;
599 1.4.2.2 skrll
600 1.4.2.2 skrll if (m == NULL) {
601 1.4.2.2 skrll MGETHDR(m_new, M_DONTWAIT, MT_DATA);
602 1.4.2.2 skrll if (m_new == NULL) {
603 1.4.2.2 skrll printf("%s: no memory for rx list "
604 1.4.2.2 skrll "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
605 1.4.2.2 skrll return (ENOBUFS);
606 1.4.2.2 skrll }
607 1.4.2.2 skrll MCLGET(m_new, M_DONTWAIT);
608 1.4.2.2 skrll if (!(m_new->m_flags & M_EXT)) {
609 1.4.2.2 skrll printf("%s: no memory for rx list "
610 1.4.2.2 skrll "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
611 1.4.2.2 skrll m_freem(m_new);
612 1.4.2.2 skrll return (ENOBUFS);
613 1.4.2.2 skrll }
614 1.4.2.2 skrll m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
615 1.4.2.2 skrll } else {
616 1.4.2.2 skrll m_new = m;
617 1.4.2.2 skrll m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
618 1.4.2.2 skrll m_new->m_data = m_new->m_ext.ext_buf;
619 1.4.2.2 skrll }
620 1.4.2.2 skrll c->cdce_mbuf = m_new;
621 1.4.2.2 skrll return (0);
622 1.4.2.2 skrll }
623 1.4.2.2 skrll
624 1.4.2.2 skrll Static int
625 1.4.2.2 skrll cdce_rx_list_init(struct cdce_softc *sc)
626 1.4.2.2 skrll {
627 1.4.2.2 skrll struct cdce_cdata *cd;
628 1.4.2.2 skrll struct cdce_chain *c;
629 1.4.2.2 skrll int i;
630 1.4.2.2 skrll
631 1.4.2.2 skrll cd = &sc->cdce_cdata;
632 1.4.2.2 skrll for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
633 1.4.2.2 skrll c = &cd->cdce_rx_chain[i];
634 1.4.2.2 skrll c->cdce_sc = sc;
635 1.4.2.2 skrll c->cdce_idx = i;
636 1.4.2.2 skrll if (cdce_newbuf(sc, c, NULL) == ENOBUFS)
637 1.4.2.2 skrll return (ENOBUFS);
638 1.4.2.2 skrll if (c->cdce_xfer == NULL) {
639 1.4.2.2 skrll c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev);
640 1.4.2.2 skrll if (c->cdce_xfer == NULL)
641 1.4.2.2 skrll return (ENOBUFS);
642 1.4.2.2 skrll c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ);
643 1.4.2.2 skrll if (c->cdce_buf == NULL)
644 1.4.2.2 skrll return (ENOBUFS);
645 1.4.2.2 skrll }
646 1.4.2.2 skrll }
647 1.4.2.2 skrll
648 1.4.2.2 skrll return (0);
649 1.4.2.2 skrll }
650 1.4.2.2 skrll
651 1.4.2.2 skrll Static int
652 1.4.2.2 skrll cdce_tx_list_init(struct cdce_softc *sc)
653 1.4.2.2 skrll {
654 1.4.2.2 skrll struct cdce_cdata *cd;
655 1.4.2.2 skrll struct cdce_chain *c;
656 1.4.2.2 skrll int i;
657 1.4.2.2 skrll
658 1.4.2.2 skrll cd = &sc->cdce_cdata;
659 1.4.2.2 skrll for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
660 1.4.2.2 skrll c = &cd->cdce_tx_chain[i];
661 1.4.2.2 skrll c->cdce_sc = sc;
662 1.4.2.2 skrll c->cdce_idx = i;
663 1.4.2.2 skrll c->cdce_mbuf = NULL;
664 1.4.2.2 skrll if (c->cdce_xfer == NULL) {
665 1.4.2.2 skrll c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev);
666 1.4.2.2 skrll if (c->cdce_xfer == NULL)
667 1.4.2.2 skrll return (ENOBUFS);
668 1.4.2.2 skrll c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ);
669 1.4.2.2 skrll if (c->cdce_buf == NULL)
670 1.4.2.2 skrll return (ENOBUFS);
671 1.4.2.2 skrll }
672 1.4.2.2 skrll }
673 1.4.2.2 skrll
674 1.4.2.2 skrll return (0);
675 1.4.2.2 skrll }
676 1.4.2.2 skrll
677 1.4.2.2 skrll Static void
678 1.4.2.2 skrll cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
679 1.4.2.2 skrll {
680 1.4.2.2 skrll struct cdce_chain *c = priv;
681 1.4.2.2 skrll struct cdce_softc *sc = c->cdce_sc;
682 1.4.2.2 skrll struct ifnet *ifp = GET_IFP(sc);
683 1.4.2.2 skrll struct mbuf *m;
684 1.4.2.2 skrll int total_len = 0;
685 1.4.2.2 skrll int s;
686 1.4.2.2 skrll
687 1.4.2.2 skrll if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
688 1.4.2.2 skrll return;
689 1.4.2.2 skrll
690 1.4.2.2 skrll if (status != USBD_NORMAL_COMPLETION) {
691 1.4.2.2 skrll if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
692 1.4.2.2 skrll return;
693 1.4.2.2 skrll if (sc->cdce_rxeof_errors == 0)
694 1.4.2.2 skrll printf("%s: usb error on rx: %s\n",
695 1.4.2.2 skrll USBDEVNAME(sc->cdce_dev), usbd_errstr(status));
696 1.4.2.2 skrll if (status == USBD_STALLED)
697 1.4.2.4 christos usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe);
698 1.4.2.2 skrll DELAY(sc->cdce_rxeof_errors * 10000);
699 1.4.2.2 skrll sc->cdce_rxeof_errors++;
700 1.4.2.2 skrll goto done;
701 1.4.2.2 skrll }
702 1.4.2.2 skrll
703 1.4.2.2 skrll sc->cdce_rxeof_errors = 0;
704 1.4.2.2 skrll
705 1.4.2.2 skrll usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
706 1.4.2.2 skrll if (sc->cdce_flags & CDCE_ZAURUS)
707 1.4.2.2 skrll total_len -= 4; /* Strip off CRC added by Zaurus */
708 1.4.2.2 skrll if (total_len <= 1)
709 1.4.2.2 skrll goto done;
710 1.4.2.2 skrll
711 1.4.2.2 skrll m = c->cdce_mbuf;
712 1.4.2.2 skrll memcpy(mtod(m, char *), c->cdce_buf, total_len);
713 1.4.2.2 skrll
714 1.4.2.2 skrll if (total_len < sizeof(struct ether_header)) {
715 1.4.2.2 skrll ifp->if_ierrors++;
716 1.4.2.2 skrll goto done;
717 1.4.2.2 skrll }
718 1.4.2.2 skrll
719 1.4.2.2 skrll ifp->if_ipackets++;
720 1.4.2.2 skrll m->m_pkthdr.len = m->m_len = total_len;
721 1.4.2.2 skrll m->m_pkthdr.rcvif = ifp;
722 1.4.2.2 skrll
723 1.4.2.2 skrll s = splnet();
724 1.4.2.2 skrll
725 1.4.2.2 skrll if (cdce_newbuf(sc, c, NULL) == ENOBUFS) {
726 1.4.2.2 skrll ifp->if_ierrors++;
727 1.4.2.2 skrll goto done1;
728 1.4.2.2 skrll }
729 1.4.2.2 skrll
730 1.4.2.2 skrll #if NBPFILTER > 0
731 1.4.2.2 skrll if (ifp->if_bpf)
732 1.4.2.2 skrll BPF_MTAP(ifp, m);
733 1.4.2.2 skrll #endif
734 1.4.2.2 skrll
735 1.4.2.2 skrll IF_INPUT(ifp, m);
736 1.4.2.2 skrll
737 1.4.2.2 skrll done1:
738 1.4.2.2 skrll splx(s);
739 1.4.2.2 skrll
740 1.4.2.2 skrll done:
741 1.4.2.2 skrll /* Setup new transfer. */
742 1.4.2.2 skrll usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf,
743 1.4.2.2 skrll CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
744 1.4.2.2 skrll cdce_rxeof);
745 1.4.2.2 skrll usbd_transfer(c->cdce_xfer);
746 1.4.2.2 skrll }
747 1.4.2.2 skrll
748 1.4.2.2 skrll Static void
749 1.4.2.2 skrll cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
750 1.4.2.2 skrll {
751 1.4.2.2 skrll struct cdce_chain *c = priv;
752 1.4.2.2 skrll struct cdce_softc *sc = c->cdce_sc;
753 1.4.2.2 skrll struct ifnet *ifp = GET_IFP(sc);
754 1.4.2.2 skrll usbd_status err;
755 1.4.2.2 skrll int s;
756 1.4.2.2 skrll
757 1.4.2.2 skrll if (sc->cdce_dying)
758 1.4.2.2 skrll return;
759 1.4.2.2 skrll
760 1.4.2.2 skrll s = splnet();
761 1.4.2.2 skrll
762 1.4.2.2 skrll ifp->if_timer = 0;
763 1.4.2.2 skrll ifp->if_flags &= ~IFF_OACTIVE;
764 1.4.2.2 skrll
765 1.4.2.2 skrll if (status != USBD_NORMAL_COMPLETION) {
766 1.4.2.2 skrll if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
767 1.4.2.2 skrll splx(s);
768 1.4.2.2 skrll return;
769 1.4.2.2 skrll }
770 1.4.2.2 skrll ifp->if_oerrors++;
771 1.4.2.2 skrll printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cdce_dev),
772 1.4.2.2 skrll usbd_errstr(status));
773 1.4.2.2 skrll if (status == USBD_STALLED)
774 1.4.2.4 christos usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe);
775 1.4.2.2 skrll splx(s);
776 1.4.2.2 skrll return;
777 1.4.2.2 skrll }
778 1.4.2.2 skrll
779 1.4.2.2 skrll usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err);
780 1.4.2.2 skrll
781 1.4.2.2 skrll if (c->cdce_mbuf != NULL) {
782 1.4.2.2 skrll m_freem(c->cdce_mbuf);
783 1.4.2.2 skrll c->cdce_mbuf = NULL;
784 1.4.2.2 skrll }
785 1.4.2.2 skrll
786 1.4.2.2 skrll if (err)
787 1.4.2.2 skrll ifp->if_oerrors++;
788 1.4.2.2 skrll else
789 1.4.2.2 skrll ifp->if_opackets++;
790 1.4.2.2 skrll
791 1.4.2.2 skrll if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
792 1.4.2.2 skrll cdce_start(ifp);
793 1.4.2.2 skrll
794 1.4.2.2 skrll splx(s);
795 1.4.2.2 skrll }
796 1.4.2.2 skrll
797 1.4.2.2 skrll int
798 1.4.2.2 skrll cdce_activate(device_ptr_t self, enum devact act)
799 1.4.2.2 skrll {
800 1.4.2.2 skrll struct cdce_softc *sc = (struct cdce_softc *)self;
801 1.4.2.2 skrll
802 1.4.2.2 skrll switch (act) {
803 1.4.2.2 skrll case DVACT_ACTIVATE:
804 1.4.2.2 skrll return (EOPNOTSUPP);
805 1.4.2.2 skrll break;
806 1.4.2.2 skrll
807 1.4.2.2 skrll case DVACT_DEACTIVATE:
808 1.4.2.2 skrll if_deactivate(GET_IFP(sc));
809 1.4.2.2 skrll sc->cdce_dying = 1;
810 1.4.2.2 skrll break;
811 1.4.2.2 skrll }
812 1.4.2.2 skrll return (0);
813 1.4.2.2 skrll }
814 1.4.2.2 skrll
815 1.4.2.2 skrll
816 1.4.2.2 skrll /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
817 1.4.2.2 skrll * code or tables extracted from it, as desired without restriction.
818 1.4.2.2 skrll */
819 1.4.2.2 skrll
820 1.4.2.2 skrll static uint32_t cdce_crc32_tab[] = {
821 1.4.2.2 skrll 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
822 1.4.2.2 skrll 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
823 1.4.2.2 skrll 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
824 1.4.2.2 skrll 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
825 1.4.2.2 skrll 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
826 1.4.2.2 skrll 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
827 1.4.2.2 skrll 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
828 1.4.2.2 skrll 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
829 1.4.2.2 skrll 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
830 1.4.2.2 skrll 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
831 1.4.2.2 skrll 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
832 1.4.2.2 skrll 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
833 1.4.2.2 skrll 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
834 1.4.2.2 skrll 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
835 1.4.2.2 skrll 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
836 1.4.2.2 skrll 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
837 1.4.2.2 skrll 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
838 1.4.2.2 skrll 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
839 1.4.2.2 skrll 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
840 1.4.2.2 skrll 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
841 1.4.2.2 skrll 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
842 1.4.2.2 skrll 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
843 1.4.2.2 skrll 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
844 1.4.2.2 skrll 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
845 1.4.2.2 skrll 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
846 1.4.2.2 skrll 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
847 1.4.2.2 skrll 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
848 1.4.2.2 skrll 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
849 1.4.2.2 skrll 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
850 1.4.2.2 skrll 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
851 1.4.2.2 skrll 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
852 1.4.2.2 skrll 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
853 1.4.2.2 skrll 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
854 1.4.2.2 skrll 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
855 1.4.2.2 skrll 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
856 1.4.2.2 skrll 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
857 1.4.2.2 skrll 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
858 1.4.2.2 skrll 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
859 1.4.2.2 skrll 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
860 1.4.2.2 skrll 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
861 1.4.2.2 skrll 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
862 1.4.2.2 skrll 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
863 1.4.2.2 skrll 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
864 1.4.2.2 skrll };
865 1.4.2.2 skrll
866 1.4.2.2 skrll Static uint32_t
867 1.4.2.2 skrll cdce_crc32(const void *buf, size_t size)
868 1.4.2.2 skrll {
869 1.4.2.2 skrll const uint8_t *p;
870 1.4.2.2 skrll uint32_t crc;
871 1.4.2.2 skrll
872 1.4.2.2 skrll p = buf;
873 1.4.2.2 skrll crc = ~0U;
874 1.4.2.2 skrll
875 1.4.2.2 skrll while (size--)
876 1.4.2.2 skrll crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
877 1.4.2.2 skrll
878 1.4.2.2 skrll return (crc ^ ~0U);
879 1.4.2.2 skrll }
880