| @@ -1,325 +1,324 @@ | | | @@ -1,325 +1,324 @@ |
1 | /* $NetBSD: if_upl.c,v 1.66 2019/08/20 06:37:06 mrg Exp $ */ | | 1 | /* $NetBSD: if_upl.c,v 1.67 2019/08/27 17:24:51 maxv Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2000 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2000 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Lennart Augustsson (lennart@augustsson.net) at | | 8 | * by Lennart Augustsson (lennart@augustsson.net) at |
9 | * Carlstedt Research & Technology. | | 9 | * Carlstedt Research & Technology. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. | | 15 | * notice, this list of conditions and the following disclaimer. |
16 | * 2. Redistributions in binary form must reproduce the above copyright | | 16 | * 2. Redistributions in binary form must reproduce the above copyright |
17 | * notice, this list of conditions and the following disclaimer in the | | 17 | * notice, this list of conditions and the following disclaimer in the |
18 | * documentation and/or other materials provided with the distribution. | | 18 | * documentation and/or other materials provided with the distribution. |
19 | * | | 19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
30 | * POSSIBILITY OF SUCH DAMAGE. | | 30 | * POSSIBILITY OF SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | /* | | 33 | /* |
34 | * Prolific PL2301/PL2302 driver | | 34 | * Prolific PL2301/PL2302 driver |
35 | */ | | 35 | */ |
36 | | | 36 | |
37 | #include <sys/cdefs.h> | | 37 | #include <sys/cdefs.h> |
38 | __KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1.66 2019/08/20 06:37:06 mrg Exp $"); | | 38 | __KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1.67 2019/08/27 17:24:51 maxv Exp $"); |
39 | | | 39 | |
40 | #ifdef _KERNEL_OPT | | 40 | #ifdef _KERNEL_OPT |
41 | #include "opt_inet.h" | | 41 | #include "opt_inet.h" |
42 | #include "opt_usb.h" | | 42 | #include "opt_usb.h" |
43 | #endif | | 43 | #endif |
44 | | | 44 | |
45 | #include <sys/param.h> | | 45 | #include <sys/param.h> |
46 | | | 46 | |
47 | #include <dev/usb/usbnet.h> | | 47 | #include <dev/usb/usbnet.h> |
48 | | | 48 | |
49 | #include <net/if_types.h> | | 49 | #include <net/if_types.h> |
50 | | | 50 | |
51 | #ifdef INET | | 51 | #ifdef INET |
52 | #include <netinet/in.h> | | 52 | #include <netinet/in.h> |
53 | #include <netinet/in_var.h> | | 53 | #include <netinet/in_var.h> |
54 | #include <netinet/if_inarp.h> | | 54 | #include <netinet/if_inarp.h> |
55 | #endif | | 55 | #endif |
56 | | | 56 | |
57 | /* | | 57 | /* |
58 | * 7 6 5 4 3 2 1 0 | | 58 | * 7 6 5 4 3 2 1 0 |
59 | * tx rx 1 0 | | 59 | * tx rx 1 0 |
60 | * 1110 0000 rxdata | | 60 | * 1110 0000 rxdata |
61 | * 1010 0000 idle | | 61 | * 1010 0000 idle |
62 | * 0010 0000 tx over | | 62 | * 0010 0000 tx over |
63 | * 0110 tx over + rxd | | 63 | * 0110 tx over + rxd |
64 | */ | | 64 | */ |
65 | | | 65 | |
66 | #define UPL_RXDATA 0x40 | | 66 | #define UPL_RXDATA 0x40 |
67 | #define UPL_TXOK 0x80 | | 67 | #define UPL_TXOK 0x80 |
68 | | | 68 | |
69 | #define UPL_CONFIG_NO 1 | | 69 | #define UPL_CONFIG_NO 1 |
70 | #define UPL_IFACE_IDX 0 | | 70 | #define UPL_IFACE_IDX 0 |
71 | | | 71 | |
72 | /***/ | | 72 | /***/ |
73 | | | 73 | |
74 | #define UPL_INTR_INTERVAL 20 | | 74 | #define UPL_INTR_INTERVAL 20 |
75 | | | 75 | |
76 | #define UPL_BUFSZ 1024 | | 76 | #define UPL_BUFSZ 1024 |
77 | | | 77 | |
78 | #define UPL_RX_LIST_CNT 1 | | 78 | #define UPL_RX_LIST_CNT 1 |
79 | #define UPL_TX_LIST_CNT 1 | | 79 | #define UPL_TX_LIST_CNT 1 |
80 | | | 80 | |
81 | #ifdef UPL_DEBUG | | 81 | #ifdef UPL_DEBUG |
82 | #define DPRINTF(x) if (upldebug) printf x | | 82 | #define DPRINTF(x) if (upldebug) printf x |
83 | #define DPRINTFN(n,x) if (upldebug >= (n)) printf x | | 83 | #define DPRINTFN(n,x) if (upldebug >= (n)) printf x |
84 | int upldebug = 0; | | 84 | int upldebug = 0; |
85 | #else | | 85 | #else |
86 | #define DPRINTF(x) | | 86 | #define DPRINTF(x) |
87 | #define DPRINTFN(n,x) | | 87 | #define DPRINTFN(n,x) |
88 | #endif | | 88 | #endif |
89 | | | 89 | |
90 | /* | | 90 | /* |
91 | * Various supported device vendors/products. | | 91 | * Various supported device vendors/products. |
92 | */ | | 92 | */ |
93 | static struct usb_devno sc_devs[] = { | | 93 | static struct usb_devno sc_devs[] = { |
94 | { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301 }, | | 94 | { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301 }, |
95 | { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302 }, | | 95 | { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302 }, |
96 | { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL25A1 }, | | 96 | { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL25A1 }, |
97 | { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U258 }, | | 97 | { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U258 }, |
98 | { USB_VENDOR_NI, USB_PRODUCT_NI_HTOH_7825 }, | | 98 | { USB_VENDOR_NI, USB_PRODUCT_NI_HTOH_7825 } |
99 | { 0, 0 } | | | |
100 | }; | | 99 | }; |
101 | | | 100 | |
102 | int upl_match(device_t, cfdata_t, void *); | | 101 | int upl_match(device_t, cfdata_t, void *); |
103 | void upl_attach(device_t, device_t, void *); | | 102 | void upl_attach(device_t, device_t, void *); |
104 | | | 103 | |
105 | CFATTACH_DECL_NEW(upl, sizeof(struct usbnet), upl_match, upl_attach, | | 104 | CFATTACH_DECL_NEW(upl, sizeof(struct usbnet), upl_match, upl_attach, |
106 | usbnet_detach, usbnet_activate); | | 105 | usbnet_detach, usbnet_activate); |
107 | | | 106 | |
108 | #if 0 | | 107 | #if 0 |
109 | static void upl_intr_cb(struct usbnet *, usbd_status); | | 108 | static void upl_intr_cb(struct usbnet *, usbd_status); |
110 | #endif | | 109 | #endif |
111 | static void upl_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); | | 110 | static void upl_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t); |
112 | static unsigned upl_tx_prepare(struct usbnet *, struct mbuf *, | | 111 | static unsigned upl_tx_prepare(struct usbnet *, struct mbuf *, |
113 | struct usbnet_chain *); | | 112 | struct usbnet_chain *); |
114 | static int upl_ioctl_cb(struct ifnet *, u_long, void *); | | 113 | static int upl_ioctl_cb(struct ifnet *, u_long, void *); |
115 | static int upl_init(struct ifnet *); | | 114 | static int upl_init(struct ifnet *); |
116 | | | 115 | |
117 | static struct usbnet_ops upl_ops = { | | 116 | static struct usbnet_ops upl_ops = { |
118 | .uno_init = upl_init, | | 117 | .uno_init = upl_init, |
119 | .uno_tx_prepare = upl_tx_prepare, | | 118 | .uno_tx_prepare = upl_tx_prepare, |
120 | .uno_rx_loop = upl_rx_loop, | | 119 | .uno_rx_loop = upl_rx_loop, |
121 | .uno_ioctl = upl_ioctl_cb, | | 120 | .uno_ioctl = upl_ioctl_cb, |
122 | #if 0 | | 121 | #if 0 |
123 | .uno_intr = upl_intr_cb, | | 122 | .uno_intr = upl_intr_cb, |
124 | #endif | | 123 | #endif |
125 | }; | | 124 | }; |
126 | | | 125 | |
127 | static int upl_output(struct ifnet *, struct mbuf *, const struct sockaddr *, | | 126 | static int upl_output(struct ifnet *, struct mbuf *, const struct sockaddr *, |
128 | const struct rtentry *); | | 127 | const struct rtentry *); |
129 | static void upl_input(struct ifnet *, struct mbuf *); | | 128 | static void upl_input(struct ifnet *, struct mbuf *); |
130 | | | 129 | |
131 | /* | | 130 | /* |
132 | * Probe for a Prolific chip. | | 131 | * Probe for a Prolific chip. |
133 | */ | | 132 | */ |
134 | int | | 133 | int |
135 | upl_match(device_t parent, cfdata_t match, void *aux) | | 134 | upl_match(device_t parent, cfdata_t match, void *aux) |
136 | { | | 135 | { |
137 | struct usb_attach_arg *uaa = aux; | | 136 | struct usb_attach_arg *uaa = aux; |
138 | | | 137 | |
139 | return usb_lookup(sc_devs, uaa->uaa_vendor, uaa->uaa_product) != NULL ? | | 138 | return usb_lookup(sc_devs, uaa->uaa_vendor, uaa->uaa_product) != NULL ? |
140 | UMATCH_VENDOR_PRODUCT : UMATCH_NONE; | | 139 | UMATCH_VENDOR_PRODUCT : UMATCH_NONE; |
141 | } | | 140 | } |
142 | | | 141 | |
143 | void | | 142 | void |
144 | upl_attach(device_t parent, device_t self, void *aux) | | 143 | upl_attach(device_t parent, device_t self, void *aux) |
145 | { | | 144 | { |
146 | struct usbnet * const un = device_private(self); | | 145 | struct usbnet * const un = device_private(self); |
147 | struct usb_attach_arg *uaa = aux; | | 146 | struct usb_attach_arg *uaa = aux; |
148 | char *devinfop; | | 147 | char *devinfop; |
149 | struct usbd_device * dev = uaa->uaa_device; | | 148 | struct usbd_device * dev = uaa->uaa_device; |
150 | usbd_status err; | | 149 | usbd_status err; |
151 | usb_interface_descriptor_t *id; | | 150 | usb_interface_descriptor_t *id; |
152 | usb_endpoint_descriptor_t *ed; | | 151 | usb_endpoint_descriptor_t *ed; |
153 | int i; | | 152 | int i; |
154 | | | 153 | |
155 | DPRINTFN(5,(" : upl_attach: un=%p, dev=%p", un, dev)); | | 154 | DPRINTFN(5,(" : upl_attach: un=%p, dev=%p", un, dev)); |
156 | | | 155 | |
157 | aprint_naive("\n"); | | 156 | aprint_naive("\n"); |
158 | aprint_normal("\n"); | | 157 | aprint_normal("\n"); |
159 | devinfop = usbd_devinfo_alloc(dev, 0); | | 158 | devinfop = usbd_devinfo_alloc(dev, 0); |
160 | aprint_normal_dev(self, "%s\n", devinfop); | | 159 | aprint_normal_dev(self, "%s\n", devinfop); |
161 | usbd_devinfo_free(devinfop); | | 160 | usbd_devinfo_free(devinfop); |
162 | | | 161 | |
163 | un->un_dev = self; | | 162 | un->un_dev = self; |
164 | un->un_udev = dev; | | 163 | un->un_udev = dev; |
165 | un->un_sc = un; | | 164 | un->un_sc = un; |
166 | un->un_ops = &upl_ops; | | 165 | un->un_ops = &upl_ops; |
167 | un->un_rx_xfer_flags = USBD_SHORT_XFER_OK; | | 166 | un->un_rx_xfer_flags = USBD_SHORT_XFER_OK; |
168 | un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER; | | 167 | un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER; |
169 | un->un_rx_list_cnt = UPL_RX_LIST_CNT; | | 168 | un->un_rx_list_cnt = UPL_RX_LIST_CNT; |
170 | un->un_tx_list_cnt = UPL_TX_LIST_CNT; | | 169 | un->un_tx_list_cnt = UPL_TX_LIST_CNT; |
171 | un->un_rx_bufsz = UPL_BUFSZ; | | 170 | un->un_rx_bufsz = UPL_BUFSZ; |
172 | un->un_tx_bufsz = UPL_BUFSZ; | | 171 | un->un_tx_bufsz = UPL_BUFSZ; |
173 | | | 172 | |
174 | err = usbd_set_config_no(dev, UPL_CONFIG_NO, 1); | | 173 | err = usbd_set_config_no(dev, UPL_CONFIG_NO, 1); |
175 | if (err) { | | 174 | if (err) { |
176 | aprint_error_dev(self, "failed to set configuration" | | 175 | aprint_error_dev(self, "failed to set configuration" |
177 | ", err=%s\n", usbd_errstr(err)); | | 176 | ", err=%s\n", usbd_errstr(err)); |
178 | return; | | 177 | return; |
179 | } | | 178 | } |
180 | | | 179 | |
181 | err = usbd_device2interface_handle(dev, UPL_IFACE_IDX, &un->un_iface); | | 180 | err = usbd_device2interface_handle(dev, UPL_IFACE_IDX, &un->un_iface); |
182 | if (err) { | | 181 | if (err) { |
183 | aprint_error_dev(self, "getting interface handle failed\n"); | | 182 | aprint_error_dev(self, "getting interface handle failed\n"); |
184 | return; | | 183 | return; |
185 | } | | 184 | } |
186 | | | 185 | |
187 | id = usbd_get_interface_descriptor(un->un_iface); | | 186 | id = usbd_get_interface_descriptor(un->un_iface); |
188 | | | 187 | |
189 | /* Find endpoints. */ | | 188 | /* Find endpoints. */ |
190 | for (i = 0; i < id->bNumEndpoints; i++) { | | 189 | for (i = 0; i < id->bNumEndpoints; i++) { |
191 | ed = usbd_interface2endpoint_descriptor(un->un_iface, i); | | 190 | ed = usbd_interface2endpoint_descriptor(un->un_iface, i); |
192 | if (ed == NULL) { | | 191 | if (ed == NULL) { |
193 | aprint_error_dev(self, "couldn't get ep %d\n", i); | | 192 | aprint_error_dev(self, "couldn't get ep %d\n", i); |
194 | return; | | 193 | return; |
195 | } | | 194 | } |
196 | if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && | | 195 | if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && |
197 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { | | 196 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { |
198 | un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress; | | 197 | un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress; |
199 | } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && | | 198 | } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && |
200 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { | | 199 | UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { |
201 | un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress; | | 200 | un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress; |
202 | } | | 201 | } |
203 | } | | 202 | } |
204 | | | 203 | |
205 | if (un->un_ed[USBNET_ENDPT_RX] == 0 || un->un_ed[USBNET_ENDPT_TX] == 0 /*|| | | 204 | if (un->un_ed[USBNET_ENDPT_RX] == 0 || un->un_ed[USBNET_ENDPT_TX] == 0 /*|| |
206 | un->un_ed[USBNET_ENDPT_INTR] == 0*/) { | | 205 | un->un_ed[USBNET_ENDPT_INTR] == 0*/) { |
207 | aprint_error_dev(self, "missing endpoint\n"); | | 206 | aprint_error_dev(self, "missing endpoint\n"); |
208 | return; | | 207 | return; |
209 | } | | 208 | } |
210 | | | 209 | |
211 | usbnet_attach(un, "upldet"); | | 210 | usbnet_attach(un, "upldet"); |
212 | | | 211 | |
213 | /* Initialize interface info.*/ | | 212 | /* Initialize interface info.*/ |
214 | struct ifnet *ifp = usbnet_ifp(un); | | 213 | struct ifnet *ifp = usbnet_ifp(un); |
215 | ifp->if_mtu = UPL_BUFSZ; | | 214 | ifp->if_mtu = UPL_BUFSZ; |
216 | ifp->if_type = IFT_OTHER; | | 215 | ifp->if_type = IFT_OTHER; |
217 | ifp->if_addrlen = 0; | | 216 | ifp->if_addrlen = 0; |
218 | ifp->if_hdrlen = 0; | | 217 | ifp->if_hdrlen = 0; |
219 | ifp->if_output = upl_output; | | 218 | ifp->if_output = upl_output; |
220 | ifp->_if_input = upl_input; | | 219 | ifp->_if_input = upl_input; |
221 | ifp->if_baudrate = 12000000; | | 220 | ifp->if_baudrate = 12000000; |
222 | ifp->if_dlt = DLT_RAW; | | 221 | ifp->if_dlt = DLT_RAW; |
223 | | | 222 | |
224 | usbnet_attach_ifp(un, IFF_POINTOPOINT | IFF_NOARP | IFF_SIMPLEX, | | 223 | usbnet_attach_ifp(un, IFF_POINTOPOINT | IFF_NOARP | IFF_SIMPLEX, |
225 | 0, NULL); | | 224 | 0, NULL); |
226 | } | | 225 | } |
227 | | | 226 | |
228 | static void | | 227 | static void |
229 | upl_rx_loop(struct usbnet * un, struct usbnet_chain *c, uint32_t total_len) | | 228 | upl_rx_loop(struct usbnet * un, struct usbnet_chain *c, uint32_t total_len) |
230 | { | | 229 | { |
231 | usbnet_isowned_rx(un); | | 230 | usbnet_isowned_rx(un); |
232 | | | 231 | |
233 | DPRINTFN(9,("%s: %s: enter status=%d length=%d\n", | | 232 | DPRINTFN(9,("%s: %s: enter status=%d length=%d\n", |
234 | device_xname(un->un_dev), __func__, status, total_len)); | | 233 | device_xname(un->un_dev), __func__, status, total_len)); |
235 | | | 234 | |
236 | usbnet_input(un, c->unc_buf, total_len); | | 235 | usbnet_input(un, c->unc_buf, total_len); |
237 | } | | 236 | } |
238 | | | 237 | |
239 | static unsigned | | 238 | static unsigned |
240 | upl_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) | | 239 | upl_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) |
241 | { | | 240 | { |
242 | int total_len; | | 241 | int total_len; |
243 | | | 242 | |
244 | if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz) | | 243 | if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz) |
245 | return 0; | | 244 | return 0; |
246 | | | 245 | |
247 | m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf); | | 246 | m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf); |
248 | total_len = m->m_pkthdr.len; | | 247 | total_len = m->m_pkthdr.len; |
249 | | | 248 | |
250 | DPRINTFN(10,("%s: %s: total_len=%d\n", | | 249 | DPRINTFN(10,("%s: %s: total_len=%d\n", |
251 | device_xname(un->un_dev), __func__, total_len)); | | 250 | device_xname(un->un_dev), __func__, total_len)); |
252 | | | 251 | |
253 | return total_len; | | 252 | return total_len; |
254 | } | | 253 | } |
255 | | | 254 | |
256 | static int | | 255 | static int |
257 | upl_init(struct ifnet *ifp) | | 256 | upl_init(struct ifnet *ifp) |
258 | { | | 257 | { |
259 | struct usbnet * const un = ifp->if_softc; | | 258 | struct usbnet * const un = ifp->if_softc; |
260 | int rv; | | 259 | int rv; |
261 | | | 260 | |
262 | usbnet_lock(un); | | 261 | usbnet_lock(un); |
263 | if (usbnet_isdying(un)) | | 262 | if (usbnet_isdying(un)) |
264 | rv = EIO; | | 263 | rv = EIO; |
265 | else | | 264 | else |
266 | rv = usbnet_init_rx_tx(un); | | 265 | rv = usbnet_init_rx_tx(un); |
267 | usbnet_unlock(un); | | 266 | usbnet_unlock(un); |
268 | | | 267 | |
269 | return rv; | | 268 | return rv; |
270 | } | | 269 | } |
271 | | | 270 | |
272 | static int | | 271 | static int |
273 | upl_ioctl_cb(struct ifnet *ifp, u_long cmd, void *data) | | 272 | upl_ioctl_cb(struct ifnet *ifp, u_long cmd, void *data) |
274 | { | | 273 | { |
275 | if (cmd == SIOCSIFMTU) { | | 274 | if (cmd == SIOCSIFMTU) { |
276 | struct ifreq *ifr = data; | | 275 | struct ifreq *ifr = data; |
277 | | | 276 | |
278 | if (ifr->ifr_mtu > UPL_BUFSZ) | | 277 | if (ifr->ifr_mtu > UPL_BUFSZ) |
279 | return EINVAL; | | 278 | return EINVAL; |
280 | } | | 279 | } |
281 | return 0; | | 280 | return 0; |
282 | } | | 281 | } |
283 | | | 282 | |
284 | static int | | 283 | static int |
285 | upl_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, | | 284 | upl_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, |
286 | const struct rtentry *rt0) | | 285 | const struct rtentry *rt0) |
287 | { | | 286 | { |
288 | struct usbnet * const un __unused = ifp->if_softc; | | 287 | struct usbnet * const un __unused = ifp->if_softc; |
289 | | | 288 | |
290 | DPRINTFN(10,("%s: %s: enter\n", device_xname(un->un_dev), __func__)); | | 289 | DPRINTFN(10,("%s: %s: enter\n", device_xname(un->un_dev), __func__)); |
291 | | | 290 | |
292 | /* If the queueing discipline needs packet classification, do it now. */ | | 291 | /* If the queueing discipline needs packet classification, do it now. */ |
293 | IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family); | | 292 | IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family); |
294 | | | 293 | |
295 | /* | | 294 | /* |
296 | * Queue message on interface, and start output if interface | | 295 | * Queue message on interface, and start output if interface |
297 | * not yet active. | | 296 | * not yet active. |
298 | */ | | 297 | */ |
299 | return if_transmit_lock(ifp, m); | | 298 | return if_transmit_lock(ifp, m); |
300 | } | | 299 | } |
301 | | | 300 | |
302 | static void | | 301 | static void |
303 | upl_input(struct ifnet *ifp, struct mbuf *m) | | 302 | upl_input(struct ifnet *ifp, struct mbuf *m) |
304 | { | | 303 | { |
305 | #ifdef INET | | 304 | #ifdef INET |
306 | size_t pktlen = m->m_len; | | 305 | size_t pktlen = m->m_len; |
307 | int s; | | 306 | int s; |
308 | | | 307 | |
309 | s = splnet(); | | 308 | s = splnet(); |
310 | if (__predict_false(!pktq_enqueue(ip_pktq, m, 0))) { | | 309 | if (__predict_false(!pktq_enqueue(ip_pktq, m, 0))) { |
311 | ifp->if_iqdrops++; | | 310 | ifp->if_iqdrops++; |
312 | m_freem(m); | | 311 | m_freem(m); |
313 | } else { | | 312 | } else { |
314 | ifp->if_ipackets++; | | 313 | ifp->if_ipackets++; |
315 | ifp->if_ibytes += pktlen; | | 314 | ifp->if_ibytes += pktlen; |
316 | } | | 315 | } |
317 | splx(s); | | 316 | splx(s); |
318 | #endif | | 317 | #endif |
319 | } | | 318 | } |
320 | | | 319 | |
321 | #ifdef _MODULE | | 320 | #ifdef _MODULE |
322 | #include "ioconf.c" | | 321 | #include "ioconf.c" |
323 | #endif | | 322 | #endif |
324 | | | 323 | |
325 | USBNET_MODULE(upl) | | 324 | USBNET_MODULE(upl) |