kernel: Use NULL for DRIVER_MODULE()'s evh & arg (which are pointers).
[dragonfly.git] / sys / dev / netif / lgue / if_lgue.c
CommitLineData
a700a71b
SW
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 */
42static struct usb_devno lgue_devs[] = {
43 { USB_DEVICE(0x01004, 0x61a2) } /* LG P500 */
44};
45
46static int lgue_match(device_t);
47static int lgue_attach(device_t);
48static int lgue_detach(device_t);
49
50static void lgue_start(struct ifnet *);
51static void lgue_stop(struct lgue_softc *);
52static void lgue_init(void *);
53static void lgue_watchdog(struct ifnet *);
54static int lgue_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
55
56static int lgue_encap(struct lgue_softc *, struct mbuf *);
57static int lgue_start_transfer(struct lgue_softc *);
58
59static void lgue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
60
61static void lgue_start_ipifunc(void *);
62static void lgue_start_schedule(struct ifnet *);
63
64static int lgue_newbuf(struct lgue_softc *, int, struct mbuf **);
65static void lgue_rxstart(struct ifnet *);
66static void lgue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
67
68static void lgue_intrstart(struct ifnet *);
69static void lgue_intreof(usbd_xfer_handle, usbd_private_handle, usbd_status);
70
71static int lgue_get_data_iface_no(usbd_device_handle,
72 usb_interface_descriptor_t *);
73
74static int lgue_getmac(struct lgue_softc *, void *);
75static int lgue_getmtu(struct lgue_softc *);
76
77static int hex(char);
78
79static device_method_t lgue_methods[] = {
80 DEVMETHOD(device_probe, lgue_match),
81 DEVMETHOD(device_attach, lgue_attach),
82 DEVMETHOD(device_detach, lgue_detach),
83
84 { 0, 0 }
85};
86
87static driver_t lgue_driver = {
88 "lgue",
89 lgue_methods,
90 sizeof(struct lgue_softc)
91};
92
93static devclass_t lgue_devclass;
94
95DECLARE_DUMMY_MODULE(if_lgue);
8515b7f9 96DRIVER_MODULE(lgue, uhub, lgue_driver, lgue_devclass, usbd_driver_load, NULL);
a700a71b
SW
97MODULE_DEPEND(lgue, usb, 1, 1, 1);
98
99/*
100 * Probe chip
101 */
102static int
103lgue_match(device_t dev)
104{
105 struct usb_attach_arg *uaa;
106 usb_interface_descriptor_t *id;
107
108 uaa = device_get_ivars(dev);
109 if (uaa->iface == NULL)
110 return(UMATCH_NONE);
111
112 if (usb_lookup(lgue_devs, uaa->vendor, uaa->product) != NULL) {
113 id = usbd_get_interface_descriptor(uaa->iface);
114 if (id != NULL &&
115 id->bInterfaceClass == UICLASS_CDC &&
116 id->bInterfaceSubClass == UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
117 return(UMATCH_VENDOR_PRODUCT);
118 }
119 return(UMATCH_NONE);
120}
121
122/*
123 * Attach the interface.
124 */
125static int
126lgue_attach(device_t dev)
127{
128 struct lgue_softc *sc;
129 struct usb_attach_arg *uaa;
130 struct ifnet *ifp;
131 usb_interface_descriptor_t *id;
132 usb_endpoint_descriptor_t *ed;
133 int i;
134 u_char eaddr[ETHER_ADDR_LEN];
135 usbd_status err;
136
137 sc = device_get_softc(dev);
138 uaa = device_get_ivars(dev);
139
140 sc->lgue_ctl_iface = uaa->iface;
141 sc->lgue_udev = uaa->device;
142
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",
146 LGUE_CONFIG_NO);
147 return(ENXIO);
148 }
149
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);
154
155 if (sc->lgue_data_iface_no == -1) {
156 device_printf(dev, "no data interface number\n");
157 goto bad;
158 }
159
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]);
164 if (id != NULL &&
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) {
169 device_printf(dev,
170 "no alternate data interface. err:%s\n",
171 usbd_errstr(err));
172 goto bad;
173 }
174 sc->lgue_data_iface = uaa->ifaces[i];
175 uaa->ifaces[i] = NULL;
176 }
177 }
178 }
179 if (sc->lgue_data_iface == NULL) {
180 device_printf(dev, "no data interface\n");
181 goto bad;
182 }
183
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);
189 if (!ed) {
190 device_printf(dev,
191 "couldn't get endpoint descriptor %d\n", i);
192 goto bad;
193 }
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;
200 }
201 }
202
203 if (sc->lgue_ed[LGUE_ENDPT_RX] == -1) {
204 device_printf(dev, "couldn't find data bilk in\n");
205 goto bad;
206 }
207 if (sc->lgue_ed[LGUE_ENDPT_TX] == -1) {
208 device_printf(dev, "couldn't find data bilk out\n");
209 goto bad;
210 }
211
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);
217 if (!ed) {
218 device_printf(dev,
219 "couldn't get endpoint descriptor %d\n", i);
220 goto bad;
221 }
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;
225 }
226 }
227
228 if (sc->lgue_ed[LGUE_ENDPT_INTR] == -1) {
229 device_printf(dev, "couldn't find interrupt bilk in\n");
230 goto bad;
231 }
232
233 /* Create interface */
234 ifp = &sc->lgue_arpcom.ac_if;
235 ifp->if_softc = sc;
236 if_initname(ifp, device_get_name(dev), device_get_unit(dev));
237 lgue_getmac(sc, eaddr);
238
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);
249
250 /* Call attach routine */
251 ether_ifattach(ifp, eaddr, NULL);
252 usb_register_netisr();
253 sc->lgue_dying = 0;
254 return(0);
255
256bad:
257 return(ENXIO);
258}
259
260/*
261 * Device detached.
262 */
263static int
264lgue_detach(device_t dev)
265{
266 struct lgue_softc *sc;
267 struct ifnet *ifp;
268
269 sc = device_get_softc(dev);
270 ifp = &sc->lgue_arpcom.ac_if;
271 ether_ifdetach(ifp);
272
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]);
279 return(0);
280}
281
282/*
283 * Find data interface.
284 */
285int
286lgue_get_data_iface_no(usbd_device_handle dev, usb_interface_descriptor_t *id)
287{
288 const usb_cdc_union_descriptor_t *cud;
289
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);
293}
294
295/*
296 * Get hard max mtu
297 */
298static int
299lgue_getmtu(struct lgue_softc *sc)
300{
301 const usb_cdc_ethernet_descriptor_t *ced;
302 usb_interface_descriptor_t *id;
303
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);
308 if (ced == NULL)
309 goto bad;
310 return(UGETW(ced->wMaxSegmentSize));
311bad:
312 kprintf("Bad mtu:%d\n", UGETW(ced->wMaxSegmentSize));
313 return(ETHERMTU);
314}
315
316/*
317 * Get mac address
318 */
319static int
320lgue_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);
344bad:
345 return(-1);
346}
347
348/*
349 * Listen INTR pipe
350 */
351static void
352lgue_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 */
366static void
367lgue_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 if (status == USBD_STALLED)
383 usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_INTR]);
384 lwkt_serialize_exit(ifp->if_serializer);
385 return;
386 }
387 lgue_intrstart(ifp);
388 lwkt_serialize_exit(ifp->if_serializer);
389}
390
391/*
392 * Encap packet & send
393 */
394static int
395lgue_encap(struct lgue_softc *sc, struct mbuf *m)
396{
397 struct ifnet *ifp;
398 struct lgue_queue_entry *entry;
399
400 ifp = &sc->lgue_arpcom.ac_if;
401 entry = kmalloc(sizeof(struct lgue_queue_entry), M_USBDEV , M_NOWAIT);
402 if (entry == NULL) {
403 if_printf(ifp, "no memory for internal queue entry\n");
404 return(ENOBUFS);
405 }
406 entry->entry_mbuf = m;
407
408 /* Put packet into internal queue tail */
409 STAILQ_INSERT_TAIL(&sc->lgue_tx_queue, entry, entry_next);
410 return(0);
411}
412
413/*
414 * Start transfer from internal queue
415 */
416static int
417lgue_start_transfer(struct lgue_softc *sc) {
418 usbd_status err;
419 struct lgue_queue_entry *entry;
420 struct ifnet *ifp;
421
422 if (STAILQ_EMPTY(&sc->lgue_tx_queue))
423 return(0);
424
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);
428
429 m_copydata(entry->entry_mbuf, 0, entry->entry_mbuf->m_pkthdr.len,
430 sc->lgue_tx_buf);
431
432 /* Transmit */
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);
440 lgue_stop(sc);
441 ifp->if_flags &= ~IFF_OACTIVE;
442 return(EIO);
443 }
444
445 m_freem(entry->entry_mbuf);
446 kfree(entry, M_USBDEV);
447
448 sc->lgue_tx_cnt++;
449 ifp->if_flags |= IFF_OACTIVE;
450 ifp->if_timer = 5;
451 return(0);
452}
453
454/*
455 * Start call
456 */
457static void
458lgue_start_ipifunc(void *arg)
459{
460 struct ifnet *ifp;
461 struct lwkt_msg *lmsg;
462
463 ifp = arg;
464 lmsg = &ifp->if_start_nmsg[mycpuid].lmsg;
465 crit_enter();
466 if (lmsg->ms_flags & MSGF_DONE)
467 lwkt_sendmsg(ifnet_portfn(mycpuid), lmsg);
468 crit_exit();
469}
470
471/*
472 * Schedule start call
473 */
474static void
475lgue_start_schedule(struct ifnet *ifp)
476{
477#ifdef SMP
478 int cpu;
479
480 cpu = ifp->if_start_cpuid(ifp);
481 if (cpu != mycpuid)
482 lwkt_send_ipiq(globaldata_find(cpu), lgue_start_ipifunc, ifp);
483 else
484#endif
485 lgue_start_ipifunc(ifp);
486}
487
488/*
489 * End of sending
490 */
491static void
492lgue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
493{
494 struct ifnet *ifp;
495 struct lgue_softc *sc;
496 usbd_status err;
497
498 sc = priv;
499 if (sc->lgue_dying)
500 return;
501
502 ifp = &sc->lgue_arpcom.ac_if;
503
504 if (status != USBD_NORMAL_COMPLETION) {
505 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
506 return;
507 if (status == USBD_STALLED)
508 usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_TX]);
509 return;
510 }
511 usbd_get_xfer_status(sc->lgue_tx_xfer, NULL, NULL, NULL,&err);
512 if (err)
513 ifp->if_oerrors++;
514 else
515 ifp->if_opackets++;
516
517 if (!STAILQ_EMPTY(&sc->lgue_tx_queue)) {
518 lgue_start_schedule(ifp);
519 }
520
521 ifp->if_timer = 0;
522 ifp->if_flags &= ~IFF_OACTIVE;
523}
524
525/*
526 * Start transfer
527 */
528static void
529lgue_start(struct ifnet *ifp)
530{
531 struct lgue_softc *sc;
532 struct mbuf *m_head;
533
534 sc = ifp->if_softc;
535 if (sc->lgue_dying)
536 return;
537
538 if (ifp->if_flags & IFF_OACTIVE) {
539 return;
540 }
541
542 /* To internal queue */
543 while ((m_head = ifq_dequeue(&ifp->if_snd, NULL)) != NULL) {
544 if (lgue_encap(sc, m_head)) {
545 m_freem(m_head);
546 break;
547 }
548 /* Filter */
549 BPF_MTAP(ifp, m_head);
550 }
551
552 lgue_start_transfer(sc);
553}
554
555/*
556 * Stop
557 */
558static void
559lgue_stop(struct lgue_softc *sc)
560{
561 struct ifnet *ifp;
562 usbd_status err;
563 struct lgue_queue_entry *entry;
564
565 if (sc->lgue_dying)
566 return;
567 sc->lgue_dying = 1;
568
569 ifp = &sc->lgue_arpcom.ac_if;
570
571 /* Stop transfers */
572 if (sc->lgue_ep[LGUE_ENDPT_TX] != NULL) {
573 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
574 if (err) {
575 if_printf(ifp, "abort tx pipe failed:%s\n",
576 usbd_errstr(err));
577 }
578 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_TX]);
579 if (err) {
580 if_printf(ifp, "close tx pipe failed:%s\n",
581 usbd_errstr(err));
582 }
583 }
584 if (sc->lgue_ep[LGUE_ENDPT_RX] != NULL) {
585 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
586 if (err) {
587 if_printf(ifp, "abort rx pipe failed:%s\n",
588 usbd_errstr(err));
589 }
590 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_RX]);
591 if (err) {
592 if_printf(ifp, "close rx pipe failed:%s\n",
593 usbd_errstr(err));
594 }
595 }
596 if (sc->lgue_ep[LGUE_ENDPT_INTR] != NULL) {
597 err = usbd_abort_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
598 if (err) {
599 if_printf(ifp, "abort intr pipe failed:%s\n",
600 usbd_errstr(err));
601 }
602 err = usbd_close_pipe(sc->lgue_ep[LGUE_ENDPT_INTR]);
603 if (err) {
604 if_printf(ifp, "close intr pipe failed:%s\n",
605 usbd_errstr(err));
606 }
607 }
608
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;
613 }
614 if (sc->lgue_tx_xfer != NULL) {
615 usbd_free_xfer(sc->lgue_tx_xfer);
616 sc->lgue_tx_xfer = NULL;
617 }
618
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;
623 }
624 if (sc->lgue_rx_xfer != NULL) {
625 usbd_free_xfer(sc->lgue_rx_xfer);
626 sc->lgue_rx_xfer = NULL;
627 }
628
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;
633 }
634 if (sc->lgue_intr_xfer != NULL) {
635 usbd_free_xfer(sc->lgue_intr_xfer);
636 sc->lgue_intr_xfer = NULL;
637 }
638
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);
645 }
646
647 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
648}
649
650/*
651 * Init
652 */
653static void
654lgue_init(void *xsc)
655{
656 struct lgue_softc *sc;
657 struct ifnet *ifp;
658 usbd_status err;
659
660 sc = xsc;
661 ifp = &sc->lgue_arpcom.ac_if;
662
663 if (ifp->if_flags & IFF_RUNNING)
664 return;
665
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");
671 return;
672 }
673 }
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");
677 return;
678 }
679
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");
684 return;
685 }
686 }
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");
690 return;
691 }
692
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");
698 return;
699 }
700 }
701 sc->lgue_intr_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);
702
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]);
706 if (err) {
707 if_printf(ifp, "open RX pipe failed: %s\n", usbd_errstr(err));
708 return;
709 }
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]);
712 if (err) {
713 if_printf(ifp, "open TX pipe failed: %s\n", usbd_errstr(err));
714 return;
715 }
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]);
719 if (err) {
720 if_printf(ifp, "open INTR pipe failed: %s\n", usbd_errstr(err));
721 return;
722 }
723
724 /* Create internal queue */
725 STAILQ_INIT(&sc->lgue_tx_queue);
726
727 ifp->if_flags |= IFF_RUNNING;
728 ifp->if_flags &= ~IFF_OACTIVE;
729
730 sc->lgue_dying = 0;
731
732 lgue_rxstart(ifp);
733 lgue_intrstart(ifp);
734}
735
736/*
737 * New mbuf
738 */
739static int
740lgue_newbuf(struct lgue_softc *sc, int len, struct mbuf **m_buf)
741{
742 struct ifnet *ifp;
743
744 ifp = &sc->lgue_arpcom.ac_if;
745 *m_buf = NULL;
746
747 /* Allocate mbuf */
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");
751 return(ENOBUFS);
752 }
753 (*m_buf)->m_len = (*m_buf)->m_pkthdr.len = MCLBYTES;
754 m_adj(*m_buf, ETHER_ALIGN);
755 return(0);
756}
757
758/*
759 * Start read
760 */
761static void
762lgue_rxstart(struct ifnet *ifp)
763{
764 struct lgue_softc *sc;
765
766 sc = ifp->if_softc;
767 if (sc->lgue_dying)
768 return;
769
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);
774}
775
776/*
777 * A frame has been uploaded: pass the resulting mbuf up to
778 * the higher level protocols.
779 */
780static void
781lgue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
782{
783 struct lgue_softc *sc;
784 struct mbuf *m;
785 struct ifnet *ifp;
786 int total_len;
787
788 sc = priv;
789 if (sc->lgue_dying)
790 return;
791
792 ifp = &sc->lgue_arpcom.ac_if;
793
794 total_len = 0;
795
796 if (!(ifp->if_flags & IFF_RUNNING))
797 return;
798
799 if (status != USBD_NORMAL_COMPLETION) {
800 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
801 return;
802 if (usbd_ratecheck(&sc->lgue_rx_notice)) {
803 if_printf(ifp, "usb error on rx:%s\n",
804 usbd_errstr(status));
805 }
806 if (status == USBD_STALLED)
807 usbd_clear_endpoint_stall(sc->lgue_ep[LGUE_ENDPT_RX]);
808 goto done;
809 }
810
811 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
812
813 if (total_len < sizeof(struct ether_header)) {
814 ifp->if_ierrors++;
815 goto done;
816 }
817
818 if (lgue_newbuf(sc, total_len, &m) == ENOBUFS) {
819 ifp->if_ierrors++;
820 return;
821 }
822
823 ifp->if_ipackets++;
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;
827
828 usb_ether_input(m);
829 lgue_rxstart(ifp);
830 return;
831done:
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);
836}
837
838/*
839 * Control
840 */
841static int
842lgue_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
843{
844 struct lgue_softc *sc;
845 struct ifreq *ifr;
846 int err;
847
848 err = 0;
849 ifr = (struct ifreq *)data;
850 sc = ifp->if_softc;
851
852 switch(command) {
853 case SIOCSIFFLAGS:
854 if (ifp->if_flags & IFF_UP) {
855 if (!(ifp->if_flags & IFF_RUNNING))
856 lgue_init(sc);
857 } else if (ifp->if_flags & IFF_RUNNING) {
858 lgue_stop(sc);
859 }
860 sc->lgue_if_flags = ifp->if_flags;
861 err = 0;
862 break;
863#if 0
864 case SIOCADDMULTI:
865 case SIOCDELMULTI:
866 err = 0;
867 break;
868#endif
869 case SIOCSIFMTU:
870 ifp->if_mtu = ifr->ifr_mtu;
871 break;
872 default:
873 err = ether_ioctl(ifp, command, data);
874 break;
875 }
876 return(err);
877}
878
879/*
880 * Watchdog
881 */
882static void
883lgue_watchdog(struct ifnet *ifp)
884{
885 struct lgue_softc *sc;
886
887 sc = ifp->if_softc;
888 ifp->if_oerrors++;
889
890 if (!ifq_is_empty(&ifp->if_snd))
891 lgue_start_schedule(ifp);
892}
893
894/*
895 * Hex -> bin
896 */
897static int
898hex(char ch)
899{
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);
903 return (-1);
904}