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