if_cdce.c revision 1.12.10.8 1 1.12.10.7 itohy /* $NetBSD: if_cdce.c,v 1.12.10.8 2007/06/22 10:44:55 itohy 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.12.10.7 itohy __KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.12.10.8 2007/06/22 10:44:55 itohy 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
95 1.1 augustss #include <dev/usb/usb.h>
96 1.1 augustss #include <dev/usb/usbdi.h>
97 1.1 augustss #include <dev/usb/usbdi_util.h>
98 1.1 augustss #include <dev/usb/usbdevs.h>
99 1.1 augustss #include <dev/usb/usbcdc.h>
100 1.12.10.4 itohy #include <dev/usb/usb_ethersubr.h>
101 1.1 augustss
102 1.1 augustss #include <dev/usb/if_cdcereg.h>
103 1.1 augustss
104 1.1 augustss Static int cdce_encap(struct cdce_softc *, struct mbuf *, int);
105 1.1 augustss Static void cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
106 1.1 augustss Static void cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
107 1.1 augustss Static void cdce_start(struct ifnet *);
108 1.12.10.6 itohy Static int cdce_ioctl(struct ifnet *, u_long, usb_ioctlarg_t);
109 1.12.10.3 itohy Static int cdce_init(struct ifnet *);
110 1.1 augustss Static void cdce_watchdog(struct ifnet *);
111 1.12.10.3 itohy Static void cdce_stop(struct ifnet *, int);
112 1.12.10.2 itohy Static uint32_t cdce_crc32(struct mbuf *);
113 1.1 augustss
114 1.1 augustss Static const struct cdce_type cdce_devs[] = {
115 1.1 augustss {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, CDCE_NO_UNION },
116 1.1 augustss {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_ZAURUS },
117 1.1 augustss {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_ZAURUS | CDCE_NO_UNION },
118 1.1 augustss {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS | CDCE_NO_UNION },
119 1.1 augustss {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_ZAURUS | CDCE_NO_UNION },
120 1.1 augustss {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_ZAURUS | CDCE_NO_UNION },
121 1.1 augustss };
122 1.1 augustss #define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p))
123 1.1 augustss
124 1.1 augustss USB_DECLARE_DRIVER(cdce);
125 1.1 augustss
126 1.1 augustss USB_MATCH(cdce)
127 1.1 augustss {
128 1.12.10.7 itohy #ifndef USB_USE_IFATTACH
129 1.1 augustss USB_MATCH_START(cdce, uaa);
130 1.1 augustss usb_interface_descriptor_t *id;
131 1.1 augustss
132 1.1 augustss if (uaa->iface == NULL)
133 1.1 augustss return (UMATCH_NONE);
134 1.1 augustss
135 1.1 augustss id = usbd_get_interface_descriptor(uaa->iface);
136 1.1 augustss if (id == NULL)
137 1.1 augustss return (UMATCH_NONE);
138 1.12.10.7 itohy #else
139 1.12.10.7 itohy USB_IFMATCH_START(cdce, uaa);
140 1.12.10.7 itohy #endif /* USB_USE_IFATTACH */
141 1.1 augustss
142 1.1 augustss if (cdce_lookup(uaa->vendor, uaa->product) != NULL)
143 1.1 augustss return (UMATCH_VENDOR_PRODUCT);
144 1.1 augustss
145 1.12.10.7 itohy if (
146 1.12.10.7 itohy #ifndef USB_USE_IFATTACH
147 1.12.10.7 itohy id->bInterfaceClass == UICLASS_CDC && id->bInterfaceSubClass ==
148 1.12.10.7 itohy #else
149 1.12.10.7 itohy uaa->class == UICLASS_CDC && uaa->subclass ==
150 1.12.10.7 itohy #endif /* USB_USE_IFATTACH */
151 1.1 augustss UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
152 1.1 augustss return (UMATCH_IFACECLASS_GENERIC);
153 1.1 augustss
154 1.1 augustss return (UMATCH_NONE);
155 1.1 augustss }
156 1.1 augustss
157 1.1 augustss USB_ATTACH(cdce)
158 1.1 augustss {
159 1.12.10.7 itohy #ifndef USB_USE_IFATTACH
160 1.1 augustss USB_ATTACH_START(cdce, sc, uaa);
161 1.12.10.7 itohy #else
162 1.12.10.7 itohy USB_IFATTACH_START(cdce, sc, uaa);
163 1.12.10.7 itohy #endif /* USB_USE_IFATTACH */
164 1.6 augustss char *devinfop;
165 1.1 augustss int s;
166 1.1 augustss struct ifnet *ifp;
167 1.1 augustss usbd_device_handle dev = uaa->device;
168 1.1 augustss const struct cdce_type *t;
169 1.1 augustss usb_interface_descriptor_t *id;
170 1.1 augustss usb_endpoint_descriptor_t *ed;
171 1.2 augustss const usb_cdc_union_descriptor_t *ud;
172 1.1 augustss int data_ifcno;
173 1.1 augustss int i;
174 1.1 augustss u_char eaddr[ETHER_ADDR_LEN];
175 1.2 augustss const usb_cdc_ethernet_descriptor_t *ue;
176 1.5 augustss char eaddr_str[USB_MAX_ENCODED_STRING_LEN];
177 1.1 augustss
178 1.6 augustss devinfop = usbd_devinfo_alloc(dev, 0);
179 1.1 augustss USB_ATTACH_SETUP;
180 1.6 augustss printf("%s: %s\n", USBDEVNAME(sc->cdce_dev), devinfop);
181 1.6 augustss usbd_devinfo_free(devinfop);
182 1.1 augustss
183 1.1 augustss sc->cdce_udev = uaa->device;
184 1.1 augustss sc->cdce_ctl_iface = uaa->iface;
185 1.1 augustss
186 1.1 augustss t = cdce_lookup(uaa->vendor, uaa->product);
187 1.1 augustss if (t)
188 1.1 augustss sc->cdce_flags = t->cdce_flags;
189 1.1 augustss
190 1.1 augustss if (sc->cdce_flags & CDCE_NO_UNION)
191 1.1 augustss sc->cdce_data_iface = sc->cdce_ctl_iface;
192 1.1 augustss else {
193 1.7 christos ud = (const usb_cdc_union_descriptor_t *)usb_find_desc(sc->cdce_udev,
194 1.2 augustss UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION);
195 1.1 augustss if (ud == NULL) {
196 1.1 augustss printf("%s: no union descriptor\n",
197 1.1 augustss USBDEVNAME(sc->cdce_dev));
198 1.1 augustss USB_ATTACH_ERROR_RETURN;
199 1.1 augustss }
200 1.1 augustss data_ifcno = ud->bSlaveInterface[0];
201 1.1 augustss
202 1.1 augustss for (i = 0; i < uaa->nifaces; i++) {
203 1.1 augustss if (uaa->ifaces[i] != NULL) {
204 1.1 augustss id = usbd_get_interface_descriptor(
205 1.1 augustss uaa->ifaces[i]);
206 1.1 augustss if (id != NULL && id->bInterfaceNumber ==
207 1.1 augustss data_ifcno) {
208 1.1 augustss sc->cdce_data_iface = uaa->ifaces[i];
209 1.1 augustss uaa->ifaces[i] = NULL;
210 1.1 augustss }
211 1.1 augustss }
212 1.1 augustss }
213 1.1 augustss }
214 1.1 augustss
215 1.1 augustss if (sc->cdce_data_iface == NULL) {
216 1.1 augustss printf("%s: no data interface\n", USBDEVNAME(sc->cdce_dev));
217 1.1 augustss USB_ATTACH_ERROR_RETURN;
218 1.1 augustss }
219 1.1 augustss
220 1.1 augustss /* Find endpoints. */
221 1.1 augustss id = usbd_get_interface_descriptor(sc->cdce_data_iface);
222 1.1 augustss sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1;
223 1.1 augustss for (i = 0; i < id->bNumEndpoints; i++) {
224 1.1 augustss ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i);
225 1.1 augustss if (!ed) {
226 1.1 augustss printf("%s: could not read endpoint descriptor\n",
227 1.1 augustss USBDEVNAME(sc->cdce_dev));
228 1.1 augustss USB_ATTACH_ERROR_RETURN;
229 1.1 augustss }
230 1.1 augustss if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
231 1.1 augustss UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
232 1.1 augustss sc->cdce_bulkin_no = ed->bEndpointAddress;
233 1.1 augustss } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
234 1.1 augustss UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
235 1.1 augustss sc->cdce_bulkout_no = ed->bEndpointAddress;
236 1.1 augustss } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
237 1.1 augustss UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
238 1.1 augustss /* XXX: CDC spec defines an interrupt pipe, but it is not
239 1.1 augustss * needed for simple host-to-host applications. */
240 1.1 augustss } else {
241 1.1 augustss printf("%s: unexpected endpoint\n",
242 1.1 augustss USBDEVNAME(sc->cdce_dev));
243 1.1 augustss }
244 1.1 augustss }
245 1.1 augustss
246 1.1 augustss if (sc->cdce_bulkin_no == -1) {
247 1.1 augustss printf("%s: could not find data bulk in\n",
248 1.1 augustss USBDEVNAME(sc->cdce_dev));
249 1.1 augustss USB_ATTACH_ERROR_RETURN;
250 1.1 augustss }
251 1.1 augustss if (sc->cdce_bulkout_no == -1 ) {
252 1.1 augustss printf("%s: could not find data bulk out\n",
253 1.1 augustss USBDEVNAME(sc->cdce_dev));
254 1.1 augustss USB_ATTACH_ERROR_RETURN;
255 1.1 augustss }
256 1.1 augustss
257 1.7 christos ue = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc(dev,
258 1.2 augustss UDESC_INTERFACE, UDESCSUB_CDC_ENF);
259 1.2 augustss if (!ue || usbd_get_string(dev, ue->iMacAddress, eaddr_str)) {
260 1.2 augustss printf("%s: faking address\n", USBDEVNAME(sc->cdce_dev));
261 1.2 augustss eaddr[0]= 0x2a;
262 1.2 augustss memcpy(&eaddr[1], &hardclock_ticks, sizeof(u_int32_t));
263 1.9 thorpej eaddr[5] = (u_int8_t)(device_unit(&sc->cdce_dev));
264 1.2 augustss } else {
265 1.7 christos int j;
266 1.2 augustss
267 1.2 augustss memset(eaddr, 0, ETHER_ADDR_LEN);
268 1.7 christos for (j = 0; j < ETHER_ADDR_LEN * 2; j++) {
269 1.7 christos int c = eaddr_str[j];
270 1.2 augustss
271 1.2 augustss if ('0' <= c && c <= '9')
272 1.2 augustss c -= '0';
273 1.2 augustss else
274 1.3 augustss c -= 'A' - 10;
275 1.2 augustss c &= 0xf;
276 1.2 augustss if (c%2 == 0)
277 1.2 augustss c <<= 4;
278 1.7 christos eaddr[j / 2] |= c;
279 1.2 augustss }
280 1.2 augustss }
281 1.2 augustss
282 1.1 augustss s = splnet();
283 1.1 augustss
284 1.1 augustss printf("%s: address %s\n", USBDEVNAME(sc->cdce_dev),
285 1.1 augustss ether_sprintf(eaddr));
286 1.1 augustss
287 1.1 augustss ifp = GET_IFP(sc);
288 1.1 augustss ifp->if_softc = sc;
289 1.1 augustss ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
290 1.1 augustss ifp->if_ioctl = cdce_ioctl;
291 1.1 augustss ifp->if_start = cdce_start;
292 1.12.10.3 itohy ifp->if_init = cdce_init;
293 1.12.10.3 itohy ifp->if_stop = cdce_stop;
294 1.12.10.4 itohy ifp->if_watchdog = cdce_watchdog;
295 1.1 augustss strncpy(ifp->if_xname, USBDEVNAME(sc->cdce_dev), IFNAMSIZ);
296 1.1 augustss
297 1.1 augustss IFQ_SET_READY(&ifp->if_snd);
298 1.1 augustss
299 1.1 augustss if_attach(ifp);
300 1.1 augustss Ether_ifattach(ifp, eaddr);
301 1.1 augustss
302 1.1 augustss sc->cdce_attached = 1;
303 1.1 augustss splx(s);
304 1.1 augustss
305 1.1 augustss usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev,
306 1.1 augustss USBDEV(sc->cdce_dev));
307 1.1 augustss
308 1.1 augustss USB_ATTACH_SUCCESS_RETURN;
309 1.1 augustss }
310 1.1 augustss
311 1.1 augustss USB_DETACH(cdce)
312 1.1 augustss {
313 1.1 augustss USB_DETACH_START(cdce, sc);
314 1.1 augustss struct ifnet *ifp = GET_IFP(sc);
315 1.1 augustss int s;
316 1.1 augustss
317 1.1 augustss s = splusb();
318 1.1 augustss
319 1.1 augustss if (!sc->cdce_attached) {
320 1.1 augustss splx(s);
321 1.1 augustss return (0);
322 1.1 augustss }
323 1.1 augustss
324 1.1 augustss if (ifp->if_flags & IFF_RUNNING)
325 1.12.10.3 itohy cdce_stop(ifp, 1);
326 1.1 augustss
327 1.1 augustss ether_ifdetach(ifp);
328 1.1 augustss
329 1.1 augustss if_detach(ifp);
330 1.1 augustss
331 1.1 augustss sc->cdce_attached = 0;
332 1.1 augustss splx(s);
333 1.1 augustss
334 1.1 augustss return (0);
335 1.1 augustss }
336 1.1 augustss
337 1.1 augustss Static void
338 1.1 augustss cdce_start(struct ifnet *ifp)
339 1.1 augustss {
340 1.1 augustss struct cdce_softc *sc = ifp->if_softc;
341 1.1 augustss struct mbuf *m_head = NULL;
342 1.1 augustss
343 1.1 augustss if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE))
344 1.1 augustss return;
345 1.1 augustss
346 1.1 augustss IFQ_POLL(&ifp->if_snd, m_head);
347 1.1 augustss if (m_head == NULL)
348 1.1 augustss return;
349 1.1 augustss
350 1.1 augustss IFQ_DEQUEUE(&ifp->if_snd, m_head);
351 1.1 augustss
352 1.1 augustss #if NBPFILTER > 0
353 1.1 augustss if (ifp->if_bpf)
354 1.1 augustss BPF_MTAP(ifp, m_head);
355 1.1 augustss #endif
356 1.1 augustss
357 1.12.10.4 itohy if (cdce_encap(sc, m_head, 0)) {
358 1.12.10.4 itohy ifp->if_flags |= IFF_OACTIVE;
359 1.12.10.4 itohy return;
360 1.12.10.4 itohy }
361 1.12.10.4 itohy
362 1.1 augustss ifp->if_flags |= IFF_OACTIVE;
363 1.1 augustss
364 1.1 augustss ifp->if_timer = 6;
365 1.1 augustss }
366 1.1 augustss
367 1.1 augustss Static int
368 1.1 augustss cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx)
369 1.1 augustss {
370 1.12.10.4 itohy struct ue_chain *c;
371 1.1 augustss usbd_status err;
372 1.12.10.4 itohy int ret;
373 1.1 augustss
374 1.1 augustss c = &sc->cdce_cdata.cdce_tx_chain[idx];
375 1.1 augustss
376 1.1 augustss if (sc->cdce_flags & CDCE_ZAURUS) {
377 1.1 augustss /* Zaurus wants a 32-bit CRC appended to every frame */
378 1.12.10.2 itohy u_int32_t crc, crcle;
379 1.12.10.5 itohy int len;
380 1.1 augustss
381 1.12.10.2 itohy crc = cdce_crc32(m);
382 1.12.10.2 itohy crcle = htole32(crc);
383 1.12.10.5 itohy len = m->m_pkthdr.len + 4;
384 1.12.10.2 itohy m_copyback(m, m->m_pkthdr.len, 4, &crcle);
385 1.12.10.5 itohy if (m->m_pkthdr.len != len) {
386 1.12.10.5 itohy m_freem(m);
387 1.12.10.5 itohy return (ENOBUFS);
388 1.12.10.5 itohy }
389 1.1 augustss }
390 1.12.10.2 itohy
391 1.12.10.4 itohy ret = usb_ether_map_tx_buffer_mbuf(c, m);
392 1.12.10.4 itohy if (ret) {
393 1.12.10.2 itohy m_freem(m);
394 1.12.10.4 itohy return (ret);
395 1.12.10.2 itohy }
396 1.1 augustss
397 1.12.10.4 itohy usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkout_pipe, c, NULL /* XXX buf */,
398 1.12.10.8 itohy m->m_pkthdr.len, USBD_NO_COPY
399 1.12.10.8 itohy #ifdef __FreeBSD__ /* callback needs context */
400 1.12.10.8 itohy | USBD_CALLBACK_AS_TASK
401 1.12.10.8 itohy #endif
402 1.12.10.8 itohy , 10000, cdce_txeof);
403 1.12.10.4 itohy err = usbd_transfer(c->ue_xfer);
404 1.1 augustss if (err != USBD_IN_PROGRESS) {
405 1.12.10.4 itohy c->ue_mbuf = NULL;
406 1.12.10.4 itohy m_freem(m);
407 1.12.10.3 itohy cdce_stop(GET_IFP(sc), 0);
408 1.1 augustss return (EIO);
409 1.1 augustss }
410 1.1 augustss
411 1.1 augustss sc->cdce_cdata.cdce_tx_cnt++;
412 1.1 augustss
413 1.1 augustss return (0);
414 1.1 augustss }
415 1.1 augustss
416 1.1 augustss Static void
417 1.12.10.3 itohy cdce_stop(struct ifnet *ifp, int disable)
418 1.1 augustss {
419 1.12.10.3 itohy struct cdce_softc *sc = ifp->if_softc;
420 1.1 augustss usbd_status err;
421 1.1 augustss
422 1.1 augustss ifp->if_timer = 0;
423 1.1 augustss
424 1.12.10.2 itohy /* Stop transfers. */
425 1.1 augustss if (sc->cdce_bulkin_pipe != NULL) {
426 1.1 augustss err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
427 1.1 augustss if (err)
428 1.1 augustss printf("%s: abort rx pipe failed: %s\n",
429 1.1 augustss USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
430 1.1 augustss }
431 1.1 augustss
432 1.1 augustss if (sc->cdce_bulkout_pipe != NULL) {
433 1.1 augustss err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
434 1.1 augustss if (err)
435 1.1 augustss printf("%s: abort tx pipe failed: %s\n",
436 1.1 augustss USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
437 1.1 augustss }
438 1.1 augustss
439 1.12.10.2 itohy /* Free RX/TX list resources. */
440 1.12.10.4 itohy usb_ether_rx_list_free(sc->cdce_cdata.cdce_rx_chain, CDCE_RX_LIST_CNT);
441 1.12.10.4 itohy usb_ether_tx_list_free(sc->cdce_cdata.cdce_tx_chain, CDCE_TX_LIST_CNT);
442 1.1 augustss
443 1.12.10.2 itohy /* Close pipes. */
444 1.12.10.2 itohy if (sc->cdce_bulkin_pipe != NULL) {
445 1.12.10.2 itohy err = usbd_close_pipe(sc->cdce_bulkin_pipe);
446 1.12.10.2 itohy if (err)
447 1.12.10.2 itohy printf("%s: close rx pipe failed: %s\n",
448 1.12.10.2 itohy USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
449 1.12.10.2 itohy sc->cdce_bulkin_pipe = NULL;
450 1.12.10.2 itohy }
451 1.12.10.2 itohy
452 1.12.10.2 itohy if (sc->cdce_bulkout_pipe != NULL) {
453 1.12.10.2 itohy err = usbd_close_pipe(sc->cdce_bulkout_pipe);
454 1.12.10.2 itohy if (err)
455 1.12.10.2 itohy printf("%s: close tx pipe failed: %s\n",
456 1.12.10.2 itohy USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
457 1.12.10.2 itohy sc->cdce_bulkout_pipe = NULL;
458 1.12.10.2 itohy }
459 1.12.10.2 itohy
460 1.1 augustss ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
461 1.1 augustss }
462 1.1 augustss
463 1.1 augustss Static int
464 1.12.10.6 itohy cdce_ioctl(struct ifnet *ifp, u_long command, usb_ioctlarg_t data)
465 1.1 augustss {
466 1.1 augustss struct cdce_softc *sc = ifp->if_softc;
467 1.12.10.3 itohy int s, error;
468 1.1 augustss
469 1.1 augustss if (sc->cdce_dying)
470 1.1 augustss return (EIO);
471 1.1 augustss
472 1.1 augustss s = splnet();
473 1.1 augustss
474 1.1 augustss switch(command) {
475 1.12.10.3 itohy #if 0 /* no media support */
476 1.12.10.3 itohy case SIOCGIFMEDIA:
477 1.12.10.3 itohy case SIOCSIFMEDIA:
478 1.12.10.3 itohy error = EINVAL;
479 1.1 augustss break;
480 1.12.10.3 itohy #endif
481 1.1 augustss
482 1.12.10.3 itohy default:
483 1.12.10.3 itohy error = ether_ioctl(ifp, command, data);
484 1.12.10.3 itohy if (error == ENETRESET) {
485 1.12.10.3 itohy #if 0 /* XXX not yet */
486 1.1 augustss if (ifp->if_flags & IFF_RUNNING)
487 1.12.10.3 itohy cdce_setmulti(sc);
488 1.12.10.3 itohy #endif
489 1.12.10.3 itohy error = 0;
490 1.1 augustss }
491 1.1 augustss break;
492 1.1 augustss }
493 1.1 augustss
494 1.1 augustss splx(s);
495 1.1 augustss
496 1.1 augustss return (error);
497 1.1 augustss }
498 1.1 augustss
499 1.1 augustss Static void
500 1.1 augustss cdce_watchdog(struct ifnet *ifp)
501 1.1 augustss {
502 1.1 augustss struct cdce_softc *sc = ifp->if_softc;
503 1.1 augustss
504 1.1 augustss if (sc->cdce_dying)
505 1.1 augustss return;
506 1.1 augustss
507 1.1 augustss ifp->if_oerrors++;
508 1.1 augustss printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev));
509 1.1 augustss }
510 1.1 augustss
511 1.12.10.3 itohy Static int
512 1.12.10.3 itohy cdce_init(struct ifnet *ifp)
513 1.1 augustss {
514 1.12.10.3 itohy struct cdce_softc *sc = ifp->if_softc;
515 1.12.10.4 itohy struct ue_chain *c;
516 1.1 augustss usbd_status err;
517 1.1 augustss int s, i;
518 1.1 augustss
519 1.1 augustss if (ifp->if_flags & IFF_RUNNING)
520 1.12.10.3 itohy return (EIO);
521 1.1 augustss
522 1.1 augustss s = splnet();
523 1.1 augustss
524 1.1 augustss err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
525 1.1 augustss USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
526 1.1 augustss if (err) {
527 1.1 augustss printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
528 1.1 augustss usbd_errstr(err));
529 1.1 augustss splx(s);
530 1.12.10.3 itohy return (EIO);
531 1.1 augustss }
532 1.1 augustss
533 1.1 augustss err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
534 1.1 augustss USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
535 1.1 augustss if (err) {
536 1.1 augustss printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
537 1.1 augustss usbd_errstr(err));
538 1.1 augustss splx(s);
539 1.12.10.3 itohy return (EIO);
540 1.1 augustss }
541 1.1 augustss
542 1.12.10.4 itohy if (usb_ether_tx_list_init(USBDEV(sc->cdce_dev),
543 1.12.10.4 itohy sc->cdce_cdata.cdce_tx_chain, CDCE_TX_LIST_CNT,
544 1.12.10.4 itohy sc->cdce_udev, sc->cdce_bulkout_pipe, NULL)) {
545 1.12.10.2 itohy printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
546 1.12.10.2 itohy splx(s);
547 1.12.10.3 itohy return (EIO);
548 1.12.10.2 itohy }
549 1.12.10.2 itohy
550 1.12.10.4 itohy if (usb_ether_rx_list_init(USBDEV(sc->cdce_dev),
551 1.12.10.4 itohy sc->cdce_cdata.cdce_rx_chain, CDCE_RX_LIST_CNT,
552 1.12.10.4 itohy sc->cdce_udev, sc->cdce_bulkin_pipe)) {
553 1.12.10.2 itohy printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
554 1.12.10.2 itohy splx(s);
555 1.12.10.3 itohy return (ENOMEM);
556 1.12.10.2 itohy }
557 1.12.10.2 itohy
558 1.12.10.2 itohy /* Maybe set multicast / broadcast here??? */
559 1.12.10.2 itohy
560 1.1 augustss for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
561 1.1 augustss c = &sc->cdce_cdata.cdce_rx_chain[i];
562 1.12.10.4 itohy (void)usbd_map_buffer_mbuf(c->ue_xfer, c->ue_mbuf);
563 1.12.10.4 itohy usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c,
564 1.12.10.8 itohy NULL /* XXX buf */, CDCE_BUFSZ,
565 1.12.10.8 itohy USBD_SHORT_XFER_OK | USBD_NO_COPY
566 1.12.10.8 itohy #ifdef __FreeBSD__ /* callback needs context */
567 1.12.10.8 itohy | USBD_CALLBACK_AS_TASK
568 1.12.10.8 itohy #endif
569 1.12.10.8 itohy ,
570 1.1 augustss USBD_NO_TIMEOUT, cdce_rxeof);
571 1.12.10.4 itohy usbd_transfer(c->ue_xfer);
572 1.1 augustss }
573 1.1 augustss
574 1.1 augustss ifp->if_flags |= IFF_RUNNING;
575 1.1 augustss ifp->if_flags &= ~IFF_OACTIVE;
576 1.1 augustss
577 1.1 augustss splx(s);
578 1.12.10.3 itohy
579 1.12.10.3 itohy return (0);
580 1.1 augustss }
581 1.1 augustss
582 1.1 augustss Static void
583 1.1 augustss cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
584 1.1 augustss {
585 1.12.10.4 itohy struct ue_chain *c = priv;
586 1.12.10.4 itohy struct cdce_softc *sc = (void *)c->ue_dev;
587 1.1 augustss struct ifnet *ifp = GET_IFP(sc);
588 1.1 augustss struct mbuf *m;
589 1.1 augustss int total_len = 0;
590 1.1 augustss int s;
591 1.1 augustss
592 1.1 augustss if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
593 1.1 augustss return;
594 1.1 augustss
595 1.12.10.2 itohy usbd_unmap_buffer(xfer);
596 1.12.10.2 itohy
597 1.1 augustss if (status != USBD_NORMAL_COMPLETION) {
598 1.1 augustss if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
599 1.1 augustss return;
600 1.1 augustss if (sc->cdce_rxeof_errors == 0)
601 1.1 augustss printf("%s: usb error on rx: %s\n",
602 1.1 augustss USBDEVNAME(sc->cdce_dev), usbd_errstr(status));
603 1.1 augustss if (status == USBD_STALLED)
604 1.8 augustss usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe);
605 1.1 augustss DELAY(sc->cdce_rxeof_errors * 10000);
606 1.1 augustss sc->cdce_rxeof_errors++;
607 1.1 augustss goto done;
608 1.1 augustss }
609 1.1 augustss
610 1.1 augustss sc->cdce_rxeof_errors = 0;
611 1.1 augustss
612 1.1 augustss usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
613 1.1 augustss if (sc->cdce_flags & CDCE_ZAURUS)
614 1.1 augustss total_len -= 4; /* Strip off CRC added by Zaurus */
615 1.12.10.2 itohy
616 1.12.10.2 itohy if (total_len < sizeof(struct ether_header)) {
617 1.12.10.2 itohy ifp->if_ierrors++;
618 1.1 augustss goto done;
619 1.12.10.2 itohy }
620 1.1 augustss
621 1.12.10.4 itohy m = c->ue_mbuf;
622 1.1 augustss
623 1.12.10.2 itohy /*
624 1.12.10.2 itohy * Allocate new mbuf cluster for the next transfer.
625 1.12.10.2 itohy * If that failed, discard current packet and recycle the mbuf.
626 1.12.10.2 itohy */
627 1.12.10.4 itohy if ((c->ue_mbuf = usb_ether_newbuf(NULL)) == NULL) {
628 1.12.10.4 itohy printf("%s: no memory for rx list -- packet dropped!\n",
629 1.12.10.4 itohy USBDEVNAME(sc->cdce_dev));
630 1.1 augustss ifp->if_ierrors++;
631 1.12.10.4 itohy c->ue_mbuf = usb_ether_newbuf(m);
632 1.1 augustss goto done;
633 1.1 augustss }
634 1.1 augustss
635 1.1 augustss ifp->if_ipackets++;
636 1.1 augustss m->m_pkthdr.len = m->m_len = total_len;
637 1.1 augustss m->m_pkthdr.rcvif = ifp;
638 1.1 augustss
639 1.1 augustss s = splnet();
640 1.1 augustss
641 1.1 augustss #if NBPFILTER > 0
642 1.1 augustss if (ifp->if_bpf)
643 1.1 augustss BPF_MTAP(ifp, m);
644 1.1 augustss #endif
645 1.1 augustss
646 1.1 augustss IF_INPUT(ifp, m);
647 1.1 augustss
648 1.1 augustss splx(s);
649 1.1 augustss
650 1.1 augustss done:
651 1.1 augustss /* Setup new transfer. */
652 1.12.10.4 itohy (void)usbd_map_buffer_mbuf(c->ue_xfer, c->ue_mbuf);
653 1.12.10.4 itohy usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c, NULL /* XXX buf */,
654 1.12.10.8 itohy CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY
655 1.12.10.8 itohy #ifdef __FreeBSD__ /* callback needs context */
656 1.12.10.8 itohy | USBD_CALLBACK_AS_TASK
657 1.12.10.8 itohy #endif
658 1.12.10.8 itohy , USBD_NO_TIMEOUT,
659 1.1 augustss cdce_rxeof);
660 1.12.10.4 itohy usbd_transfer(c->ue_xfer);
661 1.1 augustss }
662 1.1 augustss
663 1.1 augustss Static void
664 1.12 christos cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
665 1.11 christos usbd_status status)
666 1.1 augustss {
667 1.12.10.4 itohy struct ue_chain *c = priv;
668 1.12.10.4 itohy struct cdce_softc *sc = (void *)c->ue_dev;
669 1.1 augustss struct ifnet *ifp = GET_IFP(sc);
670 1.1 augustss usbd_status err;
671 1.1 augustss int s;
672 1.1 augustss
673 1.1 augustss if (sc->cdce_dying)
674 1.1 augustss return;
675 1.1 augustss
676 1.12.10.2 itohy usbd_unmap_buffer(xfer);
677 1.12.10.2 itohy
678 1.1 augustss s = splnet();
679 1.1 augustss
680 1.1 augustss ifp->if_timer = 0;
681 1.1 augustss ifp->if_flags &= ~IFF_OACTIVE;
682 1.1 augustss
683 1.1 augustss if (status != USBD_NORMAL_COMPLETION) {
684 1.1 augustss if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
685 1.1 augustss splx(s);
686 1.1 augustss return;
687 1.1 augustss }
688 1.1 augustss ifp->if_oerrors++;
689 1.1 augustss printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cdce_dev),
690 1.1 augustss usbd_errstr(status));
691 1.1 augustss if (status == USBD_STALLED)
692 1.8 augustss usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe);
693 1.1 augustss splx(s);
694 1.1 augustss return;
695 1.1 augustss }
696 1.1 augustss
697 1.12.10.4 itohy usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err);
698 1.1 augustss
699 1.12.10.4 itohy if (c->ue_mbuf != NULL) {
700 1.12.10.4 itohy m_freem(c->ue_mbuf);
701 1.12.10.4 itohy c->ue_mbuf = NULL;
702 1.1 augustss }
703 1.1 augustss
704 1.1 augustss if (err)
705 1.1 augustss ifp->if_oerrors++;
706 1.1 augustss else
707 1.1 augustss ifp->if_opackets++;
708 1.1 augustss
709 1.1 augustss if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
710 1.1 augustss cdce_start(ifp);
711 1.1 augustss
712 1.1 augustss splx(s);
713 1.1 augustss }
714 1.1 augustss
715 1.4 augustss int
716 1.1 augustss cdce_activate(device_ptr_t self, enum devact act)
717 1.1 augustss {
718 1.1 augustss struct cdce_softc *sc = (struct cdce_softc *)self;
719 1.1 augustss
720 1.1 augustss switch (act) {
721 1.1 augustss case DVACT_ACTIVATE:
722 1.1 augustss return (EOPNOTSUPP);
723 1.1 augustss break;
724 1.1 augustss
725 1.1 augustss case DVACT_DEACTIVATE:
726 1.1 augustss if_deactivate(GET_IFP(sc));
727 1.1 augustss sc->cdce_dying = 1;
728 1.1 augustss break;
729 1.1 augustss }
730 1.1 augustss return (0);
731 1.1 augustss }
732 1.1 augustss
733 1.1 augustss
734 1.1 augustss /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
735 1.1 augustss * code or tables extracted from it, as desired without restriction.
736 1.1 augustss */
737 1.1 augustss
738 1.12.10.2 itohy static const uint32_t cdce_crc32_tab[] = {
739 1.1 augustss 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
740 1.1 augustss 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
741 1.1 augustss 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
742 1.1 augustss 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
743 1.1 augustss 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
744 1.1 augustss 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
745 1.1 augustss 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
746 1.1 augustss 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
747 1.1 augustss 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
748 1.1 augustss 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
749 1.1 augustss 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
750 1.1 augustss 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
751 1.1 augustss 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
752 1.1 augustss 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
753 1.1 augustss 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
754 1.1 augustss 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
755 1.1 augustss 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
756 1.1 augustss 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
757 1.1 augustss 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
758 1.1 augustss 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
759 1.1 augustss 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
760 1.1 augustss 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
761 1.1 augustss 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
762 1.1 augustss 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
763 1.1 augustss 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
764 1.1 augustss 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
765 1.1 augustss 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
766 1.1 augustss 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
767 1.1 augustss 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
768 1.1 augustss 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
769 1.1 augustss 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
770 1.1 augustss 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
771 1.1 augustss 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
772 1.1 augustss 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
773 1.1 augustss 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
774 1.1 augustss 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
775 1.1 augustss 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
776 1.1 augustss 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
777 1.1 augustss 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
778 1.1 augustss 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
779 1.1 augustss 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
780 1.1 augustss 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
781 1.1 augustss 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
782 1.1 augustss };
783 1.1 augustss
784 1.2 augustss Static uint32_t
785 1.12.10.2 itohy cdce_crc32(struct mbuf *m)
786 1.1 augustss {
787 1.1 augustss const uint8_t *p;
788 1.1 augustss uint32_t crc;
789 1.12.10.2 itohy int len;
790 1.1 augustss
791 1.1 augustss crc = ~0U;
792 1.1 augustss
793 1.12.10.2 itohy for ( ; m; m = m->m_next) {
794 1.12.10.2 itohy for (p = mtod(m, uint8_t *), len = m->m_len; len > 0; len--) {
795 1.12.10.2 itohy crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
796 1.12.10.2 itohy }
797 1.12.10.2 itohy }
798 1.1 augustss
799 1.1 augustss return (crc ^ ~0U);
800 1.1 augustss }
801