3 * Written by Yellow Rabbit <yrabbit@sdf.lonestar.org>
9 * Takes two interfaces.
10 * IN and OUT endpoints on the data interface (altsetting).
11 * Interrupt endpoint on the control interface.
14 * Transfer frames without modification (AS IS).
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>
25 #include <net/ifq_var.h>
26 #include <net/if_arp.h>
27 #include <net/ethernet.h>
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>
40 * Supported device vendors/products
42 static struct usb_devno lgue_devs[] = {
43 { USB_DEVICE(0x01004, 0x61a2) } /* LG P500 */
46 static int lgue_match(device_t);
47 static int lgue_attach(device_t);
48 static int lgue_detach(device_t);
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 *);
56 static int lgue_encap(struct lgue_softc *, struct mbuf *);
57 static int lgue_start_transfer(struct lgue_softc *);
59 static void lgue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
61 static void lgue_start_ipifunc(void *);
62 static void lgue_start_schedule(struct ifnet *);
64 static int lgue_newbuf(struct lgue_softc *, int, struct mbuf **);
65 static void lgue_rxstart(struct ifnet *);
66 static void lgue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
68 static void lgue_intrstart(struct ifnet *);
69 static void lgue_intreof(usbd_xfer_handle, usbd_private_handle, usbd_status);
71 static int lgue_get_data_iface_no(usbd_device_handle,
72 usb_interface_descriptor_t *);
74 static int lgue_getmac(struct lgue_softc *, void *);
75 static int lgue_getmtu(struct lgue_softc *);
79 static device_method_t lgue_methods[] = {
80 DEVMETHOD(device_probe, lgue_match),
81 DEVMETHOD(device_attach, lgue_attach),
82 DEVMETHOD(device_detach, lgue_detach),
87 static driver_t lgue_driver = {
90 sizeof(struct lgue_softc)
93 static devclass_t lgue_devclass;
95 DECLARE_DUMMY_MODULE(if_lgue);
96 DRIVER_MODULE(lgue, uhub, lgue_driver, lgue_devclass, usbd_driver_load, 0);
97 MODULE_DEPEND(lgue, usb, 1, 1, 1);
103 lgue_match(device_t dev)
105 struct usb_attach_arg *uaa;
106 usb_interface_descriptor_t *id;
108 uaa = device_get_ivars(dev);
109 if (uaa->iface == NULL)
112 if (usb_lookup(lgue_devs, uaa->vendor, uaa->product) != NULL) {
113 id = usbd_get_interface_descriptor(uaa->iface);
115 id->bInterfaceClass == UICLASS_CDC &&
116 id->bInterfaceSubClass == UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
117 return(UMATCH_VENDOR_PRODUCT);
123 * Attach the interface.
126 lgue_attach(device_t dev)
128 struct lgue_softc *sc;
129 struct usb_attach_arg *uaa;
131 usb_interface_descriptor_t *id;
132 usb_endpoint_descriptor_t *ed;
134 u_char eaddr[ETHER_ADDR_LEN];
137 sc = device_get_softc(dev);
138 uaa = device_get_ivars(dev);
140 sc->lgue_ctl_iface = uaa->iface;
141 sc->lgue_udev = uaa->device;
143 /* It has only config but in case... */
144 if (usbd_set_config_no(sc->lgue_udev, LGUE_CONFIG_NO, 0)) {
145 device_printf(dev, "setting config no %d failed\n",
150 /* Get control and data intefaces */
151 id = usbd_get_interface_descriptor(uaa->iface);
152 sc->lgue_ctl_iface_no = id->bInterfaceNumber;
153 sc->lgue_data_iface_no = lgue_get_data_iface_no(sc->lgue_udev, id);
155 if (sc->lgue_data_iface_no == -1) {
156 device_printf(dev, "no data interface number\n");
160 /* Claim data interface */
161 for (i = 0; i < uaa->nifaces; ++i) {
162 if (uaa->ifaces[i] != NULL) {
163 id = usbd_get_interface_descriptor(uaa->ifaces[i]);
165 id->bInterfaceNumber == sc->lgue_data_iface_no) {
166 err = usbd_set_interface(uaa->ifaces[i],
167 LGUE_ALTERNATE_SETTING);
168 if ( err != USBD_NORMAL_COMPLETION) {
170 "no alternate data interface. err:%s\n",
174 sc->lgue_data_iface = uaa->ifaces[i];
175 uaa->ifaces[i] = NULL;
179 if (sc->lgue_data_iface == NULL) {
180 device_printf(dev, "no data interface\n");
184 /* Find data interface endpoints */
185 id = usbd_get_interface_descriptor(sc->lgue_data_iface);
186 sc->lgue_ed[LGUE_ENDPT_RX] = sc->lgue_ed[LGUE_ENDPT_TX] = -1;
187 for (i = 0; i < id->bNumEndpoints; ++i) {
188 ed = usbd_interface2endpoint_descriptor(sc->lgue_data_iface, i);
191 "couldn't get endpoint descriptor %d\n", i);
194 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
195 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
196 sc->lgue_ed[LGUE_ENDPT_RX] = ed->bEndpointAddress;
197 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
198 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
199 sc->lgue_ed[LGUE_ENDPT_TX] = ed->bEndpointAddress;
203 if (sc->lgue_ed[LGUE_ENDPT_RX] == -1) {
204 device_printf(dev, "couldn't find data bilk in\n");
207 if (sc->lgue_ed[LGUE_ENDPT_TX] == -1) {
208 device_printf(dev, "couldn't find data bilk out\n");
212 /* Find control interface endpoint */
213 id = usbd_get_interface_descriptor(sc->lgue_ctl_iface);
214 sc->lgue_ed[LGUE_ENDPT_INTR] = -1;
215 for (i = 0; i < id->bNumEndpoints; ++i) {
216 ed = usbd_interface2endpoint_descriptor(sc->lgue_ctl_iface, i);
219 "couldn't get endpoint descriptor %d\n", i);
222 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
223 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
224 sc->lgue_ed[LGUE_ENDPT_INTR] = ed->bEndpointAddress;
228 if (sc->lgue_ed[LGUE_ENDPT_INTR] == -1) {
229 device_printf(dev, "couldn't find interrupt bilk in\n");
233 /* Create interface */
234 ifp = &sc->lgue_arpcom.ac_if;
236 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
237 lgue_getmac(sc, eaddr);
239 ifp->if_mtu = lgue_getmtu(sc);
240 ifp->if_data.ifi_mtu = ifp->if_mtu;
241 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
242 ifp->if_baudrate = 10000000;
243 ifp->if_ioctl = lgue_ioctl;
244 ifp->if_start = lgue_start;
245 ifp->if_watchdog = lgue_watchdog;
246 ifp->if_init = lgue_init;
247 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
248 ifq_set_ready(&ifp->if_snd);
250 /* Call attach routine */
251 ether_ifattach(ifp, eaddr, NULL);
252 usb_register_netisr();
264 lgue_detach(device_t dev)
266 struct lgue_softc *sc;
269 sc = device_get_softc(dev);
270 ifp = &sc->lgue_arpcom.ac_if;
273 if (sc->lgue_ep[LGUE_ENDPT_TX] != NULL)
274 usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
275 if (sc->lgue_ep[LGUE_ENDPT_RX] != NULL)
276 usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
277 if (sc->lgue_ep[LGUE_ENDPT_INTR] != NULL)
278 usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
283 * Find data interface.
286 lgue_get_data_iface_no(usbd_device_handle dev, usb_interface_descriptor_t *id)
288 const usb_cdc_union_descriptor_t *cud;
290 cud = (const usb_cdc_union_descriptor_t *)usb_find_desc_if(dev,
291 UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION, id);
292 return(cud ? cud->bSlaveInterface[0] : -1);
299 lgue_getmtu(struct lgue_softc *sc)
301 const usb_cdc_ethernet_descriptor_t *ced;
302 usb_interface_descriptor_t *id;
304 id = usbd_get_interface_descriptor(sc->lgue_ctl_iface);
305 if (id == NULL) goto bad;
306 ced = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc_if(sc->lgue_udev,
307 UDESC_CS_INTERFACE, UDESCSUB_CDC_ETHERNET, id);
310 return(UGETW(ced->wMaxSegmentSize));
312 kprintf("Bad mtu:%d\n", UGETW(ced->wMaxSegmentSize));
320 lgue_getmac(struct lgue_softc *sc, void *buf)
322 const usb_cdc_ethernet_descriptor_t *ced;
323 usb_interface_descriptor_t *id;
324 char sbuf[ETHER_ADDR_LEN * 2 + 1];
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;
334 err = usbd_get_string(sc->lgue_udev, ced->iMACAddress, sbuf);
336 kprintf("Read MAC address failed\n");
340 for (i = 0; i < ETHER_ADDR_LEN; ++i) {
341 ((uByte *)buf)[i] = (hex(sbuf[i * 2]) << 4) + hex(sbuf[(i * 2) + 1]);
352 lgue_intrstart(struct ifnet *ifp)
354 struct lgue_softc *sc;
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);
367 lgue_intreof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
370 struct lgue_softc *sc;
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);
382 if (status == USBD_STALLED)
383 usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_INTR]);
384 lwkt_serialize_exit(ifp->if_serializer);
388 lwkt_serialize_exit(ifp->if_serializer);
392 * Encap packet & send
395 lgue_encap(struct lgue_softc *sc, struct mbuf *m)
398 struct lgue_queue_entry *entry;
400 ifp = &sc->lgue_arpcom.ac_if;
401 entry = kmalloc(sizeof(struct lgue_queue_entry), M_USBDEV , M_NOWAIT);
403 if_printf(ifp, "no memory for internal queue entry\n");
406 entry->entry_mbuf = m;
408 /* Put packet into internal queue tail */
409 STAILQ_INSERT_TAIL(&sc->lgue_tx_queue, entry, entry_next);
414 * Start transfer from internal queue
417 lgue_start_transfer(struct lgue_softc *sc) {
419 struct lgue_queue_entry *entry;
422 if (STAILQ_EMPTY(&sc->lgue_tx_queue))
425 ifp = &sc->lgue_arpcom.ac_if;
426 entry = STAILQ_FIRST(&sc->lgue_tx_queue);
427 STAILQ_REMOVE_HEAD(&sc->lgue_tx_queue, entry_next);
429 m_copydata(entry->entry_mbuf, 0, entry->entry_mbuf->m_pkthdr.len,
433 usbd_setup_xfer(sc->lgue_tx_xfer, sc->lgue_ep[LGUE_ENDPT_TX], sc,
434 sc->lgue_tx_buf, entry->entry_mbuf->m_pkthdr.len,
435 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_txeof);
436 err = usbd_transfer(sc->lgue_tx_xfer);
437 if (err != USBD_IN_PROGRESS) {
438 m_freem(entry->entry_mbuf);
439 kfree(entry, M_USBDEV);
441 ifp->if_flags &= ~IFF_OACTIVE;
445 m_freem(entry->entry_mbuf);
446 kfree(entry, M_USBDEV);
449 ifp->if_flags |= IFF_OACTIVE;
458 lgue_start_ipifunc(void *arg)
461 struct lwkt_msg *lmsg;
464 lmsg = &ifp->if_start_nmsg[mycpuid].lmsg;
466 if (lmsg->ms_flags & MSGF_DONE)
467 lwkt_sendmsg(ifnet_portfn(mycpuid), lmsg);
472 * Schedule start call
475 lgue_start_schedule(struct ifnet *ifp)
480 cpu = ifp->if_start_cpuid(ifp);
482 lwkt_send_ipiq(globaldata_find(cpu), lgue_start_ipifunc, ifp);
485 lgue_start_ipifunc(ifp);
492 lgue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
495 struct lgue_softc *sc;
502 ifp = &sc->lgue_arpcom.ac_if;
504 if (status != USBD_NORMAL_COMPLETION) {
505 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
507 if (status == USBD_STALLED)
508 usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_TX]);
511 usbd_get_xfer_status(sc->lgue_tx_xfer, NULL, NULL, NULL,&err);
517 if (!STAILQ_EMPTY(&sc->lgue_tx_queue)) {
518 lgue_start_schedule(ifp);
522 ifp->if_flags &= ~IFF_OACTIVE;
529 lgue_start(struct ifnet *ifp)
531 struct lgue_softc *sc;
538 if (ifp->if_flags & IFF_OACTIVE) {
542 /* To internal queue */
543 while ((m_head = ifq_dequeue(&ifp->if_snd, NULL)) != NULL) {
544 if (lgue_encap(sc, m_head)) {
549 BPF_MTAP(ifp, m_head);
552 lgue_start_transfer(sc);
559 lgue_stop(struct lgue_softc *sc)
563 struct lgue_queue_entry *entry;
569 ifp = &sc->lgue_arpcom.ac_if;
572 if (sc->lgue_ep[LGUE_ENDPT_TX] != NULL) {
573 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
575 if_printf(ifp, "abort tx pipe failed:%s\n",
578 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
580 if_printf(ifp, "close tx pipe failed:%s\n",
584 if (sc->lgue_ep[LGUE_ENDPT_RX] != NULL) {
585 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
587 if_printf(ifp, "abort rx pipe failed:%s\n",
590 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
592 if_printf(ifp, "close rx pipe failed:%s\n",
596 if (sc->lgue_ep[LGUE_ENDPT_INTR] != NULL) {
597 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
599 if_printf(ifp, "abort intr pipe failed:%s\n",
602 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
604 if_printf(ifp, "close intr pipe failed:%s\n",
609 /* Free tx buffers */
610 if (sc->lgue_tx_buf != NULL) {
611 kfree(sc->lgue_tx_buf, M_USBDEV);
612 sc->lgue_tx_buf = NULL;
614 if (sc->lgue_tx_xfer != NULL) {
615 usbd_free_xfer(sc->lgue_tx_xfer);
616 sc->lgue_tx_xfer = NULL;
619 /* Free rx buffers */
620 if (sc->lgue_rx_buf != NULL) {
621 kfree(sc->lgue_rx_buf, M_USBDEV);
622 sc->lgue_rx_buf = NULL;
624 if (sc->lgue_rx_xfer != NULL) {
625 usbd_free_xfer(sc->lgue_rx_xfer);
626 sc->lgue_rx_xfer = NULL;
629 /* Free intr buffer */
630 if (sc->lgue_intr_buf != NULL) {
631 kfree(sc->lgue_intr_buf, M_USBDEV);
632 sc->lgue_intr_buf = NULL;
634 if (sc->lgue_intr_xfer != NULL) {
635 usbd_free_xfer(sc->lgue_intr_xfer);
636 sc->lgue_intr_xfer = NULL;
639 /* Clear internal queue */
640 while (!STAILQ_EMPTY(&sc->lgue_tx_queue)) {
641 entry = STAILQ_FIRST(&sc->lgue_tx_queue);
642 STAILQ_REMOVE_HEAD(&sc->lgue_tx_queue, entry_next);
643 m_freem(entry->entry_mbuf);
644 kfree(entry, M_USBDEV);
647 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
656 struct lgue_softc *sc;
661 ifp = &sc->lgue_arpcom.ac_if;
663 if (ifp->if_flags & IFF_RUNNING)
666 /* Create RX and TX bufs */
667 if (sc->lgue_tx_xfer == NULL) {
668 sc->lgue_tx_xfer = usbd_alloc_xfer(sc->lgue_udev);
669 if (sc->lgue_tx_xfer == NULL) {
670 if_printf(ifp, "tx buffer allocate failed\n");
674 sc->lgue_tx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
675 if (sc->lgue_tx_buf == NULL) {
676 if_printf(ifp, "tx internal buffer allocate failed\n");
680 if (sc->lgue_rx_xfer == NULL) {
681 sc->lgue_rx_xfer = usbd_alloc_xfer(sc->lgue_udev);
682 if (sc->lgue_rx_xfer == NULL) {
683 if_printf(ifp, "rx buffer allocate failed\n");
687 sc->lgue_rx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
688 if (sc->lgue_rx_buf == NULL) {
689 if_printf(ifp, "rx internal buffer allocate failed\n");
693 /* Create INTR buf */
694 if (sc->lgue_intr_xfer == NULL) {
695 sc->lgue_intr_xfer = usbd_alloc_xfer(sc->lgue_udev);
696 if (sc->lgue_intr_xfer == NULL) {
697 if_printf(ifp, "intr buffer allocate failed\n");
701 sc->lgue_intr_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
703 /* Open RX and TX pipes. */
704 err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_RX],
705 USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_RX]);
707 if_printf(ifp, "open RX pipe failed: %s\n", usbd_errstr(err));
710 err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_TX],
711 USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_TX]);
713 if_printf(ifp, "open TX pipe failed: %s\n", usbd_errstr(err));
716 /* Open INTR pipe. */
717 err = usbd_open_pipe(sc->lgue_ctl_iface, sc->lgue_ed[LGUE_ENDPT_INTR],
718 USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_INTR]);
720 if_printf(ifp, "open INTR pipe failed: %s\n", usbd_errstr(err));
724 /* Create internal queue */
725 STAILQ_INIT(&sc->lgue_tx_queue);
727 ifp->if_flags |= IFF_RUNNING;
728 ifp->if_flags &= ~IFF_OACTIVE;
740 lgue_newbuf(struct lgue_softc *sc, int len, struct mbuf **m_buf)
744 ifp = &sc->lgue_arpcom.ac_if;
748 *m_buf = m_getcl(MB_DONTWAIT, MT_DATA, MT_HEADER);
749 if (*m_buf == NULL) {
750 if_printf(ifp, " no memory for rx buffer --- packet dropped!\n");
753 (*m_buf)->m_len = (*m_buf)->m_pkthdr.len = MCLBYTES;
754 m_adj(*m_buf, ETHER_ALIGN);
762 lgue_rxstart(struct ifnet *ifp)
764 struct lgue_softc *sc;
770 usbd_setup_xfer(sc->lgue_rx_xfer, sc->lgue_ep[LGUE_ENDPT_RX], sc,
771 sc->lgue_rx_buf, LGUE_BUFSZ,
772 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_rxeof);
773 usbd_transfer(sc->lgue_rx_xfer);
777 * A frame has been uploaded: pass the resulting mbuf up to
778 * the higher level protocols.
781 lgue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
783 struct lgue_softc *sc;
792 ifp = &sc->lgue_arpcom.ac_if;
796 if (!(ifp->if_flags & IFF_RUNNING))
799 if (status != USBD_NORMAL_COMPLETION) {
800 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
802 if (usbd_ratecheck(&sc->lgue_rx_notice)) {
803 if_printf(ifp, "usb error on rx:%s\n",
804 usbd_errstr(status));
806 if (status == USBD_STALLED)
807 usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_RX]);
811 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
813 if (total_len < sizeof(struct ether_header)) {
818 if (lgue_newbuf(sc, total_len, &m) == ENOBUFS) {
824 m_copyback(m, 0, total_len, sc->lgue_rx_buf);
825 m->m_pkthdr.rcvif = ifp;
826 m->m_pkthdr.len = m->m_len = total_len;
832 usbd_setup_xfer(sc->lgue_rx_xfer, sc->lgue_ep[LGUE_ENDPT_RX], sc,
833 sc->lgue_rx_buf, LGUE_BUFSZ,
834 USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, lgue_rxeof);
835 usbd_transfer(sc->lgue_rx_xfer);
842 lgue_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
844 struct lgue_softc *sc;
849 ifr = (struct ifreq *)data;
854 if (ifp->if_flags & IFF_UP) {
855 if (!(ifp->if_flags & IFF_RUNNING))
857 } else if (ifp->if_flags & IFF_RUNNING) {
860 sc->lgue_if_flags = ifp->if_flags;
870 ifp->if_mtu = ifr->ifr_mtu;
873 err = ether_ioctl(ifp, command, data);
883 lgue_watchdog(struct ifnet *ifp)
885 struct lgue_softc *sc;
890 if (!ifq_is_empty(&ifp->if_snd))
891 lgue_start_schedule(ifp);
900 if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
901 if ((ch >= '0') && (ch <= '9')) return (ch-'0');
902 if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);