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