Bug Summary

File:dev/usb/if_uaq.c
Warning:line 364, column 2
Undefined or garbage value returned to caller

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name if_uaq.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/usb/if_uaq.c
1/* $OpenBSD: if_uaq.c,v 1.2 2021/12/31 08:15:47 jmatthew Exp $ */
2/*-
3 * Copyright (c) 2021 Jonathan Matthew <jonathan@d14n.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include "bpfilter.h"
29#include "vlan.h"
30
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/sockio.h>
34#include <sys/rwlock.h>
35#include <sys/mbuf.h>
36#include <sys/kernel.h>
37#include <sys/socket.h>
38#include <sys/device.h>
39
40#include <machine/bus.h>
41
42#include <net/if.h>
43#include <net/if_media.h>
44
45#if NBPFILTER1 > 0
46#include <net/bpf.h>
47#endif
48
49#include <netinet/in.h>
50#include <netinet/if_ether.h>
51
52#include <dev/usb/usb.h>
53#include <dev/usb/usbdi.h>
54#include <dev/usb/usbdi_util.h>
55#include <dev/usb/usbdivar.h>
56#include <dev/usb/usbdevs.h>
57
58#ifdef UAQ_DEBUG
59#define DPRINTF(x) do { if (uaqdebug) printf x; } while (0)
60#define DPRINTFN(n,x) do { if (uaqdebug >= (n)) printf x; } while (0)
61int uaqdebug = 0;
62#else
63#define DPRINTF(x)
64#define DPRINTFN(n,x)
65#endif
66
67#define UAQ_ENDPT_RX0 0
68#define UAQ_ENDPT_TX1 1
69#define UAQ_ENDPT_INTR2 2
70#define UAQ_ENDPT_MAX3 3
71
72#define UAQ_TX_LIST_CNT1 1
73#define UAQ_RX_LIST_CNT1 1
74#define UAQ_TX_BUF_ALIGN8 8
75#define UAQ_RX_BUF_ALIGN8 8
76
77#define UAQ_TX_BUFSZ16384 16384
78#define UAQ_RX_BUFSZ32768 32768
79
80#define UAQ_CTL_READ1 1
81#define UAQ_CTL_WRITE2 2
82
83#define UAQ_MCAST_FILTER_SIZE8 8
84
85/* control commands */
86#define UAQ_CMD_ACCESS_MAC0x01 0x01
87#define UAQ_CMD_FLASH_PARAM0x20 0x20
88#define UAQ_CMD_PHY_POWER0x31 0x31
89#define UAQ_CMD_WOL_CFG0x60 0x60
90#define UAQ_CMD_PHY_OPS0x61 0x61
91
92/* SFR registers */
93#define UAQ_SFR_GENERAL_STATUS0x03 0x03
94#define UAQ_SFR_CHIP_STATUS0x05 0x05
95#define UAQ_SFR_RX_CTL0x0B 0x0B
96#define UAQ_SFR_RX_CTL_STOP0x0000 0x0000
97#define UAQ_SFR_RX_CTL_PRO0x0001 0x0001
98#define UAQ_SFR_RX_CTL_AMALL0x0002 0x0002
99#define UAQ_SFR_RX_CTL_AB0x0008 0x0008
100#define UAQ_SFR_RX_CTL_AM0x0010 0x0010
101#define UAQ_SFR_RX_CTL_START0x0080 0x0080
102#define UAQ_SFR_RX_CTL_IPE0x0200 0x0200
103#define UAQ_SFR_IPG_00x0D 0x0D
104#define UAQ_SFR_NODE_ID0x10 0x10
105#define UAQ_SFR_MCAST_FILTER0x16 0x16
106#define UAQ_SFR_MEDIUM_STATUS_MODE0x22 0x22
107#define UAQ_SFR_MEDIUM_XGMIIMODE0x0001 0x0001
108#define UAQ_SFR_MEDIUM_FULL_DUPLEX0x0002 0x0002
109#define UAQ_SFR_MEDIUM_RXFLOW_CTRLEN0x0010 0x0010
110#define UAQ_SFR_MEDIUM_TXFLOW_CTRLEN0x0020 0x0020
111#define UAQ_SFR_MEDIUM_JUMBO_EN0x0040 0x0040
112#define UAQ_SFR_MEDIUM_RECEIVE_EN0x0100 0x0100
113#define UAQ_SFR_MONITOR_MODE0x24 0x24
114#define UAQ_SFR_MONITOR_MODE_EPHYRW0x01 0x01
115#define UAQ_SFR_MONITOR_MODE_RWLC0x02 0x02
116#define UAQ_SFR_MONITOR_MODE_RWMP0x04 0x04
117#define UAQ_SFR_MONITOR_MODE_RWWF0x08 0x08
118#define UAQ_SFR_MONITOR_MODE_RW_FLAG0x10 0x10
119#define UAQ_SFR_MONITOR_MODE_PMEPOL0x20 0x20
120#define UAQ_SFR_MONITOR_MODE_PMETYPE0x40 0x40
121#define UAQ_SFR_RX_BULKIN_QCTRL0x2E 0x2E
122#define UAQ_SFR_RXCOE_CTL0x34 0x34
123#define UAQ_SFR_RXCOE_IP0x01 0x01
124#define UAQ_SFR_RXCOE_TCP0x02 0x02
125#define UAQ_SFR_RXCOE_UDP0x04 0x04
126#define UAQ_SFR_RXCOE_ICMP0x08 0x08
127#define UAQ_SFR_RXCOE_IGMP0x10 0x10
128#define UAQ_SFR_RXCOE_TCPV60x20 0x20
129#define UAQ_SFR_RXCOE_UDPV60x40 0x40
130#define UAQ_SFR_RXCOE_ICMV60x80 0x80
131#define UAQ_SFR_TXCOE_CTL0x35 0x35
132#define UAQ_SFR_TXCOE_IP0x01 0x01
133#define UAQ_SFR_TXCOE_TCP0x02 0x02
134#define UAQ_SFR_TXCOE_UDP0x04 0x04
135#define UAQ_SFR_TXCOE_ICMP0x08 0x08
136#define UAQ_SFR_TXCOE_IGMP0x10 0x10
137#define UAQ_SFR_TXCOE_TCPV60x20 0x20
138#define UAQ_SFR_TXCOE_UDPV60x40 0x40
139#define UAQ_SFR_TXCOE_ICMV60x80 0x80
140#define UAQ_SFR_BM_INT_MASK0x41 0x41
141#define UAQ_SFR_BMRX_DMA_CTRL0x43 0x43
142#define UAQ_SFR_BMRX_DMA_EN0x80 0x80
143#define UAQ_SFR_BMTX_DMA_CTRL0x46 0x46
144#define UAQ_SFR_PAUSE_WATERLVL_LOW0x54 0x54
145#define UAQ_SFR_ARC_CTRL0x9E 0x9E
146#define UAQ_SFR_SWP_CTRL0xB1 0xB1
147#define UAQ_SFR_TX_PAUSE_RESEND_T0xB2 0xB2
148#define UAQ_SFR_ETH_MAC_PATH0xB7 0xB7
149#define UAQ_SFR_RX_PATH_READY0x01 0x01
150#define UAQ_SFR_BULK_OUT_CTRL0xB9 0xB9
151#define UAQ_SFR_BULK_OUT_FLUSH_EN0x01 0x01
152#define UAQ_SFR_BULK_OUT_EFF_EN0x02 0x02
153
154#define UAQ_FW_VER_MAJOR0xDA 0xDA
155#define UAQ_FW_VER_MINOR0xDB 0xDB
156#define UAQ_FW_VER_REV0xDC 0xDC
157
158/* phy ops */
159#define UAQ_PHY_ADV_100M(1 << 0) (1 << 0)
160#define UAQ_PHY_ADV_1G(1 << 1) (1 << 1)
161#define UAQ_PHY_ADV_2_5G(1 << 2) (1 << 2)
162#define UAQ_PHY_ADV_5G(1 << 3) (1 << 3)
163#define UAQ_PHY_ADV_MASK0x0F 0x0F
164
165#define UAQ_PHY_PAUSE(1 << 16) (1 << 16)
166#define UAQ_PHY_ASYM_PAUSE(1 << 17) (1 << 17)
167#define UAQ_PHY_LOW_POWER(1 << 18) (1 << 18)
168#define UAQ_PHY_POWER_EN(1 << 19) (1 << 19)
169#define UAQ_PHY_WOL(1 << 20) (1 << 20)
170#define UAQ_PHY_DOWNSHIFT(1 << 21) (1 << 21)
171
172#define UAQ_PHY_DSH_RETRY_SHIFT0x18 0x18
173#define UAQ_PHY_DSH_RETRY_MASK0xF000000 0xF000000
174
175/* status */
176#define UAQ_STATUS_LINK0x8000 0x8000
177#define UAQ_STATUS_SPEED_MASK0x7F00 0x7F00
178#define UAQ_STATUS_SPEED_SHIFT8 8
179#define UAQ_STATUS_SPEED_5G0x000F 0x000F
180#define UAQ_STATUS_SPEED_2_5G0x0010 0x0010
181#define UAQ_STATUS_SPEED_1G0x0011 0x0011
182#define UAQ_STATUS_SPEED_100M0x0013 0x0013
183
184/* rx descriptor */
185#define UAQ_RX_HDR_COUNT_MASK0x1FFF 0x1FFF
186#define UAQ_RX_HDR_OFFSET_MASK0xFFFFE000 0xFFFFE000
187#define UAQ_RX_HDR_OFFSET_SHIFT13 13
188
189/* rx packet descriptor */
190#define UAQ_RX_PKT_L4_ERR0x01 0x01
191#define UAQ_RX_PKT_L3_ERR0x02 0x02
192#define UAQ_RX_PKT_L4_MASK0x1C 0x1C
193#define UAQ_RX_PKT_L4_UDP0x04 0x04
194#define UAQ_RX_PKT_L4_TCP0x10 0x10
195#define UAQ_RX_PKT_L3_MASK0x60 0x60
196#define UAQ_RX_PKT_L3_IP0x20 0x20
197#define UAQ_RX_PKT_L3_IP60x40 0x40
198#define UAQ_RX_PKT_VLAN0x400 0x400
199#define UAQ_RX_PKT_RX_OK0x800 0x800
200#define UAQ_RX_PKT_DROP0x80000000 0x80000000
201#define UAQ_RX_PKT_LEN_MASK0x7FFF0000 0x7FFF0000
202#define UAQ_RX_PKT_LEN_SHIFT16 16
203#define UAQ_RX_PKT_VLAN_SHIFT32 32
204
205/* tx packet descriptor */
206#define UAQ_TX_PKT_LEN_MASK0x1FFFFF 0x1FFFFF
207#define UAQ_TX_PKT_DROP_PADD(1 << 28) (1 << 28)
208#define UAQ_TX_PKT_VLAN(1 << 29) (1 << 29)
209#define UAQ_TX_PKT_VLAN_MASK0xFFFF 0xFFFF
210#define UAQ_TX_PKT_VLAN_SHIFT0x30 0x30
211
212
213struct uaq_chain {
214 struct uaq_softc *uc_sc;
215 struct usbd_xfer *uc_xfer;
216 char *uc_buf;
217 uint32_t uc_cnt;
218 uint32_t uc_buflen;
219 uint32_t uc_bufmax;
220 SLIST_ENTRY(uaq_chain)struct { struct uaq_chain *sle_next; } uc_list;
221 uint8_t uc_idx;
222};
223
224struct uaq_cdata {
225 struct uaq_chain uaq_rx_chain[UAQ_RX_LIST_CNT1];
226 struct uaq_chain uaq_tx_chain[UAQ_TX_LIST_CNT1];
227 SLIST_HEAD(uaq_list_head, uaq_chain)struct uaq_list_head { struct uaq_chain *slh_first; } uaq_tx_free;
228};
229
230struct uaq_softc {
231 struct device sc_dev;
232 struct usbd_device *sc_udev;
233
234 struct usbd_interface *sc_iface;
235 struct usb_task sc_link_task;
236 struct timeval sc_rx_notice;
237 int sc_ed[UAQ_ENDPT_MAX3];
238 struct usbd_pipe *sc_ep[UAQ_ENDPT_MAX3];
239 int sc_out_frame_size;
240
241 struct arpcom sc_ac;
242 struct ifmedia sc_ifmedia;
243
244 struct uaq_cdata sc_cdata;
245 uint64_t sc_link_status;
246 int sc_link_speed;
247
248 uint32_t sc_phy_cfg;
249 uint16_t sc_rxctl;
250};
251
252const struct usb_devno uaq_devs[] = {
253 { USB_VENDOR_AQUANTIA0x2eca, USB_PRODUCT_AQUANTIA_AQC1110xc101 },
254 { USB_VENDOR_ASIX0x0b95, USB_PRODUCT_ASIX_ASIX1110x2790 },
255 { USB_VENDOR_ASIX0x0b95, USB_PRODUCT_ASIX_ASIX1120x2791 },
256 { USB_VENDOR_TRENDNET0x20f4, USB_PRODUCT_TRENDNET_TUCET5G0xe05a },
257 { USB_VENDOR_QNAP0x1c04, USB_PRODUCT_QNAP_UC5G1T0x0015 },
258};
259
260int uaq_match(struct device *, void *, void *);
261void uaq_attach(struct device *, struct device *, void *);
262int uaq_detach(struct device *, int);
263
264int uaq_ctl(struct uaq_softc *, uint8_t, uint8_t, uint16_t,
265 uint16_t, void *, int);
266int uaq_read_mem(struct uaq_softc *, uint8_t, uint16_t, uint16_t,
267 void *, int);
268int uaq_write_mem(struct uaq_softc *, uint8_t, uint16_t, uint16_t,
269 void *, int);
270uint8_t uaq_read_1(struct uaq_softc *, uint8_t, uint16_t, uint16_t);
271uint16_t uaq_read_2(struct uaq_softc *, uint8_t, uint16_t, uint16_t);
272uint32_t uaq_read_4(struct uaq_softc *, uint8_t, uint16_t, uint16_t);
273int uaq_write_1(struct uaq_softc *, uint8_t, uint16_t, uint16_t,
274 uint32_t);
275int uaq_write_2(struct uaq_softc *, uint8_t, uint16_t, uint16_t,
276 uint32_t);
277int uaq_write_4(struct uaq_softc *, uint8_t, uint16_t, uint16_t,
278 uint32_t);
279
280int uaq_ifmedia_upd(struct ifnet *);
281void uaq_ifmedia_sts(struct ifnet *, struct ifmediareq *);
282void uaq_add_media_types(struct uaq_softc *);
283void uaq_iff(struct uaq_softc *);
284
285void uaq_init(void *);
286int uaq_ioctl(struct ifnet *, u_long, caddr_t);
287int uaq_xfer_list_init(struct uaq_softc *, struct uaq_chain *,
288 uint32_t, int);
289void uaq_xfer_list_free(struct uaq_softc *, struct uaq_chain *, int);
290
291void uaq_stop(struct uaq_softc *);
292void uaq_link(struct uaq_softc *);
293void uaq_intr(struct usbd_xfer *, void *, usbd_status);
294void uaq_start(struct ifnet *);
295void uaq_rxeof(struct usbd_xfer *, void *, usbd_status);
296void uaq_txeof(struct usbd_xfer *, void *, usbd_status);
297void uaq_watchdog(struct ifnet *);
298void uaq_reset(struct uaq_softc *);
299
300int uaq_encap_txpkt(struct uaq_softc *, struct mbuf *, char *,
301 uint32_t);
302int uaq_encap_xfer(struct uaq_softc *, struct uaq_chain *);
303
304struct cfdriver uaq_cd = {
305 NULL((void *)0), "uaq", DV_IFNET
306};
307
308const struct cfattach uaq_ca = {
309 sizeof(struct uaq_softc), uaq_match, uaq_attach, uaq_detach
310};
311
312int
313uaq_ctl(struct uaq_softc *sc, uint8_t rw, uint8_t cmd, uint16_t val,
314 uint16_t index, void *buf, int len)
315{
316 usb_device_request_t req;
317 usbd_status err;
318
319 if (usbd_is_dying(sc->sc_udev))
12
Assuming the condition is true
13
Taking true branch
320 return 0;
14
Returning without writing to '*buf'
321
322 if (rw == UAQ_CTL_WRITE2)
323 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
324 else
325 req.bmRequestType = UT_READ_VENDOR_DEVICE(0x80 | 0x40 | 0x00);
326 req.bRequest = cmd;
327 USETW(req.wValue, val)(*(u_int16_t *)(req.wValue) = (val));
328 USETW(req.wIndex, index)(*(u_int16_t *)(req.wIndex) = (index));
329 USETW(req.wLength, len)(*(u_int16_t *)(req.wLength) = (len));
330
331 DPRINTFN(5, ("uaq_ctl: rw %d, val 0x%04hx, index 0x%04hx, len %d\n",
332 rw, val, index, len));
333 err = usbd_do_request(sc->sc_udev, &req, buf);
334 if (err) {
335 DPRINTF(("uaq_ctl: error %d\n", err));
336 return -1;
337 }
338
339 return 0;
340}
341
342int
343uaq_read_mem(struct uaq_softc *sc, uint8_t cmd, uint16_t addr, uint16_t index,
344 void *buf, int len)
345{
346 return (uaq_ctl(sc, UAQ_CTL_READ1, cmd, addr, index, buf, len));
11
Calling 'uaq_ctl'
15
Returning from 'uaq_ctl'
16
Returning without writing to '*buf'
347}
348
349int
350uaq_write_mem(struct uaq_softc *sc, uint8_t cmd, uint16_t addr, uint16_t index,
351 void *buf, int len)
352{
353 return (uaq_ctl(sc, UAQ_CTL_WRITE2, cmd, addr, index, buf, len));
354}
355
356uint8_t
357uaq_read_1(struct uaq_softc *sc, uint8_t cmd, uint16_t reg, uint16_t index)
358{
359 uint8_t val;
9
'val' declared without an initial value
360
361 uaq_read_mem(sc, cmd, reg, index, &val, 1);
10
Calling 'uaq_read_mem'
17
Returning from 'uaq_read_mem'
362 DPRINTFN(4, ("uaq_read_1: cmd %x reg %x index %x = %x\n", cmd, reg,
363 index, val));
364 return (val);
18
Undefined or garbage value returned to caller
365}
366
367uint16_t
368uaq_read_2(struct uaq_softc *sc, uint8_t cmd, uint16_t reg, uint16_t index)
369{
370 uint16_t val;
371
372 uaq_read_mem(sc, cmd, reg, index, &val, 2);
373 DPRINTFN(4, ("uaq_read_2: cmd %x reg %x index %x = %x\n", cmd, reg,
374 index, UGETW(&val)));
375
376 return (UGETW(&val)(*(u_int16_t *)(&val)));
377}
378
379uint32_t
380uaq_read_4(struct uaq_softc *sc, uint8_t cmd, uint16_t reg, uint16_t index)
381{
382 uint32_t val;
383
384 uaq_read_mem(sc, cmd, reg, index, &val, 4);
385 DPRINTFN(4, ("uaq_read_4: cmd %x reg %x index %x = %x\n", cmd, reg,
386 index, UGETDW(&val)));
387 return (UGETDW(&val)(*(u_int32_t *)(&val)));
388}
389
390int
391uaq_write_1(struct uaq_softc *sc, uint8_t cmd, uint16_t reg, uint16_t index,
392 uint32_t val)
393{
394 uint8_t temp;
395
396 DPRINTFN(4, ("uaq_write_1: cmd %x reg %x index %x: %x\n", cmd, reg,
397 index, val));
398 temp = val & 0xff;
399 return (uaq_write_mem(sc, cmd, reg, index, &temp, 1));
400}
401
402int
403uaq_write_2(struct uaq_softc *sc, uint8_t cmd, uint16_t reg, uint16_t index,
404 uint32_t val)
405{
406 uint16_t temp;
407
408 DPRINTFN(4, ("uaq_write_2: cmd %x reg %x index %x: %x\n", cmd, reg,
409 index, val));
410 USETW(&temp, val & 0xffff)(*(u_int16_t *)(&temp) = (val & 0xffff));
411 return (uaq_write_mem(sc, cmd, reg, index, &temp, 2));
412}
413
414int
415uaq_write_4(struct uaq_softc *sc, uint8_t cmd, uint16_t reg, uint16_t index,
416 uint32_t val)
417{
418 uint8_t temp[4];
419
420 DPRINTFN(4, ("uaq_write_4: cmd %x reg %x index %x: %x\n", cmd, reg,
421 index, val));
422 USETDW(temp, val)(*(u_int32_t *)(temp) = (val));
423 return (uaq_write_mem(sc, cmd, reg, index, &temp, 4));
424}
425
426int
427uaq_match(struct device *parent, void *match, void *aux)
428{
429 struct usb_attach_arg *uaa = aux;
430
431 if (uaa->iface == NULL((void *)0) || uaa->configno != 1)
432 return (UMATCH_NONE0);
433
434 return (usb_lookup(uaq_devs, uaa->vendor, uaa->product)usbd_match_device((const struct usb_devno *)(uaq_devs), sizeof
(uaq_devs) / sizeof ((uaq_devs)[0]), sizeof ((uaq_devs)[0]),
(uaa->vendor), (uaa->product))
!= NULL((void *)0) ?
435 UMATCH_VENDOR_PRODUCT_CONF_IFACE8 : UMATCH_NONE0);
436}
437
438void
439uaq_attach(struct device *parent, struct device *self, void *aux)
440{
441 struct uaq_softc *sc = (struct uaq_softc *)self;
442 struct usb_attach_arg *uaa = aux;
443 usb_interface_descriptor_t *id;
444 usb_endpoint_descriptor_t *ed;
445 struct ifnet *ifp;
446 int i, s;
447
448 sc->sc_udev = uaa->device;
449 sc->sc_iface = uaa->iface;
450
451 usb_init_task(&sc->sc_link_task, (void (*)(void *))uaq_link, sc,((&sc->sc_link_task)->fun = ((void (*)(void *))uaq_link
), (&sc->sc_link_task)->arg = (sc), (&sc->sc_link_task
)->type = (0), (&sc->sc_link_task)->state = 0x0)
452 USB_TASK_TYPE_GENERIC)((&sc->sc_link_task)->fun = ((void (*)(void *))uaq_link
), (&sc->sc_link_task)->arg = (sc), (&sc->sc_link_task
)->type = (0), (&sc->sc_link_task)->state = 0x0)
;
453
454 id = usbd_get_interface_descriptor(sc->sc_iface);
455
456 for (i = 0; i < id->bNumEndpoints; i++) {
457 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
458 if (!ed) {
459 printf("%s: couldn't get ep %d\n",
460 sc->sc_dev.dv_xname, i);
461 return;
462 }
463 if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80 &&
464 UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02) {
465 sc->sc_ed[UAQ_ENDPT_RX0] = ed->bEndpointAddress;
466 } else if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_OUT0x00 &&
467 UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02) {
468 sc->sc_ed[UAQ_ENDPT_TX1] = ed->bEndpointAddress;
469 sc->sc_out_frame_size = UGETW(ed->wMaxPacketSize)(*(u_int16_t *)(ed->wMaxPacketSize));
470 } else if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80 &&
471 UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_INTERRUPT0x03) {
472 sc->sc_ed[UAQ_ENDPT_INTR2] = ed->bEndpointAddress;
473 }
474 }
475
476 if ((sc->sc_ed[UAQ_ENDPT_RX0] == 0) ||
477 (sc->sc_ed[UAQ_ENDPT_TX1] == 0) ||
478 (sc->sc_ed[UAQ_ENDPT_INTR2] == 0)) {
479 printf("%s: missing one or more endpoints (%d, %d, %d)\n",
480 sc->sc_dev.dv_xname, sc->sc_ed[UAQ_ENDPT_RX0],
481 sc->sc_ed[UAQ_ENDPT_TX1], sc->sc_ed[UAQ_ENDPT_INTR2]);
482 return;
483 }
484
485 s = splnet()splraise(0x7);
486
487 printf("%s: ver %u.%u.%u", sc->sc_dev.dv_xname,
488 uaq_read_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_FW_VER_MAJOR0xDA, 1) & 0x7f,
489 uaq_read_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_FW_VER_MINOR0xDB, 1),
490 uaq_read_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_FW_VER_REV0xDC, 1));
491
492 uaq_read_mem(sc, UAQ_CMD_FLASH_PARAM0x20, 0, 0, &sc->sc_ac.ac_enaddr,
493 ETHER_ADDR_LEN6);
494 printf(", address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr));
495
496 ifp = &sc->sc_ac.ac_if;
497 ifp->if_softc = sc;
498 strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ16);
499 ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
500 ifp->if_ioctl = uaq_ioctl;
501 ifp->if_start = uaq_start;
502 ifp->if_watchdog = uaq_watchdog;
503
504 ifp->if_capabilitiesif_data.ifi_capabilities = IFCAP_VLAN_MTU0x00000010 | IFCAP_CSUM_IPv40x00000001 |
505 IFCAP_CSUM_TCPv40x00000002 | IFCAP_CSUM_UDPv40x00000004;
506
507#if NVLAN1 > 0
508 ifp->if_capabilitiesif_data.ifi_capabilities |= IFCAP_VLAN_HWTAGGING0x00000020;
509#endif
510
511 ifmedia_init(&sc->sc_ifmedia, IFM_IMASK0xff00000000000000ULL, uaq_ifmedia_upd,
512 uaq_ifmedia_sts);
513 uaq_add_media_types(sc);
514 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER0x0000000000000100ULL | IFM_AUTO0ULL, 0, NULL((void *)0));
515 ifmedia_set(&sc->sc_ifmedia, IFM_ETHER0x0000000000000100ULL | IFM_AUTO0ULL);
516 sc->sc_ifmedia.ifm_media = sc->sc_ifmedia.ifm_cur->ifm_media;
517
518 if_attach(ifp);
519 ether_ifattach(ifp);
520
521 splx(s)spllower(s);
522}
523
524int
525uaq_detach(struct device *self, int flags)
526{
527 struct uaq_softc *sc = (struct uaq_softc *)self;
528 struct ifnet *ifp = &sc->sc_ac.ac_if;
529 int s;
530
531 if (sc->sc_ep[UAQ_ENDPT_TX1] != NULL((void *)0))
532 usbd_abort_pipe(sc->sc_ep[UAQ_ENDPT_TX1]);
533 if (sc->sc_ep[UAQ_ENDPT_RX0] != NULL((void *)0))
534 usbd_abort_pipe(sc->sc_ep[UAQ_ENDPT_RX0]);
535 if (sc->sc_ep[UAQ_ENDPT_INTR2] != NULL((void *)0))
536 usbd_abort_pipe(sc->sc_ep[UAQ_ENDPT_INTR2]);
537
538 s = splusb()splraise(0x5);
539
540 usb_rem_task(sc->sc_udev, &sc->sc_link_task);
541
542 usb_detach_wait(&sc->sc_dev);
543
544 if (ifp->if_flags & IFF_RUNNING0x40)
545 uaq_stop(sc);
546
547 if (ifp->if_softc != NULL((void *)0)) {
548 ether_ifdetach(ifp);
549 if_detach(ifp);
550 }
551
552 splx(s)spllower(s);
553
554 return 0;
555}
556
557int
558uaq_ifmedia_upd(struct ifnet *ifp)
559{
560 struct uaq_softc *sc = ifp->if_softc;
561 struct ifmedia *ifm = &sc->sc_ifmedia;
562 int auto_adv;
563
564 if (IFM_TYPE(ifm->ifm_media)((ifm->ifm_media) & 0x000000000000ff00ULL) != IFM_ETHER0x0000000000000100ULL)
565 return (EINVAL22);
566
567 auto_adv = UAQ_PHY_ADV_100M(1 << 0) | UAQ_PHY_ADV_1G(1 << 1);
568 if (sc->sc_udev->speed == USB_SPEED_SUPER4)
569 auto_adv |= UAQ_PHY_ADV_2_5G(1 << 2) | UAQ_PHY_ADV_5G(1 << 3);
570
571 sc->sc_phy_cfg &= ~(UAQ_PHY_ADV_MASK0x0F);
572 sc->sc_phy_cfg |= UAQ_PHY_PAUSE(1 << 16) | UAQ_PHY_ASYM_PAUSE(1 << 17) |
573 UAQ_PHY_DOWNSHIFT(1 << 21) | (3 << UAQ_PHY_DSH_RETRY_SHIFT0x18);
574
575 switch (IFM_SUBTYPE(ifm->ifm_media)((ifm->ifm_media) & 0x00000000000000ffULL)) {
576 case IFM_AUTO0ULL:
577 sc->sc_phy_cfg |= auto_adv;
578 break;
579 case IFM_5000_T35:
580 sc->sc_phy_cfg |= UAQ_PHY_ADV_5G(1 << 3);
581 break;
582 case IFM_2500_T34:
583 sc->sc_phy_cfg |= UAQ_PHY_ADV_2_5G(1 << 2);
584 break;
585 case IFM_1000_T16:
586 sc->sc_phy_cfg |= UAQ_PHY_ADV_1G(1 << 1);
587 break;
588 case IFM_100_TX6:
589 sc->sc_phy_cfg |= UAQ_PHY_ADV_100M(1 << 0);
590 break;
591 default:
592 printf("%s: unsupported media type\n", sc->sc_dev.dv_xname);
593 return (EINVAL22);
594 }
595
596 DPRINTFN(1, ("%s: phy cfg %x\n", sc->sc_dev.dv_xname, sc->sc_phy_cfg));
597 uaq_write_4(sc, UAQ_CMD_PHY_OPS0x61, 0, 0, sc->sc_phy_cfg);
598 return (0);
599}
600
601void
602uaq_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
603{
604 struct uaq_softc *sc = ifp->if_softc;
605
606 ifmr->ifm_status = IFM_AVALID0x0000000000000001ULL;
607 if (sc->sc_link_speed > 0) {
608 ifmr->ifm_status |= IFM_ACTIVE0x0000000000000002ULL;
609 ifmr->ifm_active = IFM_ETHER0x0000000000000100ULL | IFM_FDX0x0000010000000000ULL;
610 switch (sc->sc_link_speed) {
611 case UAQ_STATUS_SPEED_5G0x000F:
612 ifmr->ifm_active |= IFM_5000_T35;
613 break;
614 case UAQ_STATUS_SPEED_2_5G0x0010:
615 ifmr->ifm_active |= IFM_2500_T34;
616 break;
617 case UAQ_STATUS_SPEED_1G0x0011:
618 ifmr->ifm_active |= IFM_1000_T16;
619 break;
620 case UAQ_STATUS_SPEED_100M0x0013:
621 ifmr->ifm_active |= IFM_100_TX6;
622 break;
623 default:
624 break;
625 }
626 }
627}
628
629void
630uaq_add_media_types(struct uaq_softc *sc)
631{
632 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER0x0000000000000100ULL | IFM_100_TX6, 0, NULL((void *)0));
633 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER0x0000000000000100ULL | IFM_100_TX6 | IFM_FDX0x0000010000000000ULL, 0,
634 NULL((void *)0));
635 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER0x0000000000000100ULL | IFM_1000_T16, 0, NULL((void *)0));
636 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER0x0000000000000100ULL | IFM_1000_T16 | IFM_FDX0x0000010000000000ULL, 0,
637 NULL((void *)0));
638 /* only add 2.5G and 5G if at super speed */
639 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER0x0000000000000100ULL | IFM_2500_T34, 0, NULL((void *)0));
640 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER0x0000000000000100ULL | IFM_2500_T34 | IFM_FDX0x0000010000000000ULL, 0,
641 NULL((void *)0));
642 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER0x0000000000000100ULL | IFM_5000_T35, 0, NULL((void *)0));
643 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER0x0000000000000100ULL | IFM_5000_T35 | IFM_FDX0x0000010000000000ULL, 0,
644 NULL((void *)0));
645}
646
647void
648uaq_iff(struct uaq_softc *sc)
649{
650 struct ifnet *ifp = &sc->sc_ac.ac_if;
651 struct ether_multi *enm;
652 struct ether_multistep step;
653 uint8_t filter[UAQ_MCAST_FILTER_SIZE8];
654 uint32_t hash;
655
656 if (usbd_is_dying(sc->sc_udev))
657 return;
658
659 sc->sc_rxctl &= ~(UAQ_SFR_RX_CTL_PRO0x0001 | UAQ_SFR_RX_CTL_AMALL0x0002 |
660 UAQ_SFR_RX_CTL_AM0x0010);
661 ifp->if_flags &= ~IFF_ALLMULTI0x200;
662
663 if (ifp->if_flags & IFF_PROMISC0x100) {
664 ifp->if_flags |= IFF_ALLMULTI0x200;
665 sc->sc_rxctl |= UAQ_SFR_RX_CTL_PRO0x0001;
666 } else if (sc->sc_ac.ac_multirangecnt > 0) {
667 ifp->if_flags |= IFF_ALLMULTI0x200;
668 sc->sc_rxctl |= UAQ_SFR_RX_CTL_AMALL0x0002;
669 } else {
670 sc->sc_rxctl |= UAQ_SFR_RX_CTL_AM0x0010;
671
672 bzero(filter, sizeof(filter))__builtin_bzero((filter), (sizeof(filter)));
673 ETHER_FIRST_MULTI(step, &sc->sc_ac, enm)do { (step).e_enm = ((&(&sc->sc_ac)->ac_multiaddrs
)->lh_first); do { if ((((enm)) = ((step)).e_enm) != ((void
*)0)) ((step)).e_enm = ((((enm)))->enm_list.le_next); } while
( 0); } while ( 0)
;
674 while (enm != NULL((void *)0)) {
675 hash = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN6)
676 >> 26;
677 filter[hash >> 3] |= (1 << (hash & 7));
678 ETHER_NEXT_MULTI(step, enm)do { if (((enm) = (step).e_enm) != ((void *)0)) (step).e_enm =
(((enm))->enm_list.le_next); } while ( 0)
;
679 }
680
681 uaq_write_mem(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_MCAST_FILTER0x16,
682 UAQ_MCAST_FILTER_SIZE8, filter, UAQ_MCAST_FILTER_SIZE8);
683 }
684
685 DPRINTFN(1, ("%s: rxctl = %x\n", sc->sc_dev.dv_xname, sc->sc_rxctl));
686 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_RX_CTL0x0B, 2, sc->sc_rxctl);
687}
688
689void
690uaq_reset(struct uaq_softc *sc)
691{
692 uint8_t mode;
693
694 sc->sc_phy_cfg = UAQ_PHY_POWER_EN(1 << 19);
695 uaq_write_4(sc, UAQ_CMD_PHY_OPS0x61, 0, 0, sc->sc_phy_cfg);
696
697 uaq_write_mem(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_NODE_ID0x10, 0,
698 sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN6);
699 uaq_write_mem(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_NODE_ID0x10, ETHER_ADDR_LEN6,
700 sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN6);
701
702 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_BM_INT_MASK0x41, 0, 0xff);
703 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_SWP_CTRL0xB1, 0, 0);
704
705 mode = uaq_read_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_MONITOR_MODE0x24, 1);
8
Calling 'uaq_read_1'
706 mode &= ~(UAQ_SFR_MONITOR_MODE_EPHYRW0x01 | UAQ_SFR_MONITOR_MODE_RWLC0x02 |
707 UAQ_SFR_MONITOR_MODE_RWMP0x04 | UAQ_SFR_MONITOR_MODE_RWWF0x08 |
708 UAQ_SFR_MONITOR_MODE_RW_FLAG0x10);
709 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_MONITOR_MODE0x24, 1, mode);
710
711 sc->sc_link_status = 0;
712 sc->sc_link_speed = 0;
713}
714
715void
716uaq_init(void *xsc)
717{
718 struct uaq_softc *sc = xsc;
719 struct uaq_chain *c;
720 struct ifnet *ifp = &sc->sc_ac.ac_if;
721 usbd_status err;
722 int s, i;
723
724 s = splnet()splraise(0x7);
725
726 uaq_stop(sc);
727
728 uaq_reset(sc);
7
Calling 'uaq_reset'
729
730 if (uaq_xfer_list_init(sc, sc->sc_cdata.uaq_rx_chain,
731 UAQ_RX_BUFSZ32768, UAQ_RX_LIST_CNT1) == ENOBUFS55) {
732 printf("%s: rx list init failed\n", sc->sc_dev.dv_xname);
733 splx(s)spllower(s);
734 return;
735 }
736
737 if (uaq_xfer_list_init(sc, sc->sc_cdata.uaq_tx_chain,
738 UAQ_TX_BUFSZ16384, UAQ_TX_LIST_CNT1) == ENOBUFS55) {
739 printf("%s: tx list init failed\n", sc->sc_dev.dv_xname);
740 splx(s)spllower(s);
741 return;
742 }
743
744 SLIST_INIT(&sc->sc_cdata.uaq_tx_free){ ((&sc->sc_cdata.uaq_tx_free)->slh_first) = ((void
*)0); }
;
745 for (i = 0; i < UAQ_TX_LIST_CNT1; i++)
746 SLIST_INSERT_HEAD(&sc->sc_cdata.uaq_tx_free,do { (&sc->sc_cdata.uaq_tx_chain[i])->uc_list.sle_next
= (&sc->sc_cdata.uaq_tx_free)->slh_first; (&sc
->sc_cdata.uaq_tx_free)->slh_first = (&sc->sc_cdata
.uaq_tx_chain[i]); } while (0)
747 &sc->sc_cdata.uaq_tx_chain[i], uc_list)do { (&sc->sc_cdata.uaq_tx_chain[i])->uc_list.sle_next
= (&sc->sc_cdata.uaq_tx_free)->slh_first; (&sc
->sc_cdata.uaq_tx_free)->slh_first = (&sc->sc_cdata
.uaq_tx_chain[i]); } while (0)
;
748
749 err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UAQ_ENDPT_RX0],
750 USBD_EXCLUSIVE_USE0x01, &sc->sc_ep[UAQ_ENDPT_RX0]);
751 if (err) {
752 printf("%s: open rx pipe failed: %s\n",
753 sc->sc_dev.dv_xname, usbd_errstr(err));
754 splx(s)spllower(s);
755 return;
756 }
757
758 err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UAQ_ENDPT_TX1],
759 USBD_EXCLUSIVE_USE0x01, &sc->sc_ep[UAQ_ENDPT_TX1]);
760 if (err) {
761 printf("%s: open tx pipe failed: %s\n",
762 sc->sc_dev.dv_xname, usbd_errstr(err));
763 splx(s)spllower(s);
764 return;
765 }
766
767 for (i = 0; i < UAQ_RX_LIST_CNT1; i++) {
768 c = &sc->sc_cdata.uaq_rx_chain[i];
769 usbd_setup_xfer(c->uc_xfer, sc->sc_ep[UAQ_ENDPT_RX0],
770 c, c->uc_buf, c->uc_bufmax,
771 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
772 USBD_NO_TIMEOUT0, uaq_rxeof);
773 usbd_transfer(c->uc_xfer);
774 }
775
776 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ed[UAQ_ENDPT_INTR2],
777 0, &sc->sc_ep[UAQ_ENDPT_INTR2], sc,
778 &sc->sc_link_status, sizeof(sc->sc_link_status), uaq_intr,
779 USBD_DEFAULT_INTERVAL(-1));
780 if (err) {
781 printf("%s: couldn't open interrupt pipe\n",
782 sc->sc_dev.dv_xname);
783 return;
784 }
785
786 uaq_iff(sc);
787
788 uaq_ifmedia_upd(ifp);
789
790 ifp->if_flags |= IFF_RUNNING0x40;
791 ifq_clr_oactive(&ifp->if_snd);
792
793 splx(s)spllower(s);
794}
795
796int
797uaq_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
798{
799 struct uaq_softc *sc = ifp->if_softc;
800 struct ifreq *ifr = (struct ifreq *)data;
801 int s, error = 0;
802
803 s = splnet()splraise(0x7);
804
805 switch (cmd) {
1
Control jumps to 'case 2149607696:' at line 812
806 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
807 ifp->if_flags |= IFF_UP0x1;
808 if (!(ifp->if_flags & IFF_RUNNING0x40))
809 uaq_init(sc);
810 break;
811
812 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
813 if (ifp->if_flags & IFF_UP0x1) {
2
Assuming the condition is true
3
Taking true branch
814 if (ifp->if_flags & IFF_RUNNING0x40)
4
Assuming the condition is false
5
Taking false branch
815 error = ENETRESET52;
816 else
817 uaq_init(sc);
6
Calling 'uaq_init'
818 } else {
819 if (ifp->if_flags & IFF_RUNNING0x40)
820 uaq_stop(sc);
821 }
822 break;
823
824 case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
:
825 case SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((55)))
:
826 error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd);
827 break;
828
829 default:
830 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
831 }
832
833 if (error == ENETRESET52) {
834 if (ifp->if_flags & IFF_RUNNING0x40)
835 uaq_iff(sc);
836 error = 0;
837 }
838
839 splx(s)spllower(s);
840
841 return (error);
842}
843
844int
845uaq_xfer_list_init(struct uaq_softc *sc, struct uaq_chain *ch,
846 uint32_t bufsize, int listlen)
847{
848 struct uaq_chain *c;
849 int i;
850
851 for (i = 0; i < listlen; i++) {
852 c = &ch[i];
853 c->uc_sc = sc;
854 c->uc_idx = i;
855 c->uc_buflen = 0;
856 c->uc_bufmax = bufsize;
857 c->uc_cnt = 0;
858 if (c->uc_xfer == NULL((void *)0)) {
859 c->uc_xfer = usbd_alloc_xfer(sc->sc_udev);
860 if (c->uc_xfer == NULL((void *)0))
861 return (ENOBUFS55);
862
863 c->uc_buf = usbd_alloc_buffer(c->uc_xfer, c->uc_bufmax);
864 if (c->uc_buf == NULL((void *)0)) {
865 usbd_free_xfer(c->uc_xfer);
866 c->uc_xfer = NULL((void *)0);
867 return (ENOBUFS55);
868 }
869 }
870 }
871
872 return (0);
873}
874
875void
876uaq_xfer_list_free(struct uaq_softc *sc, struct uaq_chain *ch, int listlen)
877{
878 int i;
879
880 for (i = 0; i < listlen; i++) {
881 if (ch[i].uc_buf != NULL((void *)0)) {
882 ch[i].uc_buf = NULL((void *)0);
883 }
884 ch[i].uc_cnt = 0;
885 if (ch[i].uc_xfer != NULL((void *)0)) {
886 usbd_free_xfer(ch[i].uc_xfer);
887 ch[i].uc_xfer = NULL((void *)0);
888 }
889 }
890}
891
892void
893uaq_stop(struct uaq_softc *sc)
894{
895 struct uaq_cdata *cd;
896 struct ifnet *ifp;
897 usbd_status err;
898
899 ifp = &sc->sc_ac.ac_if;
900 ifp->if_timer = 0;
901 ifp->if_flags &= ~IFF_RUNNING0x40;
902 ifq_clr_oactive(&ifp->if_snd);
903
904 sc->sc_link_status = 0;
905 sc->sc_link_speed = 0;
906
907 if (sc->sc_ep[UAQ_ENDPT_RX0] != NULL((void *)0)) {
908 err = usbd_close_pipe(sc->sc_ep[UAQ_ENDPT_RX0]);
909 if (err) {
910 printf("%s: close rx pipe failed: %s\n",
911 sc->sc_dev.dv_xname, usbd_errstr(err));
912 }
913 sc->sc_ep[UAQ_ENDPT_RX0] = NULL((void *)0);
914 }
915
916 if (sc->sc_ep[UAQ_ENDPT_TX1] != NULL((void *)0)) {
917 err = usbd_close_pipe(sc->sc_ep[UAQ_ENDPT_TX1]);
918 if (err) {
919 printf("%s: close tx pipe failed: %s\n",
920 sc->sc_dev.dv_xname, usbd_errstr(err));
921 }
922 sc->sc_ep[UAQ_ENDPT_TX1] = NULL((void *)0);
923 }
924
925 if (sc->sc_ep[UAQ_ENDPT_INTR2] != NULL((void *)0)) {
926 err = usbd_close_pipe(sc->sc_ep[UAQ_ENDPT_INTR2]);
927 if (err) {
928 printf("%s: close intr pipe failed: %s\n",
929 sc->sc_dev.dv_xname, usbd_errstr(err));
930 }
931 sc->sc_ep[UAQ_ENDPT_INTR2] = NULL((void *)0);
932 }
933
934 cd = &sc->sc_cdata;
935 uaq_xfer_list_free(sc, cd->uaq_rx_chain, UAQ_RX_LIST_CNT1);
936 uaq_xfer_list_free(sc, cd->uaq_tx_chain, UAQ_TX_LIST_CNT1);
937}
938
939void
940uaq_link(struct uaq_softc *sc)
941{
942 if (sc->sc_link_speed > 0) {
943 uint8_t resend[3] = { 0, 0xf8, 7 };
944 uint8_t qctrl[5] = { 7, 0x00, 0x01, 0x1e, 0xff };
945 uint8_t ipg = 0;
946
947 switch (sc->sc_link_speed) {
948 case UAQ_STATUS_SPEED_100M0x0013:
949 resend[1] = 0xfb;
950 resend[2] = 0x4;
951 break;
952
953 case UAQ_STATUS_SPEED_5G0x000F:
954 ipg = 5;
955 break;
956 }
957
958 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_IPG_00x0D, 1, ipg);
959
960 uaq_write_mem(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_TX_PAUSE_RESEND_T0xB2,
961 3, resend, 3);
962 uaq_write_mem(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_RX_BULKIN_QCTRL0x2E,
963 5, qctrl, 5);
964 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_PAUSE_WATERLVL_LOW0x54,
965 2, 0x0810);
966
967 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_BMRX_DMA_CTRL0x43, 1,
968 0);
969 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_BMTX_DMA_CTRL0x46, 1,
970 0);
971 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_ARC_CTRL0x9E, 1, 0);
972
973 sc->sc_rxctl = UAQ_SFR_RX_CTL_IPE0x0200 | UAQ_SFR_RX_CTL_AB0x0008;
974 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_RX_CTL0x0B, 2,
975 sc->sc_rxctl);
976
977 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_ETH_MAC_PATH0xB7, 1,
978 UAQ_SFR_RX_PATH_READY0x01);
979
980 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_BULK_OUT_CTRL0xB9, 1,
981 UAQ_SFR_BULK_OUT_EFF_EN0x02);
982
983 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_MEDIUM_STATUS_MODE0x22,
984 2, 0);
985 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_MEDIUM_STATUS_MODE0x22,
986 2, UAQ_SFR_MEDIUM_XGMIIMODE0x0001 | UAQ_SFR_MEDIUM_FULL_DUPLEX0x0002 |
987 UAQ_SFR_MEDIUM_RECEIVE_EN0x0100 | UAQ_SFR_MEDIUM_RXFLOW_CTRLEN0x0010 |
988 UAQ_SFR_MEDIUM_TXFLOW_CTRLEN0x0020); /* JUMBO_EN */
989
990 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_RXCOE_CTL0x34, 1,
991 UAQ_SFR_RXCOE_IP0x01 | UAQ_SFR_RXCOE_TCP0x02 | UAQ_SFR_RXCOE_UDP0x04 |
992 UAQ_SFR_RXCOE_TCPV60x20 | UAQ_SFR_RXCOE_UDPV60x40);
993 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_TXCOE_CTL0x35, 1,
994 UAQ_SFR_TXCOE_IP0x01 | UAQ_SFR_TXCOE_TCP0x02 | UAQ_SFR_TXCOE_UDP0x04 |
995 UAQ_SFR_TXCOE_TCPV60x20 | UAQ_SFR_TXCOE_UDPV60x40);
996
997 sc->sc_rxctl |= UAQ_SFR_RX_CTL_START0x0080;
998 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_RX_CTL0x0B, 2,
999 sc->sc_rxctl);
1000 } else {
1001 uint16_t mode;
1002
1003 mode = uaq_read_2(sc, UAQ_CMD_ACCESS_MAC0x01,
1004 UAQ_SFR_MEDIUM_STATUS_MODE0x22, 2);
1005 mode &= ~UAQ_SFR_MEDIUM_RECEIVE_EN0x0100;
1006 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_MEDIUM_STATUS_MODE0x22,
1007 2, mode);
1008
1009 sc->sc_rxctl &= ~UAQ_SFR_RX_CTL_START0x0080;
1010 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_RX_CTL0x0B, 2,
1011 sc->sc_rxctl);
1012
1013 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_BULK_OUT_CTRL0xB9, 1,
1014 UAQ_SFR_BULK_OUT_FLUSH_EN0x01 | UAQ_SFR_BULK_OUT_EFF_EN0x02);
1015
1016 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_BULK_OUT_CTRL0xB9, 1,
1017 UAQ_SFR_BULK_OUT_EFF_EN0x02);
1018 }
1019}
1020
1021void
1022uaq_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
1023{
1024 struct uaq_softc *sc = priv;
1025 struct ifnet *ifp = &sc->sc_ac.ac_if;
1026 uint64_t linkstatus;
1027 uint64_t baudrate;
1028 int link_state;
1029
1030 if (status == USBD_CANCELLED)
1031 return;
1032
1033 if (status != USBD_NORMAL_COMPLETION) {
1034 DPRINTFN(2, ("uaq_intr: status=%d\n", status));
1035 if (status == USBD_STALLED)
1036 usbd_clear_endpoint_stall_async(
1037 sc->sc_ep[UAQ_ENDPT_INTR2]);
1038 return;
1039 }
1040
1041 linkstatus = letoh64(sc->sc_link_status)((__uint64_t)(sc->sc_link_status));
1042 DPRINTFN(1, ("uaq_intr: link status %llx\n", linkstatus));
1043
1044 if (linkstatus & UAQ_STATUS_LINK0x8000) {
1045 link_state = LINK_STATE_FULL_DUPLEX6;
1046 sc->sc_link_speed = (linkstatus & UAQ_STATUS_SPEED_MASK0x7F00)
1047 >> UAQ_STATUS_SPEED_SHIFT8;
1048 switch (sc->sc_link_speed) {
1049 case UAQ_STATUS_SPEED_5G0x000F:
1050 baudrate = IF_Gbps(5)((((((5) * 1000ULL) * 1000ULL) * 1000ULL)));
1051 break;
1052 case UAQ_STATUS_SPEED_2_5G0x0010:
1053 baudrate = IF_Mbps(2500)((((2500) * 1000ULL) * 1000ULL));
1054 break;
1055 case UAQ_STATUS_SPEED_1G0x0011:
1056 baudrate = IF_Gbps(1)((((((1) * 1000ULL) * 1000ULL) * 1000ULL)));
1057 break;
1058 case UAQ_STATUS_SPEED_100M0x0013:
1059 baudrate = IF_Mbps(100)((((100) * 1000ULL) * 1000ULL));
1060 break;
1061 default:
1062 baudrate = 0;
1063 break;
1064 }
1065
1066 ifp->if_baudrateif_data.ifi_baudrate = baudrate;
1067 } else {
1068 link_state = LINK_STATE_DOWN2;
1069 sc->sc_link_speed = 0;
1070 }
1071
1072 if (link_state != ifp->if_link_stateif_data.ifi_link_state) {
1073 ifp->if_link_stateif_data.ifi_link_state = link_state;
1074 if_link_state_change(ifp);
1075 usb_add_task(sc->sc_udev, &sc->sc_link_task);
1076 }
1077}
1078
1079void
1080uaq_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1081{
1082 struct uaq_chain *c = (struct uaq_chain *)priv;
1083 struct uaq_softc *sc = c->uc_sc;
1084 struct ifnet *ifp = &sc->sc_ac.ac_if;
1085 uint8_t *buf;
1086 uint64_t *pdesc;
1087 uint64_t desc;
1088 uint32_t total_len;
1089 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
1090 struct mbuf *m;
1091 int pktlen, s;
1092 int count, offset;
1093
1094 if (usbd_is_dying(sc->sc_udev))
1095 return;
1096
1097 if (!(ifp->if_flags & IFF_RUNNING0x40))
1098 return;
1099
1100 if (status != USBD_NORMAL_COMPLETION) {
1101 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1102 return;
1103 if (usbd_ratecheck(&sc->sc_rx_notice)) {
1104 printf("%s: usb errors on rx: %s\n",
1105 sc->sc_dev.dv_xname, usbd_errstr(status));
1106 }
1107 if (status == USBD_STALLED)
1108 usbd_clear_endpoint_stall_async(
1109 sc->sc_ep[UAQ_ENDPT_RX0]);
1110 goto done;
1111 }
1112
1113 usbd_get_xfer_status(xfer, NULL((void *)0), (void **)&buf, &total_len, NULL((void *)0));
1114 DPRINTFN(3, ("received %d bytes\n", total_len));
1115 if ((total_len & 7) != 0) {
1116 printf("%s: weird rx transfer length %d\n",
1117 sc->sc_dev.dv_xname, total_len);
1118 goto done;
1119 }
1120
1121 pdesc = (uint64_t *)(buf + (total_len - sizeof(desc)));
1122 desc = lemtoh64(pdesc)((__uint64_t)(*(__uint64_t *)(pdesc)));
1123
1124 count = desc & UAQ_RX_HDR_COUNT_MASK0x1FFF;
1125 if (count == 0)
1126 goto done;
1127
1128 /* get offset of packet headers */
1129 offset = total_len - ((count + 1) * sizeof(desc));
1130 if (offset != ((desc & UAQ_RX_HDR_OFFSET_MASK0xFFFFE000) >>
1131 UAQ_RX_HDR_OFFSET_SHIFT13)) {
1132 printf("%s: offset mismatch, got %d expected %lld\n",
1133 sc->sc_dev.dv_xname, offset,
1134 desc >> UAQ_RX_HDR_OFFSET_SHIFT13);
1135 goto done;
1136 }
1137 if (offset < 0 || offset > total_len) {
1138 printf("%s: offset %d outside buffer (%d)\n",
1139 sc->sc_dev.dv_xname, offset, total_len);
1140 goto done;
1141 }
1142
1143 pdesc = (uint64_t *)(buf + offset);
1144 total_len = offset;
1145
1146 while (count-- > 0) {
1147 desc = lemtoh64(pdesc)((__uint64_t)(*(__uint64_t *)(pdesc)));
1148 pdesc++;
1149
1150 pktlen = (desc & UAQ_RX_PKT_LEN_MASK0x7FFF0000) >> UAQ_RX_PKT_LEN_SHIFT16;
1151 if (pktlen > total_len) {
1152 DPRINTFN(2, ("not enough bytes for this packet\n"));
1153 ifp->if_ierrorsif_data.ifi_ierrors++;
1154 goto done;
1155 }
1156
1157 m = m_devget(buf + 2, pktlen - 2, ETHER_ALIGN2);
1158 if (m == NULL((void *)0)) {
1159 DPRINTFN(2, ("m_devget failed for this packet\n"));
1160 ifp->if_ierrorsif_data.ifi_ierrors++;
1161 goto done;
1162 }
1163
1164 if ((desc & UAQ_RX_PKT_L3_ERR0x02) == 0)
1165 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK0x0008;
1166
1167 if ((desc & UAQ_RX_PKT_L4_ERR0x01) == 0)
1168 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK0x0020 |
1169 M_UDP_CSUM_IN_OK0x0080;
1170
1171#if NVLAN1 > 0
1172 if (desc & UAQ_RX_PKT_VLAN0x400) {
1173 m->m_pkthdrM_dat.MH.MH_pkthdr.ether_vtag = (desc >> UAQ_RX_PKT_VLAN_SHIFT32) &
1174 0xfff;
1175 m->m_flagsm_hdr.mh_flags |= M_VLANTAG0x0020;
1176 }
1177#endif
1178 ml_enqueue(&ml, m);
1179
1180 total_len -= roundup(pktlen, UAQ_RX_BUF_ALIGN)((((pktlen)+((8)-1))/(8))*(8));
1181 buf += roundup(pktlen, UAQ_RX_BUF_ALIGN)((((pktlen)+((8)-1))/(8))*(8));
1182 }
1183
1184done:
1185 s = splnet()splraise(0x7);
1186 if_input(ifp, &ml);
1187 splx(s)spllower(s);
1188 memset(c->uc_buf, 0, UAQ_RX_BUFSZ)__builtin_memset((c->uc_buf), (0), (32768));
1189
1190 usbd_setup_xfer(xfer, sc->sc_ep[UAQ_ENDPT_RX0], c, c->uc_buf,
1191 UAQ_RX_BUFSZ32768, USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
1192 USBD_NO_TIMEOUT0, uaq_rxeof);
1193 usbd_transfer(xfer);
1194}
1195
1196
1197void
1198uaq_watchdog(struct ifnet *ifp)
1199{
1200 struct uaq_softc *sc = ifp->if_softc;
1201 struct uaq_chain *c;
1202 usbd_status err;
1203 int i, s;
1204
1205 ifp->if_timer = 0;
1206
1207 if (usbd_is_dying(sc->sc_udev))
1208 return;
1209
1210 if ((ifp->if_flags & (IFF_RUNNING0x40|IFF_UP0x1)) != (IFF_RUNNING0x40|IFF_UP0x1))
1211 return;
1212
1213 sc = ifp->if_softc;
1214 s = splnet()splraise(0x7);
1215
1216 ifp->if_oerrorsif_data.ifi_oerrors++;
1217 DPRINTF(("%s: watchdog timeout\n", sc->sc_dev.dv_xname));
1218
1219 for (i = 0; i < UAQ_TX_LIST_CNT1; i++) {
1220 c = &sc->sc_cdata.uaq_tx_chain[i];
1221 if (c->uc_cnt > 0) {
1222 usbd_get_xfer_status(c->uc_xfer, NULL((void *)0), NULL((void *)0), NULL((void *)0),
1223 &err);
1224 uaq_txeof(c->uc_xfer, c, err);
1225 }
1226 }
1227
1228 if (ifq_is_oactive(&ifp->if_snd))
1229 ifq_restart(&ifp->if_snd);
1230 splx(s)spllower(s);
1231}
1232
1233void
1234uaq_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1235{
1236 struct uaq_softc *sc;
1237 struct uaq_chain *c;
1238 struct ifnet *ifp;
1239 int s;
1240
1241 c = priv;
1242 sc = c->uc_sc;
1243 ifp = &sc->sc_ac.ac_if;
1244
1245 if (usbd_is_dying(sc->sc_udev))
1246 return;
1247
1248 if (status != USBD_NORMAL_COMPLETION)
1249 DPRINTF(("%s: %s uc_idx=%u : %s\n", sc->sc_dev.dv_xname,
1250 __func__, c->uc_idx, usbd_errstr(status)));
1251 else
1252 DPRINTF(("%s: txeof\n", sc->sc_dev.dv_xname));
1253
1254 s = splnet()splraise(0x7);
1255
1256 c->uc_cnt = 0;
1257 c->uc_buflen = 0;
1258
1259 SLIST_INSERT_HEAD(&sc->sc_cdata.uaq_tx_free, c, uc_list)do { (c)->uc_list.sle_next = (&sc->sc_cdata.uaq_tx_free
)->slh_first; (&sc->sc_cdata.uaq_tx_free)->slh_first
= (c); } while (0)
;
1260
1261 if (status != USBD_NORMAL_COMPLETION) {
1262 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1263 splx(s)spllower(s);
1264 return;
1265 }
1266
1267 ifp->if_oerrorsif_data.ifi_oerrors++;
1268 printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname,
1269 usbd_errstr(status));
1270
1271 if (status == USBD_STALLED)
1272 usbd_clear_endpoint_stall_async(
1273 sc->sc_ep[UAQ_ENDPT_TX1]);
1274 splx(s)spllower(s);
1275 return;
1276 }
1277
1278 ifp->if_timer = 0;
1279 if (ifq_is_oactive(&ifp->if_snd))
1280 ifq_restart(&ifp->if_snd);
1281 splx(s)spllower(s);
1282}
1283
1284void
1285uaq_start(struct ifnet *ifp)
1286{
1287 struct uaq_softc *sc = ifp->if_softc;
1288 struct uaq_cdata *cd = &sc->sc_cdata;
1289 struct uaq_chain *c;
1290 struct mbuf *m = NULL((void *)0);
1291 int s, mlen;
1292
1293 if ((sc->sc_link_speed == 0) ||
1294 (ifp->if_flags & (IFF_RUNNING0x40|IFF_UP0x1)) !=
1295 (IFF_RUNNING0x40|IFF_UP0x1)) {
1296 return;
1297 }
1298
1299 s = splnet()splraise(0x7);
1300
1301 c = SLIST_FIRST(&cd->uaq_tx_free)((&cd->uaq_tx_free)->slh_first);
1302 while (c != NULL((void *)0)) {
1303 m = ifq_deq_begin(&ifp->if_snd);
1304 if (m == NULL((void *)0))
1305 break;
1306
1307 mlen = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1308
1309 /* Discard packet larger than buffer. */
1310 if (mlen + sizeof(uint64_t) >= c->uc_bufmax) {
1311 ifq_deq_commit(&ifp->if_snd, m);
1312 m_freem(m);
1313 ifp->if_oerrorsif_data.ifi_oerrors++;
1314 continue;
1315 }
1316
1317 /* Append packet to current buffer. */
1318 mlen = uaq_encap_txpkt(sc, m, c->uc_buf + c->uc_buflen,
1319 c->uc_bufmax - c->uc_buflen);
1320 if (mlen <= 0) {
1321 ifq_deq_rollback(&ifp->if_snd, m);
1322 break;
1323 }
1324
1325 ifq_deq_commit(&ifp->if_snd, m);
1326 c->uc_cnt += 1;
1327 c->uc_buflen += mlen;
1328
1329#if NBPFILTER1 > 0
1330 if (ifp->if_bpf)
1331 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
1332#endif
1333
1334 m_freem(m);
1335 }
1336
1337 if (c != NULL((void *)0)) {
1338 /* Send current buffer unless empty */
1339 if (c->uc_buflen > 0 && c->uc_cnt > 0) {
1340 SLIST_REMOVE_HEAD(&cd->uaq_tx_free, uc_list)do { (&cd->uaq_tx_free)->slh_first = (&cd->uaq_tx_free
)->slh_first->uc_list.sle_next; } while (0)
;
1341 if (uaq_encap_xfer(sc, c)) {
1342 SLIST_INSERT_HEAD(&cd->uaq_tx_free, c,do { (c)->uc_list.sle_next = (&cd->uaq_tx_free)->
slh_first; (&cd->uaq_tx_free)->slh_first = (c); } while
(0)
1343 uc_list)do { (c)->uc_list.sle_next = (&cd->uaq_tx_free)->
slh_first; (&cd->uaq_tx_free)->slh_first = (c); } while
(0)
;
1344 }
1345 c = SLIST_FIRST(&cd->uaq_tx_free)((&cd->uaq_tx_free)->slh_first);
1346
1347 ifp->if_timer = 5;
1348 if (c == NULL((void *)0))
1349 ifq_set_oactive(&ifp->if_snd);
1350 }
1351 }
1352
1353 splx(s)spllower(s);
1354}
1355
1356int
1357uaq_encap_txpkt(struct uaq_softc *sc, struct mbuf *m, char *buf,
1358 uint32_t maxlen)
1359{
1360 uint64_t desc;
1361 int padded;
1362
1363 desc = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1364 padded = roundup(m->m_pkthdr.len, UAQ_TX_BUF_ALIGN)((((m->M_dat.MH.MH_pkthdr.len)+((8)-1))/(8))*(8));
1365 if (((padded + sizeof(desc)) % sc->sc_out_frame_size) == 0) {
1366 desc |= UAQ_TX_PKT_DROP_PADD(1 << 28);
1367 padded += 8;
1368 }
1369
1370 if (padded + sizeof(desc) > maxlen)
1371 return (-1);
1372
1373#if NVLAN1 > 0
1374 if (m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020)
1375 desc |= (((uint64_t)m->m_pkthdrM_dat.MH.MH_pkthdr.ether_vtag) <<
1376 UAQ_TX_PKT_VLAN_SHIFT0x30) | UAQ_TX_PKT_VLAN(1 << 29);
1377#endif
1378
1379 htolem64((uint64_t *)buf, desc)(*(__uint64_t *)((uint64_t *)buf) = ((__uint64_t)(desc)));
1380 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, buf + sizeof(desc));
1381 return (padded + sizeof(desc));
1382}
1383
1384int
1385uaq_encap_xfer(struct uaq_softc *sc, struct uaq_chain *c)
1386{
1387 usbd_status err;
1388
1389 usbd_setup_xfer(c->uc_xfer, sc->sc_ep[UAQ_ENDPT_TX1], c, c->uc_buf,
1390 c->uc_buflen, USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01, 10000,
1391 uaq_txeof);
1392
1393 err = usbd_transfer(c->uc_xfer);
1394 if (err != USBD_IN_PROGRESS) {
1395 c->uc_cnt = 0;
1396 c->uc_buflen = 0;
1397 uaq_stop(sc);
1398 return (EIO5);
1399 }
1400
1401 return (0);
1402}