]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/usb/if_cdce.c
Add codec id support for Analog Device AD1986 AC'97 codec.
[FreeBSD/FreeBSD.git] / sys / dev / usb / if_cdce.c
1 /*      $NetBSD: if_cdce.c,v 1.4 2004/10/24 12:50:54 augustss Exp $ */
2
3 /*
4  * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com>
5  * Copyright (c) 2003-2005 Craig Boston
6  * Copyright (c) 2004 Daniel Hartmeier
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Bill Paul.
20  * 4. Neither the name of the author nor the names of any co-contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul, THE VOICES IN HIS HEAD OR
28  * THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
31  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
34  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36
37 /*
38  * USB Communication Device Class (Ethernet Networking Control Model)
39  * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
40  */
41
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/sockio.h>
48 #include <sys/mbuf.h>
49 #include <sys/malloc.h>
50 #include <sys/kernel.h>
51 #include <sys/module.h>
52 #include <sys/socket.h>
53 #include <sys/endian.h>
54
55 #include <net/if.h>
56 #include <net/if_arp.h>
57 #include <net/ethernet.h>
58 #include <net/if_types.h>
59 #include <net/if_media.h>
60
61 #include <net/bpf.h>
62
63 #include <sys/bus.h>
64 #include <machine/bus.h>
65
66 #include <dev/usb/usb.h>
67 #include <dev/usb/usbdi.h>
68 #include <dev/usb/usbdi_util.h>
69 #include <dev/usb/usbdivar.h>
70 #include <dev/usb/usb_ethersubr.h>
71
72 #include <dev/usb/usbcdc.h>
73 #include "usbdevs.h"
74 #include <dev/usb/if_cdcereg.h>
75
76 Static device_shutdown_t cdce_shutdown;
77 USB_DECLARE_DRIVER_INIT(cdce,
78         DEVMETHOD(device_probe, cdce_match),
79         DEVMETHOD(device_attach, cdce_attach),
80         DEVMETHOD(device_detach, cdce_detach),
81         DEVMETHOD(device_shutdown, cdce_shutdown)
82         );
83 DRIVER_MODULE(cdce, uhub, cdce_driver, cdce_devclass, usbd_driver_load, 0);
84 MODULE_VERSION(cdce, 0);
85
86 Static int       cdce_encap(struct cdce_softc *, struct mbuf *, int);
87 Static void      cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
88 Static void      cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
89 Static void      cdce_start(struct ifnet *);
90 Static int       cdce_ioctl(struct ifnet *, u_long, caddr_t);
91 Static void      cdce_init(void *);
92 Static void      cdce_reset(struct cdce_softc *);
93 Static void      cdce_stop(struct cdce_softc *);
94 Static void      cdce_rxstart(struct ifnet *);
95 Static int       cdce_ifmedia_upd(struct ifnet *ifp);
96 Static void      cdce_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr);
97
98 Static const struct cdce_type cdce_devs[] = {
99   {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, CDCE_NO_UNION },
100   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_ZAURUS },
101   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300 }, CDCE_ZAURUS | CDCE_NO_UNION },
102   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS | CDCE_NO_UNION },
103   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700 }, CDCE_ZAURUS | CDCE_NO_UNION },
104   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750 }, CDCE_ZAURUS | CDCE_NO_UNION },
105   {{ USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00 }, CDCE_NO_UNION },
106   {{ USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_ETHERNETGADGET }, CDCE_NO_UNION },
107 };
108 #define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p))
109
110 USB_MATCH(cdce)
111 {
112         USB_MATCH_START(cdce, uaa);
113         usb_interface_descriptor_t *id;
114
115         if (uaa->iface == NULL)
116                 return (UMATCH_NONE);
117
118         id = usbd_get_interface_descriptor(uaa->iface);
119         if (id == NULL)
120                 return (UMATCH_NONE);
121
122         if (cdce_lookup(uaa->vendor, uaa->product) != NULL)
123                 return (UMATCH_VENDOR_PRODUCT);
124
125         if (id->bInterfaceClass == UICLASS_CDC && id->bInterfaceSubClass ==
126             UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
127                 return (UMATCH_IFACECLASS_GENERIC);
128
129         return (UMATCH_NONE);
130 }
131
132 USB_ATTACH(cdce)
133 {
134         USB_ATTACH_START(cdce, sc, uaa);
135         struct ifnet                    *ifp;
136         usbd_device_handle               dev = uaa->device;
137         const struct cdce_type          *t;
138         usb_interface_descriptor_t      *id;
139         usb_endpoint_descriptor_t       *ed;
140         const usb_cdc_union_descriptor_t *ud;
141         usb_config_descriptor_t         *cd;
142         int                              data_ifcno;
143         int                              i, j, numalts;
144         u_char                           eaddr[ETHER_ADDR_LEN];
145         const usb_cdc_ethernet_descriptor_t *ue;
146         char                             eaddr_str[USB_MAX_STRING_LEN];
147
148         bzero(sc, sizeof(struct cdce_softc));
149         sc->cdce_dev = self;
150         usbd_devinfo(dev, 0, sc->devinfo);
151         device_set_desc_copy(self, sc->devinfo);
152         printf("%s: %s\n", USBDEVNAME(sc->cdce_dev), sc->devinfo);
153
154         sc->cdce_udev = uaa->device;
155         sc->cdce_unit = device_get_unit(self);
156
157         t = cdce_lookup(uaa->vendor, uaa->product);
158         if (t)
159                 sc->cdce_flags = t->cdce_flags;
160
161         if (sc->cdce_flags & CDCE_NO_UNION)
162                 sc->cdce_data_iface = uaa->iface;
163         else {
164                 ud = (const usb_cdc_union_descriptor_t *)usb_find_desc(sc->cdce_udev,
165                     UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION);
166                 if (ud == NULL) {
167                         printf("%s: no union descriptor\n",
168                             USBDEVNAME(sc->cdce_dev));
169                         USB_ATTACH_ERROR_RETURN;
170                 }
171                 data_ifcno = ud->bSlaveInterface[0];
172
173                 for (i = 0; i < uaa->nifaces; i++) {
174                         if (uaa->ifaces[i] != NULL) {
175                                 id = usbd_get_interface_descriptor(
176                                     uaa->ifaces[i]);
177                                 if (id != NULL && id->bInterfaceNumber ==
178                                     data_ifcno) {
179                                         sc->cdce_data_iface = uaa->ifaces[i];
180                                         uaa->ifaces[i] = NULL;
181                                 }
182                         }
183                 }
184         }
185
186         if (sc->cdce_data_iface == NULL) {
187                 printf("%s: no data interface\n", USBDEVNAME(sc->cdce_dev));
188                 USB_ATTACH_ERROR_RETURN;
189         }
190
191         /*
192          * <quote>
193          *  The Data Class interface of a networking device shall have a minimum
194          *  of two interface settings. The first setting (the default interface
195          *  setting) includes no endpoints and therefore no networking traffic is
196          *  exchanged whenever the default interface setting is selected. One or
197          *  more additional interface settings are used for normal operation, and
198          *  therefore each includes a pair of endpoints (one IN, and one OUT) to
199          *  exchange network traffic. Select an alternate interface setting to
200          *  initialize the network aspects of the device and to enable the
201          *  exchange of network traffic.
202          * </quote>
203          *
204          * Some devices, most notably cable modems, include interface settings
205          * that have no IN or OUT endpoint, therefore loop through the list of all
206          * available interface settings looking for one with both IN and OUT
207          * endpoints.
208          */
209         id = usbd_get_interface_descriptor(sc->cdce_data_iface);
210         cd = usbd_get_config_descriptor(sc->cdce_udev);
211         numalts = usbd_get_no_alts(cd, id->bInterfaceNumber);
212
213         for (j = 0; j < numalts; j++) {
214                 if (usbd_set_interface(sc->cdce_data_iface, j)) {
215                         printf("%s: setting alternate interface failed\n",
216                             USBDEVNAME(sc->cdce_dev));
217                         USB_ATTACH_ERROR_RETURN;
218                 }
219                 /* Find endpoints. */
220                 id = usbd_get_interface_descriptor(sc->cdce_data_iface);
221                 sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1;
222                 for (i = 0; i < id->bNumEndpoints; i++) {
223                         ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i);
224                         if (!ed) {
225                                 printf("%s: could not read endpoint descriptor\n",
226                                     USBDEVNAME(sc->cdce_dev));
227                                 USB_ATTACH_ERROR_RETURN;
228                         }
229                         if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
230                             UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
231                                 sc->cdce_bulkin_no = ed->bEndpointAddress;
232                         } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
233                             UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
234                                 sc->cdce_bulkout_no = ed->bEndpointAddress;
235                         } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
236                             UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
237                                 /* XXX: CDC spec defines an interrupt pipe, but it is not
238                                  * needed for simple host-to-host applications. */
239                         } else {
240                                 printf("%s: unexpected endpoint\n",
241                                     USBDEVNAME(sc->cdce_dev));
242                         }
243                 }
244                 /* If we found something, try and use it... */
245                 if ((sc->cdce_bulkin_no != -1) && (sc->cdce_bulkout_no != -1))
246                         break;
247         }
248
249         if (sc->cdce_bulkin_no == -1) {
250                 printf("%s: could not find data bulk in\n",
251                     USBDEVNAME(sc->cdce_dev));
252                 USB_ATTACH_ERROR_RETURN;
253         }
254         if (sc->cdce_bulkout_no == -1 ) {
255                 printf("%s: could not find data bulk out\n",
256                     USBDEVNAME(sc->cdce_dev));
257                 USB_ATTACH_ERROR_RETURN;
258         }
259
260         mtx_init(&sc->cdce_mtx, USBDEVNAME(sc->cdce_dev), MTX_NETWORK_LOCK,
261             MTX_DEF | MTX_RECURSE);
262         ifmedia_init(&sc->cdce_ifmedia, 0, cdce_ifmedia_upd, cdce_ifmedia_sts);
263         CDCE_LOCK(sc);
264
265         ue = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc(dev,
266             UDESC_INTERFACE, UDESCSUB_CDC_ENF);
267         if (!ue || usbd_get_string(dev, ue->iMacAddress, eaddr_str)) {
268                 /* Fake MAC address */
269                 printf("%s: faking MAC address\n", USBDEVNAME(sc->cdce_dev));
270                 eaddr[0]= 0x2a;
271                 memcpy(&eaddr[1], &ticks, sizeof(u_int32_t));
272                 eaddr[5] = (u_int8_t)(sc->cdce_unit);
273         } else {
274                 int i;
275
276                 memset(eaddr, 0, ETHER_ADDR_LEN);
277                 for (i = 0; i < ETHER_ADDR_LEN * 2; i++) {
278                         int c = eaddr_str[i];
279
280                         if ('0' <= c && c <= '9')
281                                 c -= '0';
282                         else
283                                 c -= 'A' - 10;
284                         c &= 0xf;
285                         if (c % 2 == 0)
286                                 c <<= 4;
287                         eaddr[i / 2] |= c;
288                 }
289         }
290
291         ifp = GET_IFP(sc) = if_alloc(IFT_ETHER);
292         if (ifp == NULL) {
293                 printf("%s: can not if_alloc()\n", USBDEVNAME(sc->cdce_dev));
294                 CDCE_UNLOCK(sc);
295                 mtx_destroy(&sc->cdce_mtx);
296                 USB_ATTACH_ERROR_RETURN;
297         }
298         ifp->if_softc = sc;
299         if_initname(ifp, "cdce", sc->cdce_unit);
300         ifp->if_mtu = ETHERMTU;
301         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
302                 IFF_NEEDSGIANT;
303         ifp->if_ioctl = cdce_ioctl;
304         ifp->if_output = ether_output;
305         ifp->if_start = cdce_start;
306         ifp->if_init = cdce_init;
307         ifp->if_baudrate = 11000000;
308         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
309
310         sc->q.ifp = ifp;
311         sc->q.if_rxstart = cdce_rxstart;
312
313         /* No IFM type for 11Mbps USB, so go with 10baseT */
314         ifmedia_add(&sc->cdce_ifmedia, IFM_ETHER | IFM_10_T, 0, 0);
315         ifmedia_set(&sc->cdce_ifmedia, IFM_ETHER | IFM_10_T);
316
317         ether_ifattach(ifp, eaddr);
318         usb_register_netisr();
319
320         CDCE_UNLOCK(sc);
321
322         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev,
323             USBDEV(sc->cdce_dev));
324
325         USB_ATTACH_SUCCESS_RETURN;
326 }
327
328 USB_DETACH(cdce)
329 {
330         USB_DETACH_START(cdce, sc);
331         struct ifnet    *ifp;
332
333         CDCE_LOCK(sc);
334         sc->cdce_dying = 1;
335         ifp = GET_IFP(sc);
336         if (ifp->if_drv_flags & IFF_DRV_RUNNING)
337                 cdce_shutdown(sc->cdce_dev);
338
339         ether_ifdetach(ifp);
340         if_free(ifp);
341         ifmedia_removeall(&sc->cdce_ifmedia);
342         CDCE_UNLOCK(sc);
343         mtx_destroy(&sc->cdce_mtx);
344
345         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->cdce_udev,
346                 USBDEV(sc->cdce_dev));
347
348         return (0);
349 }
350
351 Static void
352 cdce_start(struct ifnet *ifp)
353 {
354         struct cdce_softc       *sc;
355         struct mbuf             *m_head = NULL;
356
357         sc = ifp->if_softc;
358         CDCE_LOCK(sc);
359
360
361         if (sc->cdce_dying ||
362                 ifp->if_drv_flags & IFF_DRV_OACTIVE ||
363                 !(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
364                 CDCE_UNLOCK(sc);
365                 return;
366         }
367
368         IF_DEQUEUE(&ifp->if_snd, m_head);
369         if (m_head == NULL) {
370                 CDCE_UNLOCK(sc);
371                 return;
372         }
373
374         if (cdce_encap(sc, m_head, 0)) {
375                 IF_PREPEND(&ifp->if_snd, m_head);
376                 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
377                 CDCE_UNLOCK(sc);
378                 return;
379         }
380
381         BPF_MTAP(ifp, m_head);
382
383         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
384
385         CDCE_UNLOCK(sc);
386
387         return;
388 }
389
390 Static int
391 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx)
392 {
393         struct ue_chain *c;
394         usbd_status              err;
395         int                      extra = 0;
396
397         c = &sc->cdce_cdata.ue_tx_chain[idx];
398
399         m_copydata(m, 0, m->m_pkthdr.len, c->ue_buf);
400         if (sc->cdce_flags & CDCE_ZAURUS) {
401                 /* Zaurus wants a 32-bit CRC appended to every frame */
402                 u_int32_t crc;
403
404                 crc = htole32(crc32(c->ue_buf, m->m_pkthdr.len));
405                 bcopy(&crc, c->ue_buf + m->m_pkthdr.len, 4);
406                 extra = 4;
407         }
408         c->ue_mbuf = m;
409
410         usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkout_pipe, c, c->ue_buf,
411             m->m_pkthdr.len + extra, 0, 10000, cdce_txeof);
412         err = usbd_transfer(c->ue_xfer);
413         if (err != USBD_IN_PROGRESS) {
414                 cdce_stop(sc);
415                 return (EIO);
416         }
417
418         sc->cdce_cdata.ue_tx_cnt++;
419
420         return (0);
421 }
422
423 Static void
424 cdce_stop(struct cdce_softc *sc)
425 {
426         usbd_status      err;
427         struct ifnet    *ifp;
428
429         CDCE_LOCK(sc);
430
431         cdce_reset(sc);
432
433         ifp = GET_IFP(sc);
434         ifp->if_timer = 0;
435
436         if (sc->cdce_bulkin_pipe != NULL) {
437                 err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
438                 if (err)
439                         printf("%s: abort rx pipe failed: %s\n",
440                             USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
441                 err = usbd_close_pipe(sc->cdce_bulkin_pipe);
442                 if (err)
443                         printf("%s: close rx pipe failed: %s\n",
444                             USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
445                 sc->cdce_bulkin_pipe = NULL;
446         }
447
448         if (sc->cdce_bulkout_pipe != NULL) {
449                 err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
450                 if (err)
451                         printf("%s: abort tx pipe failed: %s\n",
452                             USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
453                 err = usbd_close_pipe(sc->cdce_bulkout_pipe);
454                 if (err)
455                         printf("%s: close tx pipe failed: %s\n",
456                             USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
457                 sc->cdce_bulkout_pipe = NULL;
458         }
459
460         usb_ether_rx_list_free(&sc->cdce_cdata);
461         usb_ether_tx_list_free(&sc->cdce_cdata);
462
463         ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
464         CDCE_UNLOCK(sc);
465
466         return;
467 }
468
469 Static int
470 cdce_shutdown(device_ptr_t dev)
471 {
472         struct cdce_softc *sc;
473
474         sc = device_get_softc(dev);
475         cdce_stop(sc);
476
477         return (0);
478 }
479
480 Static int
481 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
482 {
483         struct cdce_softc       *sc = ifp->if_softc;
484         struct ifreq            *ifr = (struct ifreq *)data;
485         int                      error = 0;
486
487         if (sc->cdce_dying)
488                 return (ENXIO);
489
490         switch(command) {
491         case SIOCSIFFLAGS:
492                 if (ifp->if_flags & IFF_UP) {
493                         if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
494                                 cdce_init(sc);
495                 } else {
496                         if (ifp->if_drv_flags & IFF_DRV_RUNNING)
497                                 cdce_stop(sc);
498                 }
499                 error = 0;
500                 break;
501
502         case SIOCSIFMEDIA:
503         case SIOCGIFMEDIA:
504                 error = ifmedia_ioctl(ifp, ifr, &sc->cdce_ifmedia, command);
505                 break;
506
507         default:
508                 error = ether_ioctl(ifp, command, data);
509                 break;
510         }
511
512         return (error);
513 }
514
515 Static void
516 cdce_reset(struct cdce_softc *sc)
517 {
518         /* XXX Maybe reset the bulk pipes here? */
519         return;
520 }
521
522 Static void
523 cdce_init(void *xsc)
524 {
525         struct cdce_softc       *sc = xsc;
526         struct ifnet            *ifp = GET_IFP(sc);
527         struct ue_chain *c;
528         usbd_status              err;
529         int                      i;
530
531         if (ifp->if_drv_flags & IFF_DRV_RUNNING)
532                 return;
533
534         CDCE_LOCK(sc);
535         cdce_reset(sc);
536
537         if (usb_ether_tx_list_init(sc, &sc->cdce_cdata,
538             sc->cdce_udev) == ENOBUFS) {
539                 printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
540                 CDCE_UNLOCK(sc);
541                 return;
542         }
543
544         if (usb_ether_rx_list_init(sc, &sc->cdce_cdata,
545             sc->cdce_udev) == ENOBUFS) {
546                 printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
547                 CDCE_UNLOCK(sc);
548                 return;
549         }
550
551         /* Maybe set multicast / broadcast here??? */
552
553         err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
554             USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
555         if (err) {
556                 printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
557                     usbd_errstr(err));
558                 CDCE_UNLOCK(sc);
559                 return;
560         }
561
562         err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
563             USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
564         if (err) {
565                 printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
566                     usbd_errstr(err));
567                 CDCE_UNLOCK(sc);
568                 return;
569         }
570
571         for (i = 0; i < UE_RX_LIST_CNT; i++) {
572                 c = &sc->cdce_cdata.ue_rx_chain[i];
573                 usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c,
574                     mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK,
575                     USBD_NO_TIMEOUT, cdce_rxeof);
576                 usbd_transfer(c->ue_xfer);
577         }
578
579         ifp->if_drv_flags |= IFF_DRV_RUNNING;
580         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
581
582         CDCE_UNLOCK(sc);
583
584         return;
585 }
586
587 Static void
588 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
589 {
590         struct ue_chain *c = priv;
591         struct cdce_softc       *sc = c->ue_sc;
592         struct ifnet            *ifp;
593         struct mbuf             *m;
594         int                      total_len = 0;
595
596         CDCE_LOCK(sc);
597         ifp = GET_IFP(sc);
598
599         if (sc->cdce_dying || !(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
600                 CDCE_UNLOCK(sc);
601                 return;
602         }
603
604         if (status != USBD_NORMAL_COMPLETION) {
605                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
606                         CDCE_UNLOCK(sc);
607                         return;
608                 }
609                 if (sc->cdce_rxeof_errors == 0)
610                         printf("%s: usb error on rx: %s\n",
611                             USBDEVNAME(sc->cdce_dev), usbd_errstr(status));
612                 if (status == USBD_STALLED)
613                         usbd_clear_endpoint_stall(sc->cdce_bulkin_pipe);
614                 DELAY(sc->cdce_rxeof_errors * 10000);
615                 sc->cdce_rxeof_errors++;
616                 goto done;
617         }
618
619         sc->cdce_rxeof_errors = 0;
620
621         usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
622
623         if (sc->cdce_flags & CDCE_ZAURUS)
624                 total_len -= 4; /* Strip off CRC added by Zaurus */
625
626         m = c->ue_mbuf;
627
628         if (total_len < sizeof(struct ether_header)) {
629                 ifp->if_ierrors++;
630                 goto done;
631         }
632
633         ifp->if_ipackets++;
634         m->m_pkthdr.rcvif = (struct ifnet *)&sc->q;
635         m->m_pkthdr.len = m->m_len = total_len;
636
637         /* Put the packet on the special USB input queue. */
638         usb_ether_input(m);
639         CDCE_UNLOCK(sc);
640
641         return;
642
643 done:
644         /* Setup new transfer. */
645         usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c,
646             mtod(c->ue_mbuf, char *),
647             UE_BUFSZ, USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT,
648             cdce_rxeof);
649         usbd_transfer(c->ue_xfer);
650         CDCE_UNLOCK(sc);
651
652         return;
653 }
654
655 Static void
656 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
657 {
658         struct ue_chain *c = priv;
659         struct cdce_softc       *sc = c->ue_sc;
660         struct ifnet            *ifp;
661         usbd_status              err;
662
663         CDCE_LOCK(sc);
664         ifp = GET_IFP(sc);
665
666         if (sc->cdce_dying ||
667                 !(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
668                 CDCE_UNLOCK(sc);
669                 return;
670         }
671
672         if (status != USBD_NORMAL_COMPLETION) {
673                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
674                         CDCE_UNLOCK(sc);
675                         return;
676                 }
677                 ifp->if_oerrors++;
678                 printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cdce_dev),
679                     usbd_errstr(status));
680                 if (status == USBD_STALLED)
681                         usbd_clear_endpoint_stall(sc->cdce_bulkout_pipe);
682                 CDCE_UNLOCK(sc);
683                 return;
684         }
685
686         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
687         usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err);
688
689         if (c->ue_mbuf != NULL) {
690                 c->ue_mbuf->m_pkthdr.rcvif = ifp;
691                 usb_tx_done(c->ue_mbuf);
692                 c->ue_mbuf = NULL;
693         }
694
695         if (err)
696                 ifp->if_oerrors++;
697         else
698                 ifp->if_opackets++;
699
700         CDCE_UNLOCK(sc);
701
702         return;
703 }
704
705 Static void
706 cdce_rxstart(struct ifnet *ifp)
707 {
708         struct cdce_softc   *sc;
709         struct ue_chain   *c;
710
711         sc = ifp->if_softc;
712         CDCE_LOCK(sc);
713
714         if (sc->cdce_dying || !(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
715                 CDCE_UNLOCK(sc);
716                 return;
717         }
718
719         c = &sc->cdce_cdata.ue_rx_chain[sc->cdce_cdata.ue_rx_prod];
720
721         c->ue_mbuf = usb_ether_newbuf();
722         if (c->ue_mbuf == NULL) {
723                 printf("%s: no memory for rx list "
724                     "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
725                 ifp->if_ierrors++;
726                 CDCE_UNLOCK(sc);
727                 return;
728         }
729
730         usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c,
731             mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK,
732             USBD_NO_TIMEOUT, cdce_rxeof);
733         usbd_transfer(c->ue_xfer);
734
735         CDCE_UNLOCK(sc);
736         return;
737 }
738
739 Static int
740 cdce_ifmedia_upd(struct ifnet *ifp)
741 {
742
743         /* no-op, cdce has only 1 possible media type */
744         return 0;
745 }
746
747 Static void
748 cdce_ifmedia_sts(struct ifnet * const ifp, struct ifmediareq *req)
749 {
750
751         req->ifm_status = IFM_AVALID | IFM_ACTIVE;
752         req->ifm_active = IFM_ETHER | IFM_10_T;
753 }