0721cc7d1b31d58a8521b8d369af75bd6038433c
[dragonfly.git] / sys / dev / netif / lgue / if_lgue.c
1 /*
2  * LG-P500 Smartphone
3  * Written by Yellow Rabbit <yrabbit@sdf.lonestar.org>
4  */
5
6 /*
7  * XXX
8  * USB:
9  * Takes two interfaces.
10  * IN and OUT endpoints on the data interface (altsetting).
11  * Interrupt endpoint on the control interface.
12  *
13  * NET:
14  * Transfer frames without modification (AS IS).
15  */
16
17 #include <sys/param.h>
18 #include <sys/systm.h>
19 #include <sys/kernel.h>
20 #include <sys/socket.h>
21 #include <sys/sockio.h>
22 #include <sys/bus.h>
23
24 #include <net/if.h>
25 #include <net/ifq_var.h>
26 #include <net/if_arp.h>
27 #include <net/ethernet.h>
28 #include <net/bpf.h>
29
30 #include <bus/usb/usb.h>
31 #include <bus/usb/usbcdc.h>
32 #include <bus/usb/usbdi.h>
33 #include <bus/usb/usbdi_util.h>
34 #include <bus/usb/usbdivar.h>
35 #include <bus/usb/usb_ethersubr.h>
36
37 #include "if_lgue.h"
38
39 /*
40  * Supported device vendors/products
41  */
42 static struct usb_devno lgue_devs[] = {
43         { USB_DEVICE(0x1004, 0x61a2) }  /* LG P500 */
44 };
45
46 static int lgue_match(device_t);
47 static int lgue_attach(device_t);
48 static int lgue_detach(device_t);
49
50 static void lgue_start(struct ifnet *);
51 static void lgue_stop(struct lgue_softc *);
52 static void lgue_init(void *);
53 static void lgue_watchdog(struct ifnet *);
54 static int lgue_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
55
56 static int lgue_encap(struct lgue_softc *, struct mbuf *);
57 static int lgue_start_transfer(struct lgue_softc *);
58
59 static void lgue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
60
61 static int lgue_newbuf(struct lgue_softc *, int, struct mbuf **);
62 static void lgue_rxstart(struct ifnet *);
63 static void lgue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
64
65 static void lgue_intrstart(struct ifnet *);
66 static void lgue_intreof(usbd_xfer_handle, usbd_private_handle, usbd_status);
67
68 static int lgue_get_data_iface_no(usbd_device_handle,
69                usb_interface_descriptor_t *);
70
71 static int lgue_getmac(struct lgue_softc *, void *);
72 static int lgue_getmtu(struct lgue_softc *);
73
74 static int hex(char);
75
76 static device_method_t lgue_methods[] = {
77         DEVMETHOD(device_probe,  lgue_match),
78         DEVMETHOD(device_attach, lgue_attach),
79         DEVMETHOD(device_detach, lgue_detach),
80
81         { 0, 0 }
82 };
83
84 static driver_t lgue_driver = {
85         "lgue",
86         lgue_methods,
87         sizeof(struct lgue_softc)
88 };
89
90 static devclass_t lgue_devclass;
91
92 DECLARE_DUMMY_MODULE(if_lgue);
93 DRIVER_MODULE(lgue, uhub, lgue_driver, lgue_devclass, usbd_driver_load, NULL);
94 MODULE_DEPEND(lgue, usb, 1, 1, 1);
95
96 /*
97  * Probe chip
98  */
99 static int
100 lgue_match(device_t dev)
101 {
102         struct usb_attach_arg *uaa;
103         usb_interface_descriptor_t *id;
104
105         uaa = device_get_ivars(dev);
106         if (uaa->iface == NULL)
107                 return(UMATCH_NONE);
108
109         if (usb_lookup(lgue_devs, uaa->vendor, uaa->product) != NULL) {
110                 id = usbd_get_interface_descriptor(uaa->iface);
111                 if (id != NULL &&
112                     id->bInterfaceClass == UICLASS_CDC &&
113                     id->bInterfaceSubClass == UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
114                         return(UMATCH_VENDOR_PRODUCT);
115         }
116         return(UMATCH_NONE);
117 }
118
119 /*
120  * Attach the interface.
121  */
122 static int
123 lgue_attach(device_t dev)
124 {
125         struct lgue_softc *sc;
126         struct usb_attach_arg *uaa;
127         struct ifnet *ifp;
128         usb_interface_descriptor_t *id;
129         usb_endpoint_descriptor_t *ed;
130         int i;
131         u_char eaddr[ETHER_ADDR_LEN];
132         usbd_status err;
133
134         sc = device_get_softc(dev);
135         uaa = device_get_ivars(dev);
136
137         sc->lgue_ctl_iface = uaa->iface;
138         sc->lgue_udev = uaa->device;
139
140         /* It has only config but in case... */
141         if (usbd_set_config_no(sc->lgue_udev, LGUE_CONFIG_NO, 0)) {
142                 device_printf(dev, "setting config no %d failed\n",
143                     LGUE_CONFIG_NO);
144                 return(ENXIO);
145         }
146
147         /* Get control and data intefaces */
148         id = usbd_get_interface_descriptor(uaa->iface);
149         sc->lgue_ctl_iface_no = id->bInterfaceNumber;
150         sc->lgue_data_iface_no = lgue_get_data_iface_no(sc->lgue_udev, id);
151
152         if (sc->lgue_data_iface_no == -1) {
153                 device_printf(dev, "no data interface number\n");
154                 goto bad;
155         }
156
157         /* Claim data interface */
158         for (i = 0; i < uaa->nifaces; ++i) {
159                 if (uaa->ifaces[i] != NULL) {
160                         id = usbd_get_interface_descriptor(uaa->ifaces[i]);
161                         if (id != NULL &&
162                             id->bInterfaceNumber == sc->lgue_data_iface_no) {
163                                 err = usbd_set_interface(uaa->ifaces[i],
164                                     LGUE_ALTERNATE_SETTING);
165                                 if ( err != USBD_NORMAL_COMPLETION) {
166                                         device_printf(dev,
167                                             "no alternate data interface. err:%s\n",
168                                             usbd_errstr(err));
169                                         goto bad;
170                                 }
171                                 sc->lgue_data_iface = uaa->ifaces[i];
172                                 uaa->ifaces[i] = NULL;
173                         }
174                 }
175         }
176         if (sc->lgue_data_iface == NULL) {
177                 device_printf(dev, "no data interface\n");
178                 goto bad;
179         }
180
181         /* Find data interface endpoints */
182         id = usbd_get_interface_descriptor(sc->lgue_data_iface);
183         sc->lgue_ed[LGUE_ENDPT_RX] = sc->lgue_ed[LGUE_ENDPT_TX] = -1;
184         for (i = 0; i < id->bNumEndpoints; ++i) {
185                 ed = usbd_interface2endpoint_descriptor(sc->lgue_data_iface, i);
186                 if (!ed) {
187                         device_printf(dev,
188                             "couldn't get endpoint descriptor %d\n", i);
189                         goto bad;
190                 }
191                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
192                                 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
193                         sc->lgue_ed[LGUE_ENDPT_RX] = ed->bEndpointAddress;
194                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
195                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
196                         sc->lgue_ed[LGUE_ENDPT_TX] = ed->bEndpointAddress;
197                 }
198         }
199
200         if (sc->lgue_ed[LGUE_ENDPT_RX] == -1) {
201                 device_printf(dev, "couldn't find data bilk in\n");
202                 goto bad;
203         }
204         if (sc->lgue_ed[LGUE_ENDPT_TX] == -1) {
205                 device_printf(dev, "couldn't find data bilk out\n");
206                 goto bad;
207         }
208
209         /* Find control interface endpoint */
210         id = usbd_get_interface_descriptor(sc->lgue_ctl_iface);
211         sc->lgue_ed[LGUE_ENDPT_INTR] = -1;
212         for (i = 0; i < id->bNumEndpoints; ++i) {
213                 ed = usbd_interface2endpoint_descriptor(sc->lgue_ctl_iface, i);
214                 if (!ed) {
215                         device_printf(dev,
216                             "couldn't get endpoint descriptor %d\n", i);
217                         goto bad;
218                 }
219                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
220                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
221                         sc->lgue_ed[LGUE_ENDPT_INTR] = ed->bEndpointAddress;
222                 }
223         }
224
225         if (sc->lgue_ed[LGUE_ENDPT_INTR] == -1) {
226                 device_printf(dev, "couldn't find interrupt bilk in\n");
227                 goto bad;
228         }
229
230         /* Create interface */
231         ifp = &sc->lgue_arpcom.ac_if;
232         ifp->if_softc = sc;
233         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
234         lgue_getmac(sc, eaddr);
235
236         ifp->if_mtu = lgue_getmtu(sc);
237         ifp->if_data.ifi_mtu = ifp->if_mtu;
238         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
239         ifp->if_baudrate = 10000000;
240         ifp->if_ioctl = lgue_ioctl;
241         ifp->if_start = lgue_start;
242         ifp->if_watchdog = lgue_watchdog;
243         ifp->if_init = lgue_init;
244         ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
245         ifq_set_ready(&ifp->if_snd);
246
247         /* Call attach routine */
248         ether_ifattach(ifp, eaddr, NULL);
249         usb_register_netisr();
250         sc->lgue_dying = 0;
251         return(0);
252
253 bad:
254         return(ENXIO);
255 }
256
257 /*
258  * Device detached.
259  */
260 static int
261 lgue_detach(device_t dev)
262 {
263         struct lgue_softc *sc;
264         struct ifnet *ifp;
265
266         sc = device_get_softc(dev);
267         ifp = &sc->lgue_arpcom.ac_if;
268         ether_ifdetach(ifp);
269
270         if (sc->lgue_ep[LGUE_ENDPT_TX] != NULL)
271                 usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
272         if (sc->lgue_ep[LGUE_ENDPT_RX] != NULL)
273                 usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
274         if (sc->lgue_ep[LGUE_ENDPT_INTR] != NULL)
275                 usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
276         return(0);
277 }
278
279 /*
280  * Find data interface.
281  */
282 int
283 lgue_get_data_iface_no(usbd_device_handle dev, usb_interface_descriptor_t *id)
284 {
285         const usb_cdc_union_descriptor_t *cud;
286
287         cud = (const usb_cdc_union_descriptor_t *)usb_find_desc_if(dev,
288             UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION, id);
289         return(cud ? cud->bSlaveInterface[0] : -1);
290 }
291
292 /*
293  * Get hard max mtu
294  */
295 static int
296 lgue_getmtu(struct lgue_softc *sc)
297 {
298         const usb_cdc_ethernet_descriptor_t *ced;
299         usb_interface_descriptor_t *id;
300
301         id = usbd_get_interface_descriptor(sc->lgue_ctl_iface);
302         if (id == NULL) {
303                 kprintf("usbd_get_interface_descriptor() returned NULL\n");
304                 return(ETHERMTU);
305         }
306
307         ced = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc_if(sc->lgue_udev,
308             UDESC_CS_INTERFACE, UDESCSUB_CDC_ETHERNET, id);
309         if (ced == NULL) {
310                 kprintf("usb_find_desc_if() returned NULL\n");
311                 return(ETHERMTU);
312         }
313         return(UGETW(ced->wMaxSegmentSize));
314 }
315
316 /*
317  * Get mac address
318  */
319 static int
320 lgue_getmac(struct lgue_softc *sc, void *buf)
321 {
322         const usb_cdc_ethernet_descriptor_t *ced;
323         usb_interface_descriptor_t *id;
324         char sbuf[ETHER_ADDR_LEN * 2 + 1];
325         usbd_status err;
326         int i;
327
328         id = usbd_get_interface_descriptor(sc->lgue_ctl_iface);
329         if (id == NULL) goto bad;
330         ced = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc_if(sc->lgue_udev,
331             UDESC_CS_INTERFACE, UDESCSUB_CDC_ETHERNET, id);
332         if (ced == NULL) goto bad;
333
334         err = usbd_get_string(sc->lgue_udev, ced->iMACAddress, sbuf);
335         if(err) {
336                 kprintf("Read MAC address failed\n");
337                 goto bad;
338         }
339
340         for (i = 0; i < ETHER_ADDR_LEN; ++i) {
341                 ((uByte *)buf)[i] = (hex(sbuf[i * 2]) << 4) + hex(sbuf[(i * 2) + 1]);
342         }
343         return(0);
344 bad:
345         return(-1);
346 }
347
348 /*
349  * Listen INTR pipe
350  */
351 static void
352 lgue_intrstart(struct ifnet *ifp)
353 {
354         struct lgue_softc *sc;
355
356         sc = ifp->if_softc;
357         usbd_setup_xfer(sc->lgue_intr_xfer, sc->lgue_ep[LGUE_ENDPT_INTR], sc,
358             sc->lgue_intr_buf, LGUE_BUFSZ,
359             USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_intreof);
360         usbd_transfer(sc->lgue_intr_xfer);
361 }
362
363 /*
364  * INTR arrived
365  */
366 static void
367 lgue_intreof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
368 {
369         struct ifnet *ifp;
370         struct lgue_softc *sc;
371
372         sc = priv;
373         if (sc->lgue_dying)
374                 return;
375
376         ifp = &sc->lgue_arpcom.ac_if;
377         lwkt_serialize_enter(ifp->if_serializer);
378         if (status != USBD_NORMAL_COMPLETION) {
379                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
380                         lwkt_serialize_exit(ifp->if_serializer);
381                         return;
382                 }
383                 if_printf(ifp, "usb error on intr: %s\n", usbd_errstr(status));
384                 if (status == USBD_STALLED)
385                         usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_INTR]);
386                 lwkt_serialize_exit(ifp->if_serializer);
387                 return;
388         }
389         lgue_intrstart(ifp);
390         lwkt_serialize_exit(ifp->if_serializer);
391 }
392
393 /*
394  * Encap packet & send
395  */
396 static int
397 lgue_encap(struct lgue_softc *sc, struct mbuf *m)
398 {
399         struct ifnet *ifp;
400         struct lgue_queue_entry *entry;
401
402         ifp = &sc->lgue_arpcom.ac_if;
403         entry = kmalloc(sizeof(struct lgue_queue_entry), M_USBDEV , M_NOWAIT);
404         if (entry == NULL) {
405                 if_printf(ifp, "no memory for internal queue entry\n");
406                 return(ENOBUFS);
407         }
408         entry->entry_mbuf = m;
409
410         /* Put packet into internal queue tail */
411         STAILQ_INSERT_TAIL(&sc->lgue_tx_queue, entry, entry_next);
412         return(0);
413 }
414
415 /*
416  * Start transfer from internal queue
417  */
418 static int
419 lgue_start_transfer(struct lgue_softc *sc) {
420         usbd_status err;
421         struct lgue_queue_entry *entry;
422         struct ifnet *ifp;
423
424         if (STAILQ_EMPTY(&sc->lgue_tx_queue))
425                 return(0);
426
427         ifp = &sc->lgue_arpcom.ac_if;
428         entry = STAILQ_FIRST(&sc->lgue_tx_queue);
429         STAILQ_REMOVE_HEAD(&sc->lgue_tx_queue, entry_next);
430
431         m_copydata(entry->entry_mbuf, 0, entry->entry_mbuf->m_pkthdr.len,
432             sc->lgue_tx_buf);
433
434         /* Transmit */
435         usbd_setup_xfer(sc->lgue_tx_xfer, sc->lgue_ep[LGUE_ENDPT_TX], sc,
436             sc->lgue_tx_buf, entry->entry_mbuf->m_pkthdr.len,
437             USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_txeof);
438         err = usbd_transfer(sc->lgue_tx_xfer);
439         if (err != USBD_IN_PROGRESS) {
440                 m_freem(entry->entry_mbuf);
441                 kfree(entry, M_USBDEV);
442                 lgue_stop(sc);
443                 ifq_clr_oactive(&ifp->if_snd);
444                 return(EIO);
445         }
446
447         m_freem(entry->entry_mbuf);
448         kfree(entry, M_USBDEV);
449
450         sc->lgue_tx_cnt++;
451         ifq_set_oactive(&ifp->if_snd);
452         ifp->if_timer = 5;
453         return(0);
454 }
455
456 /*
457  * End of sending
458  */
459 static void
460 lgue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
461 {
462         struct ifnet *ifp;
463         struct lgue_softc *sc;
464         usbd_status err;
465
466         sc = priv;
467         if (sc->lgue_dying)
468                 return;
469
470         ifp = &sc->lgue_arpcom.ac_if;
471
472         if (status != USBD_NORMAL_COMPLETION) {
473                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
474                         return;
475                 if (status == USBD_STALLED)
476                         usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_TX]);
477                 return;
478         }
479         usbd_get_xfer_status(sc->lgue_tx_xfer, NULL, NULL, NULL,&err);
480         if (err)
481                 ifp->if_oerrors++;
482         else
483                 ifp->if_opackets++;
484
485         if (!STAILQ_EMPTY(&sc->lgue_tx_queue)) {
486                 if_devstart_sched(ifp);
487         }
488
489         ifp->if_timer = 0;
490         ifq_clr_oactive(&ifp->if_snd);
491 }
492
493 /*
494  * Start transfer
495  */
496 static void
497 lgue_start(struct ifnet *ifp)
498 {
499         struct lgue_softc *sc;
500         struct mbuf *m_head;
501
502         sc = ifp->if_softc;
503         if (sc->lgue_dying)
504                 return;
505
506         if (ifq_is_oactive(&ifp->if_snd)) {
507                 return;
508         }
509
510         /* To internal queue */
511         while ((m_head = ifq_dequeue(&ifp->if_snd, NULL)) != NULL) {
512                 if (lgue_encap(sc, m_head)) {
513                         m_freem(m_head);
514                         break;
515                 }
516                 /* Filter */
517                 BPF_MTAP(ifp, m_head);
518         }
519
520         lgue_start_transfer(sc);
521 }
522
523 /*
524  * Stop
525  */
526 static void
527 lgue_stop(struct lgue_softc *sc)
528 {
529         struct ifnet *ifp;
530         usbd_status err;
531         struct lgue_queue_entry *entry;
532
533         if (sc->lgue_dying)
534                 return;
535         sc->lgue_dying = 1;
536
537         ifp = &sc->lgue_arpcom.ac_if;
538
539         /* Stop transfers */
540         if (sc->lgue_ep[LGUE_ENDPT_TX] != NULL) {
541                 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
542                 if (err) {
543                         if_printf(ifp, "abort tx pipe failed:%s\n",
544                             usbd_errstr(err));
545                 }
546                 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
547                 if (err) {
548                         if_printf(ifp, "close tx pipe failed:%s\n",
549                             usbd_errstr(err));
550                 }
551         }
552         if (sc->lgue_ep[LGUE_ENDPT_RX] != NULL) {
553                 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
554                 if (err) {
555                         if_printf(ifp, "abort rx pipe failed:%s\n",
556                             usbd_errstr(err));
557                 }
558                 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
559                 if (err) {
560                         if_printf(ifp, "close rx pipe failed:%s\n",
561                             usbd_errstr(err));
562                 }
563         }
564         if (sc->lgue_ep[LGUE_ENDPT_INTR] != NULL) {
565                 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
566                 if (err) {
567                         if_printf(ifp, "abort intr pipe failed:%s\n",
568                             usbd_errstr(err));
569                 }
570                 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
571                 if (err) {
572                         if_printf(ifp, "close intr pipe failed:%s\n",
573                             usbd_errstr(err));
574                 }
575         }
576
577         /* Free tx buffers */
578         if (sc->lgue_tx_buf != NULL) {
579                 kfree(sc->lgue_tx_buf, M_USBDEV);
580                 sc->lgue_tx_buf = NULL;
581         }
582         if (sc->lgue_tx_xfer != NULL) {
583                 usbd_free_xfer(sc->lgue_tx_xfer);
584                 sc->lgue_tx_xfer = NULL;
585         }
586
587         /* Free rx buffers */
588         if (sc->lgue_rx_buf != NULL) {
589                 kfree(sc->lgue_rx_buf, M_USBDEV);
590                 sc->lgue_rx_buf = NULL;
591         }
592         if (sc->lgue_rx_xfer != NULL) {
593                 usbd_free_xfer(sc->lgue_rx_xfer);
594                 sc->lgue_rx_xfer = NULL;
595         }
596
597         /* Free intr buffer */
598         if (sc->lgue_intr_buf != NULL) {
599                 kfree(sc->lgue_intr_buf, M_USBDEV);
600                 sc->lgue_intr_buf = NULL;
601         }
602         if (sc->lgue_intr_xfer != NULL) {
603                 usbd_free_xfer(sc->lgue_intr_xfer);
604                 sc->lgue_intr_xfer = NULL;
605         }
606
607         /* Clear internal queue */
608         while (!STAILQ_EMPTY(&sc->lgue_tx_queue)) {
609                 entry = STAILQ_FIRST(&sc->lgue_tx_queue);
610                 STAILQ_REMOVE_HEAD(&sc->lgue_tx_queue, entry_next);
611                 m_freem(entry->entry_mbuf);
612                 kfree(entry, M_USBDEV);
613         }
614
615         ifp->if_flags &= ~IFF_RUNNING;
616         ifq_clr_oactive(&ifp->if_snd);
617 }
618
619 /*
620  * Init
621  */
622 static void
623 lgue_init(void *xsc)
624 {
625         struct lgue_softc *sc;
626         struct ifnet *ifp;
627         usbd_status err;
628
629         sc = xsc;
630         ifp = &sc->lgue_arpcom.ac_if;
631
632         if (ifp->if_flags & IFF_RUNNING)
633                 return;
634
635         /* Create RX and TX bufs */
636         if (sc->lgue_tx_xfer == NULL) {
637                 sc->lgue_tx_xfer = usbd_alloc_xfer(sc->lgue_udev);
638                 if (sc->lgue_tx_xfer == NULL) {
639                         if_printf(ifp, "tx buffer allocate failed\n");
640                         return;
641                 }
642         }
643         sc->lgue_tx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
644
645         if (sc->lgue_rx_xfer == NULL) {
646                 sc->lgue_rx_xfer = usbd_alloc_xfer(sc->lgue_udev);
647                 if (sc->lgue_rx_xfer == NULL) {
648                         if_printf(ifp, "rx buffer allocate failed\n");
649                         return;
650                 }
651         }
652         sc->lgue_rx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
653
654         /* Create INTR buf */
655         if (sc->lgue_intr_xfer == NULL) {
656                 sc->lgue_intr_xfer = usbd_alloc_xfer(sc->lgue_udev);
657                 if (sc->lgue_intr_xfer == NULL) {
658                         if_printf(ifp, "intr buffer allocate failed\n");
659                         return;
660                 }
661         }
662         sc->lgue_intr_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
663
664         /* Open RX and TX pipes. */
665         err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_RX],
666             USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_RX]);
667         if (err) {
668                 if_printf(ifp, "open RX pipe failed: %s\n", usbd_errstr(err));
669                 return;
670         }
671         err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_TX],
672             USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_TX]);
673         if (err) {
674                 if_printf(ifp, "open TX pipe failed: %s\n", usbd_errstr(err));
675                 return;
676         }
677         /* Open INTR pipe. */
678         err = usbd_open_pipe(sc->lgue_ctl_iface, sc->lgue_ed[LGUE_ENDPT_INTR],
679             USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_INTR]);
680         if (err) {
681                 if_printf(ifp, "open INTR pipe failed: %s\n", usbd_errstr(err));
682                 return;
683         }
684
685         /* Create internal queue */
686         STAILQ_INIT(&sc->lgue_tx_queue);
687
688         ifp->if_flags |= IFF_RUNNING;
689         ifq_clr_oactive(&ifp->if_snd);
690
691         sc->lgue_dying = 0;
692
693         lgue_rxstart(ifp);
694         lgue_intrstart(ifp);
695 }
696
697 /*
698  * New mbuf
699  */
700 static int
701 lgue_newbuf(struct lgue_softc *sc, int len, struct mbuf **m_buf)
702 {
703         struct ifnet *ifp;
704
705         ifp = &sc->lgue_arpcom.ac_if;
706         *m_buf = NULL;
707
708         /* Allocate mbuf */
709         *m_buf = m_getcl(MB_DONTWAIT, MT_DATA, MT_HEADER);
710         if (*m_buf == NULL) {
711                 if_printf(ifp, " no memory for rx buffer --- packet dropped!\n");
712                 return(ENOBUFS);
713         }
714         (*m_buf)->m_len = (*m_buf)->m_pkthdr.len = MCLBYTES;
715         m_adj(*m_buf, ETHER_ALIGN);
716         return(0);
717 }
718
719 /*
720  * Start read
721  */
722 static void
723 lgue_rxstart(struct ifnet *ifp)
724 {
725         struct lgue_softc *sc;
726
727         sc = ifp->if_softc;
728         if (sc->lgue_dying)
729                 return;
730
731         usbd_setup_xfer(sc->lgue_rx_xfer, sc->lgue_ep[LGUE_ENDPT_RX], sc,
732             sc->lgue_rx_buf, LGUE_BUFSZ,
733             USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_rxeof);
734         usbd_transfer(sc->lgue_rx_xfer);
735 }
736
737 /*
738  * A frame has been uploaded: pass the resulting mbuf up to
739  * the higher level protocols.
740  */
741 static void
742 lgue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
743 {
744         struct lgue_softc       *sc;
745         struct mbuf             *m;
746         struct ifnet    *ifp;
747         int                     total_len;
748
749         sc = priv;
750         if (sc->lgue_dying)
751                 return;
752
753         ifp = &sc->lgue_arpcom.ac_if;
754
755         total_len = 0;
756
757         if (!(ifp->if_flags & IFF_RUNNING))
758                 return;
759
760         if (status != USBD_NORMAL_COMPLETION) {
761                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
762                         return;
763                 if (usbd_ratecheck(&sc->lgue_rx_notice)) {
764                         if_printf(ifp, "usb error on rx:%s\n",
765                             usbd_errstr(status));
766                 }
767                 if (status == USBD_STALLED)
768                         usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_RX]);
769                 goto done;
770         }
771
772         usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
773
774         if (total_len < sizeof(struct ether_header)) {
775                 ifp->if_ierrors++;
776                 goto done;
777         }
778
779         if (lgue_newbuf(sc, total_len, &m) == ENOBUFS) {
780                 ifp->if_ierrors++;
781                 return;
782         }
783
784         ifp->if_ipackets++;
785         m_copyback(m, 0, total_len, sc->lgue_rx_buf);
786         m->m_pkthdr.rcvif = ifp;
787         m->m_pkthdr.len = m->m_len = total_len;
788
789         usb_ether_input(m);
790         lgue_rxstart(ifp);
791         return;
792 done:
793         usbd_setup_xfer(sc->lgue_rx_xfer, sc->lgue_ep[LGUE_ENDPT_RX], sc,
794             sc->lgue_rx_buf, LGUE_BUFSZ,
795             USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_rxeof);
796         usbd_transfer(sc->lgue_rx_xfer);
797 }
798
799 /*
800  * Control
801  */
802 static int
803 lgue_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
804 {
805         struct lgue_softc *sc;
806         struct ifreq *ifr;
807         int err;
808
809         err = 0;
810         ifr = (struct ifreq *)data;
811         sc = ifp->if_softc;
812
813         switch(command) {
814         case SIOCSIFFLAGS:
815                 if (ifp->if_flags & IFF_UP) {
816                         if (!(ifp->if_flags & IFF_RUNNING))
817                                 lgue_init(sc);
818                 } else if (ifp->if_flags & IFF_RUNNING) {
819                         lgue_stop(sc);
820                 }
821                 sc->lgue_if_flags = ifp->if_flags;
822                 err = 0;
823                 break;
824 #if 0
825         case SIOCADDMULTI:
826         case SIOCDELMULTI:
827                 err = 0;
828                 break;
829 #endif
830         case SIOCSIFMTU:
831                 ifp->if_mtu = ifr->ifr_mtu;
832                 break;
833         default:
834                 err = ether_ioctl(ifp, command, data);
835                 break;
836         }
837         return(err);
838 }
839
840 /*
841  * Watchdog
842  */
843 static void
844 lgue_watchdog(struct ifnet *ifp)
845 {
846         ifp->if_oerrors++;
847
848         if (!ifq_is_empty(&ifp->if_snd))
849                 if_devstart_sched(ifp);
850 }
851
852 /*
853  * Hex -> bin
854  */
855 static int
856 hex(char ch)
857 {
858         if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
859         if ((ch >= '0') && (ch <= '9')) return (ch-'0');
860         if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
861         return (-1);
862 }