1 /* $NetBSD: if_upl.c,v 1.34 2009/09/23 19:07:19 plunky Exp $ */
3 * Copyright (c) 2000 The NetBSD Foundation, Inc.
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Lennart Augustsson (lennart@augustsson.net) at
8 * Carlstedt Research & Technology.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Prolific PL2301/PL2302 driver
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1.34 2009/09/23 19:07:19 plunky Exp $");
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/callout.h>
46 #include <sys/sockio.h>
48 #include <sys/malloc.h>
49 #include <sys/kernel.h>
50 #include <sys/socket.h>
52 #include <sys/device.h>
58 #include <net/if_types.h>
59 #include <net/if_dl.h>
60 #include <net/netisr.h>
62 #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
69 #include <netinet/in.h>
70 #include <netinet/in_var.h>
71 #include <netinet/if_inarp.h>
75 #include <dev/usb/usb.h>
76 #include <dev/usb/usbdi.h>
77 #include <dev/usb/usbdi_util.h>
78 #include <dev/usb/usbdevs.h>
89 #define UPL_RXDATA 0x40
92 #define UPL_INTR_PKTLEN 1
94 #define UPL_CONFIG_NO 1
95 #define UPL_IFACE_IDX 0
99 #define UPL_INTR_INTERVAL 20
101 #define UPL_BUFSZ 1024
103 #define UPL_RX_FRAMES 1
104 #define UPL_TX_FRAMES 1
106 #define UPL_RX_LIST_CNT 1
107 #define UPL_TX_LIST_CNT 1
109 #define UPL_ENDPT_RX 0x0
110 #define UPL_ENDPT_TX 0x1
111 #define UPL_ENDPT_INTR 0x2
112 #define UPL_ENDPT_MAX 0x3
122 struct upl_softc
*upl_sc
;
123 usbd_xfer_handle upl_xfer
;
125 struct mbuf
*upl_mbuf
;
130 struct upl_chain upl_tx_chain
[UPL_TX_LIST_CNT
];
131 struct upl_chain upl_rx_chain
[UPL_RX_LIST_CNT
];
139 USBBASEDEVICE sc_dev
;
143 rndsource_element_t sc_rnd_source
;
146 usb_callout_t sc_stat_ch
;
148 usbd_device_handle sc_udev
;
149 usbd_interface_handle sc_iface
;
151 u_int16_t sc_product
;
152 int sc_ed
[UPL_ENDPT_MAX
];
153 usbd_pipe_handle sc_ep
[UPL_ENDPT_MAX
];
154 struct upl_cdata sc_cdata
;
161 struct timeval sc_rx_notice
;
166 #define DPRINTF(x) if (upldebug) logprintf x
167 #define DPRINTFN(n,x) if (upldebug >= (n)) logprintf x
171 #define DPRINTFN(n,x)
175 * Various supported device vendors/products.
177 Static
struct upl_type sc_devs
[] = {
178 { USB_VENDOR_PROLIFIC
, USB_PRODUCT_PROLIFIC_PL2301
},
179 { USB_VENDOR_PROLIFIC
, USB_PRODUCT_PROLIFIC_PL2302
},
183 USB_DECLARE_DRIVER(upl
);
185 Static
int upl_openpipes(struct upl_softc
*);
186 Static
int upl_tx_list_init(struct upl_softc
*);
187 Static
int upl_rx_list_init(struct upl_softc
*);
188 Static
int upl_newbuf(struct upl_softc
*, struct upl_chain
*, struct mbuf
*);
189 Static
int upl_send(struct upl_softc
*, struct mbuf
*, int);
190 Static
void upl_intr(usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
191 Static
void upl_rxeof(usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
192 Static
void upl_txeof(usbd_xfer_handle
, usbd_private_handle
, usbd_status
);
193 Static
void upl_start(struct ifnet
*);
194 Static
int upl_ioctl(struct ifnet
*, u_long
, void *);
195 Static
void upl_init(void *);
196 Static
void upl_stop(struct upl_softc
*);
197 Static
void upl_watchdog(struct ifnet
*);
199 Static
int upl_output(struct ifnet
*, struct mbuf
*, const struct sockaddr
*,
201 Static
void upl_input(struct ifnet
*, struct mbuf
*);
204 * Probe for a Prolific chip.
208 USB_MATCH_START(upl
, uaa
);
211 for (t
= sc_devs
; t
->upl_vid
!= 0; t
++)
212 if (uaa
->vendor
== t
->upl_vid
&& uaa
->product
== t
->upl_did
)
213 return (UMATCH_VENDOR_PRODUCT
);
215 return (UMATCH_NONE
);
220 USB_ATTACH_START(upl
, sc
, uaa
);
223 usbd_device_handle dev
= uaa
->device
;
224 usbd_interface_handle iface
;
227 usb_interface_descriptor_t
*id
;
228 usb_endpoint_descriptor_t
*ed
;
231 DPRINTFN(5,(" : upl_attach: sc=%p, dev=%p", sc
, dev
));
238 devinfop
= usbd_devinfo_alloc(dev
, 0);
239 aprint_normal_dev(self
, "%s\n", devinfop
);
240 usbd_devinfo_free(devinfop
);
242 err
= usbd_set_config_no(dev
, UPL_CONFIG_NO
, 1);
244 aprint_error_dev(self
, "setting config no failed\n");
245 USB_ATTACH_ERROR_RETURN
;
249 sc
->sc_product
= uaa
->product
;
250 sc
->sc_vendor
= uaa
->vendor
;
252 err
= usbd_device2interface_handle(dev
, UPL_IFACE_IDX
, &iface
);
254 aprint_error_dev(self
, "getting interface handle failed\n");
255 USB_ATTACH_ERROR_RETURN
;
258 sc
->sc_iface
= iface
;
259 id
= usbd_get_interface_descriptor(iface
);
261 /* Find endpoints. */
262 for (i
= 0; i
< id
->bNumEndpoints
; i
++) {
263 ed
= usbd_interface2endpoint_descriptor(iface
, i
);
265 aprint_error_dev(self
, "couldn't get ep %d\n", i
);
266 USB_ATTACH_ERROR_RETURN
;
268 if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
269 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
270 sc
->sc_ed
[UPL_ENDPT_RX
] = ed
->bEndpointAddress
;
271 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_OUT
&&
272 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_BULK
) {
273 sc
->sc_ed
[UPL_ENDPT_TX
] = ed
->bEndpointAddress
;
274 } else if (UE_GET_DIR(ed
->bEndpointAddress
) == UE_DIR_IN
&&
275 UE_GET_XFERTYPE(ed
->bmAttributes
) == UE_INTERRUPT
) {
276 sc
->sc_ed
[UPL_ENDPT_INTR
] = ed
->bEndpointAddress
;
280 if (sc
->sc_ed
[UPL_ENDPT_RX
] == 0 || sc
->sc_ed
[UPL_ENDPT_TX
] == 0 ||
281 sc
->sc_ed
[UPL_ENDPT_INTR
] == 0) {
282 aprint_error_dev(self
, "missing endpoint\n");
283 USB_ATTACH_ERROR_RETURN
;
288 /* Initialize interface info.*/
291 ifp
->if_mtu
= UPL_BUFSZ
;
292 ifp
->if_flags
= IFF_POINTOPOINT
| IFF_NOARP
| IFF_SIMPLEX
;
293 ifp
->if_ioctl
= upl_ioctl
;
294 ifp
->if_start
= upl_start
;
295 ifp
->if_watchdog
= upl_watchdog
;
296 strncpy(ifp
->if_xname
, USBDEVNAME(sc
->sc_dev
), IFNAMSIZ
);
298 ifp
->if_type
= IFT_OTHER
;
301 ifp
->if_output
= upl_output
;
302 ifp
->if_input
= upl_input
;
303 ifp
->if_baudrate
= 12000000;
304 ifp
->if_dlt
= DLT_RAW
;
305 IFQ_SET_READY(&ifp
->if_snd
);
307 /* Attach the interface. */
312 bpfattach(ifp
, DLT_RAW
, 0);
315 rnd_attach_source(&sc
->sc_rnd_source
, USBDEVNAME(sc
->sc_dev
),
322 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH
, sc
->sc_udev
,
325 USB_ATTACH_SUCCESS_RETURN
;
330 USB_DETACH_START(upl
, sc
);
331 struct ifnet
*ifp
= &sc
->sc_if
;
334 DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc
->sc_dev
), __func__
));
338 if (!sc
->sc_attached
) {
339 /* Detached before attached finished, so just bail out. */
344 if (ifp
->if_flags
& IFF_RUNNING
)
348 rnd_detach_source(&sc
->sc_rnd_source
);
357 if (sc
->sc_ep
[UPL_ENDPT_TX
] != NULL
||
358 sc
->sc_ep
[UPL_ENDPT_RX
] != NULL
||
359 sc
->sc_ep
[UPL_ENDPT_INTR
] != NULL
)
360 aprint_debug_dev(self
, "detach has active endpoints\n");
366 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH
, sc
->sc_udev
,
373 upl_activate(device_ptr_t self
, enum devact act
)
375 struct upl_softc
*sc
= device_private(self
);
377 DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc
->sc_dev
), __func__
));
380 case DVACT_DEACTIVATE
:
381 /* Deactivate the interface. */
382 if_deactivate(&sc
->sc_if
);
391 * Initialize an RX descriptor and attach an MBUF cluster.
394 upl_newbuf(struct upl_softc
*sc
, struct upl_chain
*c
, struct mbuf
*m
)
396 struct mbuf
*m_new
= NULL
;
398 DPRINTFN(8,("%s: %s: enter\n", USBDEVNAME(sc
->sc_dev
), __func__
));
401 MGETHDR(m_new
, M_DONTWAIT
, MT_DATA
);
403 printf("%s: no memory for rx list "
404 "-- packet dropped!\n", USBDEVNAME(sc
->sc_dev
));
408 MCLGET(m_new
, M_DONTWAIT
);
409 if (!(m_new
->m_flags
& M_EXT
)) {
410 printf("%s: no memory for rx list "
411 "-- packet dropped!\n", USBDEVNAME(sc
->sc_dev
));
415 m_new
->m_len
= m_new
->m_pkthdr
.len
= MCLBYTES
;
418 m_new
->m_len
= m_new
->m_pkthdr
.len
= MCLBYTES
;
419 m_new
->m_data
= m_new
->m_ext
.ext_buf
;
428 upl_rx_list_init(struct upl_softc
*sc
)
430 struct upl_cdata
*cd
;
434 DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc
->sc_dev
), __func__
));
437 for (i
= 0; i
< UPL_RX_LIST_CNT
; i
++) {
438 c
= &cd
->upl_rx_chain
[i
];
441 if (upl_newbuf(sc
, c
, NULL
) == ENOBUFS
)
443 if (c
->upl_xfer
== NULL
) {
444 c
->upl_xfer
= usbd_alloc_xfer(sc
->sc_udev
);
445 if (c
->upl_xfer
== NULL
)
447 c
->upl_buf
= usbd_alloc_buffer(c
->upl_xfer
, UPL_BUFSZ
);
448 if (c
->upl_buf
== NULL
) {
449 usbd_free_xfer(c
->upl_xfer
);
459 upl_tx_list_init(struct upl_softc
*sc
)
461 struct upl_cdata
*cd
;
465 DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc
->sc_dev
), __func__
));
468 for (i
= 0; i
< UPL_TX_LIST_CNT
; i
++) {
469 c
= &cd
->upl_tx_chain
[i
];
473 if (c
->upl_xfer
== NULL
) {
474 c
->upl_xfer
= usbd_alloc_xfer(sc
->sc_udev
);
475 if (c
->upl_xfer
== NULL
)
477 c
->upl_buf
= usbd_alloc_buffer(c
->upl_xfer
, UPL_BUFSZ
);
478 if (c
->upl_buf
== NULL
) {
479 usbd_free_xfer(c
->upl_xfer
);
489 * A frame has been uploaded: pass the resulting mbuf chain up to
490 * the higher level protocols.
493 upl_rxeof(usbd_xfer_handle xfer
, usbd_private_handle priv
, usbd_status status
)
495 struct upl_chain
*c
= priv
;
496 struct upl_softc
*sc
= c
->upl_sc
;
497 struct ifnet
*ifp
= &sc
->sc_if
;
505 if (!(ifp
->if_flags
& IFF_RUNNING
))
508 if (status
!= USBD_NORMAL_COMPLETION
) {
509 if (status
== USBD_NOT_STARTED
|| status
== USBD_CANCELLED
)
512 if (usbd_ratecheck(&sc
->sc_rx_notice
)) {
513 printf("%s: %u usb errors on rx: %s\n",
514 USBDEVNAME(sc
->sc_dev
), sc
->sc_rx_errs
,
515 usbd_errstr(status
));
518 if (status
== USBD_STALLED
)
519 usbd_clear_endpoint_stall_async(sc
->sc_ep
[UPL_ENDPT_RX
]);
523 usbd_get_xfer_status(xfer
, NULL
, NULL
, &total_len
, NULL
);
525 DPRINTFN(9,("%s: %s: enter status=%d length=%d\n",
526 USBDEVNAME(sc
->sc_dev
), __func__
, status
, total_len
));
529 memcpy(mtod(c
->upl_mbuf
, char *), c
->upl_buf
, total_len
);
532 m
->m_pkthdr
.len
= m
->m_len
= total_len
;
534 m
->m_pkthdr
.rcvif
= ifp
;
539 if (upl_newbuf(sc
, c
, NULL
) == ENOBUFS
) {
546 * Handle BPF listeners. Let the BPF user see the packet, but
547 * don't pass it up to the ether_input() layer unless it's
548 * a broadcast packet, multicast packet, matches our ethernet
549 * address or the interface is in promiscuous mode.
556 DPRINTFN(10,("%s: %s: deliver %d\n", USBDEVNAME(sc
->sc_dev
),
557 __func__
, m
->m_len
));
566 /* Setup new transfer. */
567 usbd_setup_xfer(c
->upl_xfer
, sc
->sc_ep
[UPL_ENDPT_RX
],
568 c
, c
->upl_buf
, UPL_BUFSZ
, USBD_SHORT_XFER_OK
| USBD_NO_COPY
,
569 USBD_NO_TIMEOUT
, upl_rxeof
);
570 usbd_transfer(c
->upl_xfer
);
572 DPRINTFN(10,("%s: %s: start rx\n", USBDEVNAME(sc
->sc_dev
),
578 * A frame was downloaded to the chip. It's safe for us to clean up
582 upl_txeof(usbd_xfer_handle xfer
, usbd_private_handle priv
,
585 struct upl_chain
*c
= priv
;
586 struct upl_softc
*sc
= c
->upl_sc
;
587 struct ifnet
*ifp
= &sc
->sc_if
;
595 DPRINTFN(10,("%s: %s: enter status=%d\n", USBDEVNAME(sc
->sc_dev
),
599 ifp
->if_flags
&= ~IFF_OACTIVE
;
601 if (status
!= USBD_NORMAL_COMPLETION
) {
602 if (status
== USBD_NOT_STARTED
|| status
== USBD_CANCELLED
) {
607 printf("%s: usb error on tx: %s\n", USBDEVNAME(sc
->sc_dev
),
608 usbd_errstr(status
));
609 if (status
== USBD_STALLED
)
610 usbd_clear_endpoint_stall_async(sc
->sc_ep
[UPL_ENDPT_TX
]);
617 m_freem(c
->upl_mbuf
);
620 if (IFQ_IS_EMPTY(&ifp
->if_snd
) == 0)
627 upl_send(struct upl_softc
*sc
, struct mbuf
*m
, int idx
)
633 c
= &sc
->sc_cdata
.upl_tx_chain
[idx
];
636 * Copy the mbuf data into a contiguous buffer, leaving two
637 * bytes at the beginning to hold the frame length.
639 m_copydata(m
, 0, m
->m_pkthdr
.len
, c
->upl_buf
);
642 total_len
= m
->m_pkthdr
.len
;
644 DPRINTFN(10,("%s: %s: total_len=%d\n",
645 USBDEVNAME(sc
->sc_dev
), __func__
, total_len
));
647 usbd_setup_xfer(c
->upl_xfer
, sc
->sc_ep
[UPL_ENDPT_TX
],
648 c
, c
->upl_buf
, total_len
, USBD_NO_COPY
, USBD_DEFAULT_TIMEOUT
,
652 err
= usbd_transfer(c
->upl_xfer
);
653 if (err
!= USBD_IN_PROGRESS
) {
654 printf("%s: upl_send error=%s\n", USBDEVNAME(sc
->sc_dev
),
660 sc
->sc_cdata
.upl_tx_cnt
++;
666 upl_start(struct ifnet
*ifp
)
668 struct upl_softc
*sc
= ifp
->if_softc
;
669 struct mbuf
*m_head
= NULL
;
674 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc
->sc_dev
),__func__
));
676 if (ifp
->if_flags
& IFF_OACTIVE
)
679 IFQ_POLL(&ifp
->if_snd
, m_head
);
683 if (upl_send(sc
, m_head
, 0)) {
684 ifp
->if_flags
|= IFF_OACTIVE
;
688 IFQ_DEQUEUE(&ifp
->if_snd
, m_head
);
692 * If there's a BPF listener, bounce a copy of this frame
696 BPF_MTAP(ifp
, m_head
);
699 ifp
->if_flags
|= IFF_OACTIVE
;
702 * Set a timeout in case the chip goes out to lunch.
710 struct upl_softc
*sc
= xsc
;
711 struct ifnet
*ifp
= &sc
->sc_if
;
717 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc
->sc_dev
),__func__
));
719 if (ifp
->if_flags
& IFF_RUNNING
)
725 if (upl_tx_list_init(sc
) == ENOBUFS
) {
726 printf("%s: tx list init failed\n", USBDEVNAME(sc
->sc_dev
));
732 if (upl_rx_list_init(sc
) == ENOBUFS
) {
733 printf("%s: rx list init failed\n", USBDEVNAME(sc
->sc_dev
));
738 if (sc
->sc_ep
[UPL_ENDPT_RX
] == NULL
) {
739 if (upl_openpipes(sc
)) {
745 ifp
->if_flags
|= IFF_RUNNING
;
746 ifp
->if_flags
&= ~IFF_OACTIVE
;
752 upl_openpipes(struct upl_softc
*sc
)
758 /* Open RX and TX pipes. */
759 err
= usbd_open_pipe(sc
->sc_iface
, sc
->sc_ed
[UPL_ENDPT_RX
],
760 USBD_EXCLUSIVE_USE
, &sc
->sc_ep
[UPL_ENDPT_RX
]);
762 printf("%s: open rx pipe failed: %s\n",
763 USBDEVNAME(sc
->sc_dev
), usbd_errstr(err
));
766 err
= usbd_open_pipe(sc
->sc_iface
, sc
->sc_ed
[UPL_ENDPT_TX
],
767 USBD_EXCLUSIVE_USE
, &sc
->sc_ep
[UPL_ENDPT_TX
]);
769 printf("%s: open tx pipe failed: %s\n",
770 USBDEVNAME(sc
->sc_dev
), usbd_errstr(err
));
773 err
= usbd_open_pipe_intr(sc
->sc_iface
, sc
->sc_ed
[UPL_ENDPT_INTR
],
774 USBD_EXCLUSIVE_USE
, &sc
->sc_ep
[UPL_ENDPT_INTR
], sc
,
775 &sc
->sc_ibuf
, UPL_INTR_PKTLEN
, upl_intr
,
778 printf("%s: open intr pipe failed: %s\n",
779 USBDEVNAME(sc
->sc_dev
), usbd_errstr(err
));
785 /* Start up the receive pipe. */
786 for (i
= 0; i
< UPL_RX_LIST_CNT
; i
++) {
787 c
= &sc
->sc_cdata
.upl_rx_chain
[i
];
788 usbd_setup_xfer(c
->upl_xfer
, sc
->sc_ep
[UPL_ENDPT_RX
],
789 c
, c
->upl_buf
, UPL_BUFSZ
,
790 USBD_SHORT_XFER_OK
| USBD_NO_COPY
, USBD_NO_TIMEOUT
,
792 usbd_transfer(c
->upl_xfer
);
800 upl_intr(usbd_xfer_handle xfer
, usbd_private_handle priv
,
803 struct upl_softc
*sc
= priv
;
804 struct ifnet
*ifp
= &sc
->sc_if
;
807 DPRINTFN(15,("%s: %s: enter\n", USBDEVNAME(sc
->sc_dev
),__func__
));
812 if (!(ifp
->if_flags
& IFF_RUNNING
))
815 if (status
!= USBD_NORMAL_COMPLETION
) {
816 if (status
== USBD_NOT_STARTED
|| status
== USBD_CANCELLED
) {
820 if (usbd_ratecheck(&sc
->sc_rx_notice
)) {
821 printf("%s: %u usb errors on intr: %s\n",
822 USBDEVNAME(sc
->sc_dev
), sc
->sc_rx_errs
,
823 usbd_errstr(status
));
824 sc
->sc_intr_errs
= 0;
826 if (status
== USBD_STALLED
)
827 usbd_clear_endpoint_stall_async(sc
->sc_ep
[UPL_ENDPT_RX
]);
836 DPRINTFN(10,("%s: %s: stat=0x%02x\n", USBDEVNAME(sc
->sc_dev
),
842 upl_ioctl(struct ifnet
*ifp
, u_long command
, void *data
)
844 struct upl_softc
*sc
= ifp
->if_softc
;
845 struct ifaddr
*ifa
= (struct ifaddr
*)data
;
846 struct ifreq
*ifr
= (struct ifreq
*)data
;
852 DPRINTFN(5,("%s: %s: cmd=0x%08lx\n",
853 USBDEVNAME(sc
->sc_dev
), __func__
, command
));
859 ifp
->if_flags
|= IFF_UP
;
862 switch (ifa
->ifa_addr
->sa_family
) {
871 if (ifr
->ifr_mtu
> UPL_BUFSZ
)
873 else if ((error
= ifioctl_common(ifp
, command
, data
)) == ENETRESET
)
878 if ((error
= ifioctl_common(ifp
, command
, data
)) != 0)
880 /* XXX re-use ether_ioctl() */
881 switch (ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) {
893 error
= ifioctl_common(ifp
, command
, data
);
903 upl_watchdog(struct ifnet
*ifp
)
905 struct upl_softc
*sc
= ifp
->if_softc
;
907 DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc
->sc_dev
),__func__
));
913 printf("%s: watchdog timeout\n", USBDEVNAME(sc
->sc_dev
));
918 if (IFQ_IS_EMPTY(&ifp
->if_snd
) == 0)
923 * Stop the adapter and free any mbufs allocated to the
927 upl_stop(struct upl_softc
*sc
)
933 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc
->sc_dev
),__func__
));
938 /* Stop transfers. */
939 if (sc
->sc_ep
[UPL_ENDPT_RX
] != NULL
) {
940 err
= usbd_abort_pipe(sc
->sc_ep
[UPL_ENDPT_RX
]);
942 printf("%s: abort rx pipe failed: %s\n",
943 USBDEVNAME(sc
->sc_dev
), usbd_errstr(err
));
945 err
= usbd_close_pipe(sc
->sc_ep
[UPL_ENDPT_RX
]);
947 printf("%s: close rx pipe failed: %s\n",
948 USBDEVNAME(sc
->sc_dev
), usbd_errstr(err
));
950 sc
->sc_ep
[UPL_ENDPT_RX
] = NULL
;
953 if (sc
->sc_ep
[UPL_ENDPT_TX
] != NULL
) {
954 err
= usbd_abort_pipe(sc
->sc_ep
[UPL_ENDPT_TX
]);
956 printf("%s: abort tx pipe failed: %s\n",
957 USBDEVNAME(sc
->sc_dev
), usbd_errstr(err
));
959 err
= usbd_close_pipe(sc
->sc_ep
[UPL_ENDPT_TX
]);
961 printf("%s: close tx pipe failed: %s\n",
962 USBDEVNAME(sc
->sc_dev
), usbd_errstr(err
));
964 sc
->sc_ep
[UPL_ENDPT_TX
] = NULL
;
967 if (sc
->sc_ep
[UPL_ENDPT_INTR
] != NULL
) {
968 err
= usbd_abort_pipe(sc
->sc_ep
[UPL_ENDPT_INTR
]);
970 printf("%s: abort intr pipe failed: %s\n",
971 USBDEVNAME(sc
->sc_dev
), usbd_errstr(err
));
973 err
= usbd_close_pipe(sc
->sc_ep
[UPL_ENDPT_INTR
]);
975 printf("%s: close intr pipe failed: %s\n",
976 USBDEVNAME(sc
->sc_dev
), usbd_errstr(err
));
978 sc
->sc_ep
[UPL_ENDPT_INTR
] = NULL
;
981 /* Free RX resources. */
982 for (i
= 0; i
< UPL_RX_LIST_CNT
; i
++) {
983 if (sc
->sc_cdata
.upl_rx_chain
[i
].upl_mbuf
!= NULL
) {
984 m_freem(sc
->sc_cdata
.upl_rx_chain
[i
].upl_mbuf
);
985 sc
->sc_cdata
.upl_rx_chain
[i
].upl_mbuf
= NULL
;
987 if (sc
->sc_cdata
.upl_rx_chain
[i
].upl_xfer
!= NULL
) {
988 usbd_free_xfer(sc
->sc_cdata
.upl_rx_chain
[i
].upl_xfer
);
989 sc
->sc_cdata
.upl_rx_chain
[i
].upl_xfer
= NULL
;
993 /* Free TX resources. */
994 for (i
= 0; i
< UPL_TX_LIST_CNT
; i
++) {
995 if (sc
->sc_cdata
.upl_tx_chain
[i
].upl_mbuf
!= NULL
) {
996 m_freem(sc
->sc_cdata
.upl_tx_chain
[i
].upl_mbuf
);
997 sc
->sc_cdata
.upl_tx_chain
[i
].upl_mbuf
= NULL
;
999 if (sc
->sc_cdata
.upl_tx_chain
[i
].upl_xfer
!= NULL
) {
1000 usbd_free_xfer(sc
->sc_cdata
.upl_tx_chain
[i
].upl_xfer
);
1001 sc
->sc_cdata
.upl_tx_chain
[i
].upl_xfer
= NULL
;
1005 ifp
->if_flags
&= ~(IFF_RUNNING
| IFF_OACTIVE
);
1009 upl_output(struct ifnet
*ifp
, struct mbuf
*m
, const struct sockaddr
*dst
,
1010 struct rtentry
*rt0
)
1013 ALTQ_DECL(struct altq_pktattr pktattr
;)
1015 DPRINTFN(10,("%s: %s: enter\n",
1016 USBDEVNAME(((struct upl_softc
*)ifp
->if_softc
)->sc_dev
),
1020 * if the queueing discipline needs packet classification,
1023 IFQ_CLASSIFY(&ifp
->if_snd
, m
, dst
->sa_family
, &pktattr
);
1025 len
= m
->m_pkthdr
.len
;
1028 * Queue message on interface, and start output if interface
1031 IFQ_ENQUEUE(&ifp
->if_snd
, m
, &pktattr
, error
);
1033 /* mbuf is already freed */
1037 ifp
->if_obytes
+= len
;
1038 if ((ifp
->if_flags
& IFF_OACTIVE
) == 0)
1039 (*ifp
->if_start
)(ifp
);
1046 upl_input(struct ifnet
*ifp
, struct mbuf
*m
)
1049 struct ifqueue
*inq
;
1052 /* XXX Assume all traffic is IP */
1054 schednetisr(NETISR_IP
);
1058 if (IF_QFULL(inq
)) {
1062 if (sc
->sc_flags
& SC_DEBUG
)
1063 printf("%s: input queue full\n", ifp
->if_xname
);
1072 ifp
->if_ibytes
+= m
->m_len
;