Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name if_uaq.c -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 -ffp-contract=on -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 -target-feature +retpoline-external-thunk -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/llvm16/lib/clang/16 -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/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -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/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -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/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -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 SUSPEND -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 -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 -fcf-protection=branch -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 /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/usb/if_uaq.c
1/* $OpenBSD: if_uaq.c,v 1.5 2022/09/01 17:07:09 mlarkin 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_BUFSZ(62 * 1024) (62 * 1024)
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))
4
Assuming the condition is true
5
Taking true branch
320 return 0;
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));
3
Calling 'uaq_ctl'
6
Returning from 'uaq_ctl'
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;
360
361 uaq_read_mem(sc, cmd, reg, index, &val, 1);
362 DPRINTFN(4, ("uaq_read_1: cmd %x reg %x index %x = %x\n", cmd, reg,
363 index, val));
364 return (val);
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;
1
'val' declared without an initial value
383
384 uaq_read_mem(sc, cmd, reg, index, &val, 4);
2
Calling 'uaq_read_mem'
7
Returning from 'uaq_read_mem'
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)));
8
Undefined or garbage value returned to caller
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(0x4);
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(0x2);
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);
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(0x4);
725
726 uaq_stop(sc);
727
728 uaq_reset(sc);
729
730 if (uaq_xfer_list_init(sc, sc->sc_cdata.uaq_rx_chain,
731 UAQ_RX_BUFSZ(62 * 1024), 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 splx(s)spllower(s);
784 return;
785 }
786
787 uaq_iff(sc);
788
789 uaq_ifmedia_upd(ifp);
790
791 ifp->if_flags |= IFF_RUNNING0x40;
792 ifq_clr_oactive(&ifp->if_snd);
793
794 splx(s)spllower(s);
795}
796
797int
798uaq_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
799{
800 struct uaq_softc *sc = ifp->if_softc;
801 struct ifreq *ifr = (struct ifreq *)data;
802 int s, error = 0;
803
804 s = splnet()splraise(0x4);
805
806 switch (cmd) {
807 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
808 ifp->if_flags |= IFF_UP0x1;
809 if (!(ifp->if_flags & IFF_RUNNING0x40))
810 uaq_init(sc);
811 break;
812
813 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
814 if (ifp->if_flags & IFF_UP0x1) {
815 if (ifp->if_flags & IFF_RUNNING0x40)
816 error = ENETRESET52;
817 else
818 uaq_init(sc);
819 } else {
820 if (ifp->if_flags & IFF_RUNNING0x40)
821 uaq_stop(sc);
822 }
823 break;
824
825 case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
:
826 case SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((55)))
:
827 error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd);
828 break;
829
830 default:
831 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
832 }
833
834 if (error == ENETRESET52) {
835 if (ifp->if_flags & IFF_RUNNING0x40)
836 uaq_iff(sc);
837 error = 0;
838 }
839
840 splx(s)spllower(s);
841
842 return (error);
843}
844
845int
846uaq_xfer_list_init(struct uaq_softc *sc, struct uaq_chain *ch,
847 uint32_t bufsize, int listlen)
848{
849 struct uaq_chain *c;
850 int i;
851
852 for (i = 0; i < listlen; i++) {
853 c = &ch[i];
854 c->uc_sc = sc;
855 c->uc_idx = i;
856 c->uc_buflen = 0;
857 c->uc_bufmax = bufsize;
858 c->uc_cnt = 0;
859 if (c->uc_xfer == NULL((void *)0)) {
860 c->uc_xfer = usbd_alloc_xfer(sc->sc_udev);
861 if (c->uc_xfer == NULL((void *)0))
862 return (ENOBUFS55);
863
864 c->uc_buf = usbd_alloc_buffer(c->uc_xfer, c->uc_bufmax);
865 if (c->uc_buf == NULL((void *)0)) {
866 usbd_free_xfer(c->uc_xfer);
867 c->uc_xfer = NULL((void *)0);
868 return (ENOBUFS55);
869 }
870 }
871 }
872
873 return (0);
874}
875
876void
877uaq_xfer_list_free(struct uaq_softc *sc, struct uaq_chain *ch, int listlen)
878{
879 int i;
880
881 for (i = 0; i < listlen; i++) {
882 if (ch[i].uc_buf != NULL((void *)0)) {
883 ch[i].uc_buf = NULL((void *)0);
884 }
885 ch[i].uc_cnt = 0;
886 if (ch[i].uc_xfer != NULL((void *)0)) {
887 usbd_free_xfer(ch[i].uc_xfer);
888 ch[i].uc_xfer = NULL((void *)0);
889 }
890 }
891}
892
893void
894uaq_stop(struct uaq_softc *sc)
895{
896 struct uaq_cdata *cd;
897 struct ifnet *ifp;
898 usbd_status err;
899
900 ifp = &sc->sc_ac.ac_if;
901 ifp->if_timer = 0;
902 ifp->if_flags &= ~IFF_RUNNING0x40;
903 ifq_clr_oactive(&ifp->if_snd);
904
905 sc->sc_link_status = 0;
906 sc->sc_link_speed = 0;
907
908 if (sc->sc_ep[UAQ_ENDPT_RX0] != NULL((void *)0)) {
909 err = usbd_close_pipe(sc->sc_ep[UAQ_ENDPT_RX0]);
910 if (err) {
911 printf("%s: close rx pipe failed: %s\n",
912 sc->sc_dev.dv_xname, usbd_errstr(err));
913 }
914 sc->sc_ep[UAQ_ENDPT_RX0] = NULL((void *)0);
915 }
916
917 if (sc->sc_ep[UAQ_ENDPT_TX1] != NULL((void *)0)) {
918 err = usbd_close_pipe(sc->sc_ep[UAQ_ENDPT_TX1]);
919 if (err) {
920 printf("%s: close tx pipe failed: %s\n",
921 sc->sc_dev.dv_xname, usbd_errstr(err));
922 }
923 sc->sc_ep[UAQ_ENDPT_TX1] = NULL((void *)0);
924 }
925
926 if (sc->sc_ep[UAQ_ENDPT_INTR2] != NULL((void *)0)) {
927 err = usbd_close_pipe(sc->sc_ep[UAQ_ENDPT_INTR2]);
928 if (err) {
929 printf("%s: close intr pipe failed: %s\n",
930 sc->sc_dev.dv_xname, usbd_errstr(err));
931 }
932 sc->sc_ep[UAQ_ENDPT_INTR2] = NULL((void *)0);
933 }
934
935 cd = &sc->sc_cdata;
936 uaq_xfer_list_free(sc, cd->uaq_rx_chain, UAQ_RX_LIST_CNT1);
937 uaq_xfer_list_free(sc, cd->uaq_tx_chain, UAQ_TX_LIST_CNT1);
938}
939
940void
941uaq_link(struct uaq_softc *sc)
942{
943 if (sc->sc_link_speed > 0) {
944 uint8_t resend[3] = { 0, 0xf8, 7 };
945 uint8_t qctrl[5] = { 7, 0x00, 0x01, 0x1e, 0xff };
946 uint8_t ipg = 0;
947
948 switch (sc->sc_link_speed) {
949 case UAQ_STATUS_SPEED_100M0x0013:
950 resend[1] = 0xfb;
951 resend[2] = 0x4;
952 break;
953
954 case UAQ_STATUS_SPEED_5G0x000F:
955 ipg = 5;
956 break;
957 }
958
959 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_IPG_00x0D, 1, ipg);
960
961 uaq_write_mem(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_TX_PAUSE_RESEND_T0xB2,
962 3, resend, 3);
963 uaq_write_mem(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_RX_BULKIN_QCTRL0x2E,
964 5, qctrl, 5);
965 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_PAUSE_WATERLVL_LOW0x54,
966 2, 0x0810);
967
968 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_BMRX_DMA_CTRL0x43, 1,
969 0);
970 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_BMTX_DMA_CTRL0x46, 1,
971 0);
972 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_ARC_CTRL0x9E, 1, 0);
973
974 sc->sc_rxctl = UAQ_SFR_RX_CTL_IPE0x0200 | UAQ_SFR_RX_CTL_AB0x0008;
975 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_RX_CTL0x0B, 2,
976 sc->sc_rxctl);
977
978 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_ETH_MAC_PATH0xB7, 1,
979 UAQ_SFR_RX_PATH_READY0x01);
980
981 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_BULK_OUT_CTRL0xB9, 1,
982 UAQ_SFR_BULK_OUT_EFF_EN0x02);
983
984 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_MEDIUM_STATUS_MODE0x22,
985 2, 0);
986 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_MEDIUM_STATUS_MODE0x22,
987 2, UAQ_SFR_MEDIUM_XGMIIMODE0x0001 | UAQ_SFR_MEDIUM_FULL_DUPLEX0x0002 |
988 UAQ_SFR_MEDIUM_RECEIVE_EN0x0100 | UAQ_SFR_MEDIUM_RXFLOW_CTRLEN0x0010 |
989 UAQ_SFR_MEDIUM_TXFLOW_CTRLEN0x0020); /* JUMBO_EN */
990
991 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_RXCOE_CTL0x34, 1,
992 UAQ_SFR_RXCOE_IP0x01 | UAQ_SFR_RXCOE_TCP0x02 | UAQ_SFR_RXCOE_UDP0x04 |
993 UAQ_SFR_RXCOE_TCPV60x20 | UAQ_SFR_RXCOE_UDPV60x40);
994 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_TXCOE_CTL0x35, 1,
995 UAQ_SFR_TXCOE_IP0x01 | UAQ_SFR_TXCOE_TCP0x02 | UAQ_SFR_TXCOE_UDP0x04 |
996 UAQ_SFR_TXCOE_TCPV60x20 | UAQ_SFR_TXCOE_UDPV60x40);
997
998 sc->sc_rxctl |= UAQ_SFR_RX_CTL_START0x0080;
999 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_RX_CTL0x0B, 2,
1000 sc->sc_rxctl);
1001 } else {
1002 uint16_t mode;
1003
1004 mode = uaq_read_2(sc, UAQ_CMD_ACCESS_MAC0x01,
1005 UAQ_SFR_MEDIUM_STATUS_MODE0x22, 2);
1006 mode &= ~UAQ_SFR_MEDIUM_RECEIVE_EN0x0100;
1007 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_MEDIUM_STATUS_MODE0x22,
1008 2, mode);
1009
1010 sc->sc_rxctl &= ~UAQ_SFR_RX_CTL_START0x0080;
1011 uaq_write_2(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_RX_CTL0x0B, 2,
1012 sc->sc_rxctl);
1013
1014 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_BULK_OUT_CTRL0xB9, 1,
1015 UAQ_SFR_BULK_OUT_FLUSH_EN0x01 | UAQ_SFR_BULK_OUT_EFF_EN0x02);
1016
1017 uaq_write_1(sc, UAQ_CMD_ACCESS_MAC0x01, UAQ_SFR_BULK_OUT_CTRL0xB9, 1,
1018 UAQ_SFR_BULK_OUT_EFF_EN0x02);
1019 }
1020}
1021
1022void
1023uaq_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
1024{
1025 struct uaq_softc *sc = priv;
1026 struct ifnet *ifp = &sc->sc_ac.ac_if;
1027 uint64_t linkstatus;
1028 uint64_t baudrate;
1029 int link_state;
1030
1031 if (status == USBD_CANCELLED)
1032 return;
1033
1034 if (status != USBD_NORMAL_COMPLETION) {
1035 DPRINTFN(2, ("uaq_intr: status=%d\n", status));
1036 if (status == USBD_STALLED)
1037 usbd_clear_endpoint_stall_async(
1038 sc->sc_ep[UAQ_ENDPT_INTR2]);
1039 return;
1040 }
1041
1042 linkstatus = letoh64(sc->sc_link_status)((__uint64_t)(sc->sc_link_status));
1043 DPRINTFN(1, ("uaq_intr: link status %llx\n", linkstatus));
1044
1045 if (linkstatus & UAQ_STATUS_LINK0x8000) {
1046 link_state = LINK_STATE_FULL_DUPLEX6;
1047 sc->sc_link_speed = (linkstatus & UAQ_STATUS_SPEED_MASK0x7F00)
1048 >> UAQ_STATUS_SPEED_SHIFT8;
1049 switch (sc->sc_link_speed) {
1050 case UAQ_STATUS_SPEED_5G0x000F:
1051 baudrate = IF_Gbps(5)((((((5) * 1000ULL) * 1000ULL) * 1000ULL)));
1052 break;
1053 case UAQ_STATUS_SPEED_2_5G0x0010:
1054 baudrate = IF_Mbps(2500)((((2500) * 1000ULL) * 1000ULL));
1055 break;
1056 case UAQ_STATUS_SPEED_1G0x0011:
1057 baudrate = IF_Gbps(1)((((((1) * 1000ULL) * 1000ULL) * 1000ULL)));
1058 break;
1059 case UAQ_STATUS_SPEED_100M0x0013:
1060 baudrate = IF_Mbps(100)((((100) * 1000ULL) * 1000ULL));
1061 break;
1062 default:
1063 baudrate = 0;
1064 break;
1065 }
1066
1067 ifp->if_baudrateif_data.ifi_baudrate = baudrate;
1068 } else {
1069 link_state = LINK_STATE_DOWN2;
1070 sc->sc_link_speed = 0;
1071 }
1072
1073 if (link_state != ifp->if_link_stateif_data.ifi_link_state) {
1074 ifp->if_link_stateif_data.ifi_link_state = link_state;
1075 if_link_state_change(ifp);
1076 usb_add_task(sc->sc_udev, &sc->sc_link_task);
1077 }
1078}
1079
1080void
1081uaq_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1082{
1083 struct uaq_chain *c = (struct uaq_chain *)priv;
1084 struct uaq_softc *sc = c->uc_sc;
1085 struct ifnet *ifp = &sc->sc_ac.ac_if;
1086 uint8_t *buf;
1087 uint64_t *pdesc;
1088 uint64_t desc;
1089 uint32_t total_len;
1090 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
1091 struct mbuf *m;
1092 int pktlen, s;
1093 int count, offset;
1094
1095 if (usbd_is_dying(sc->sc_udev))
1096 return;
1097
1098 if (!(ifp->if_flags & IFF_RUNNING0x40))
1099 return;
1100
1101 if (status != USBD_NORMAL_COMPLETION) {
1102 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1103 return;
1104 if (usbd_ratecheck(&sc->sc_rx_notice)) {
1105 printf("%s: usb errors on rx: %s\n",
1106 sc->sc_dev.dv_xname, usbd_errstr(status));
1107 }
1108 if (status == USBD_STALLED)
1109 usbd_clear_endpoint_stall_async(
1110 sc->sc_ep[UAQ_ENDPT_RX0]);
1111 goto done;
1112 }
1113
1114 usbd_get_xfer_status(xfer, NULL((void *)0), (void **)&buf, &total_len, NULL((void *)0));
1115 DPRINTFN(3, ("received %d bytes\n", total_len));
1116 if ((total_len & 7) != 0) {
1117 printf("%s: weird rx transfer length %d\n",
1118 sc->sc_dev.dv_xname, total_len);
1119 goto done;
1120 }
1121
1122 pdesc = (uint64_t *)(buf + (total_len - sizeof(desc)));
1123 desc = lemtoh64(pdesc)((__uint64_t)(*(__uint64_t *)(pdesc)));
1124
1125 count = desc & UAQ_RX_HDR_COUNT_MASK0x1FFF;
1126 if (count == 0)
1127 goto done;
1128
1129 /* get offset of packet headers */
1130 offset = total_len - ((count + 1) * sizeof(desc));
1131 if (offset != ((desc & UAQ_RX_HDR_OFFSET_MASK0xFFFFE000) >>
1132 UAQ_RX_HDR_OFFSET_SHIFT13)) {
1133 printf("%s: offset mismatch, got %d expected %lld\n",
1134 sc->sc_dev.dv_xname, offset,
1135 desc >> UAQ_RX_HDR_OFFSET_SHIFT13);
1136 goto done;
1137 }
1138 if (offset < 0 || offset > total_len) {
1139 printf("%s: offset %d outside buffer (%d)\n",
1140 sc->sc_dev.dv_xname, offset, total_len);
1141 goto done;
1142 }
1143
1144 pdesc = (uint64_t *)(buf + offset);
1145 total_len = offset;
1146
1147 while (count-- > 0) {
1148 desc = lemtoh64(pdesc)((__uint64_t)(*(__uint64_t *)(pdesc)));
1149 pdesc++;
1150
1151 pktlen = (desc & UAQ_RX_PKT_LEN_MASK0x7FFF0000) >> UAQ_RX_PKT_LEN_SHIFT16;
1152 if (pktlen > total_len) {
1153 DPRINTFN(2, ("not enough bytes for this packet\n"));
1154 ifp->if_ierrorsif_data.ifi_ierrors++;
1155 goto done;
1156 }
1157
1158 m = m_devget(buf + 2, pktlen - 2, ETHER_ALIGN2);
1159 if (m == NULL((void *)0)) {
1160 DPRINTFN(2, ("m_devget failed for this packet\n"));
1161 ifp->if_ierrorsif_data.ifi_ierrors++;
1162 goto done;
1163 }
1164
1165 if ((desc & UAQ_RX_PKT_L3_ERR0x02) == 0)
1166 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK0x0008;
1167
1168 if ((desc & UAQ_RX_PKT_L4_ERR0x01) == 0)
1169 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK0x0020 |
1170 M_UDP_CSUM_IN_OK0x0080;
1171
1172#if NVLAN1 > 0
1173 if (desc & UAQ_RX_PKT_VLAN0x400) {
1174 m->m_pkthdrM_dat.MH.MH_pkthdr.ether_vtag = (desc >> UAQ_RX_PKT_VLAN_SHIFT32) &
1175 0xfff;
1176 m->m_flagsm_hdr.mh_flags |= M_VLANTAG0x0020;
1177 }
1178#endif
1179 ml_enqueue(&ml, m);
1180
1181 total_len -= roundup(pktlen, UAQ_RX_BUF_ALIGN)((((pktlen)+((8)-1))/(8))*(8));
1182 buf += roundup(pktlen, UAQ_RX_BUF_ALIGN)((((pktlen)+((8)-1))/(8))*(8));
1183 }
1184
1185done:
1186 s = splnet()splraise(0x4);
1187 if_input(ifp, &ml);
1188 splx(s)spllower(s);
1189 memset(c->uc_buf, 0, UAQ_RX_BUFSZ)__builtin_memset((c->uc_buf), (0), ((62 * 1024)));
1190
1191 usbd_setup_xfer(xfer, sc->sc_ep[UAQ_ENDPT_RX0], c, c->uc_buf,
1192 UAQ_RX_BUFSZ(62 * 1024), USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
1193 USBD_NO_TIMEOUT0, uaq_rxeof);
1194 usbd_transfer(xfer);
1195}
1196
1197
1198void
1199uaq_watchdog(struct ifnet *ifp)
1200{
1201 struct uaq_softc *sc = ifp->if_softc;
1202 struct uaq_chain *c;
1203 usbd_status err;
1204 int i, s;
1205
1206 ifp->if_timer = 0;
1207
1208 if (usbd_is_dying(sc->sc_udev))
1209 return;
1210
1211 if ((ifp->if_flags & (IFF_RUNNING0x40|IFF_UP0x1)) != (IFF_RUNNING0x40|IFF_UP0x1))
1212 return;
1213
1214 sc = ifp->if_softc;
1215 s = splnet()splraise(0x4);
1216
1217 ifp->if_oerrorsif_data.ifi_oerrors++;
1218 DPRINTF(("%s: watchdog timeout\n", sc->sc_dev.dv_xname));
1219
1220 for (i = 0; i < UAQ_TX_LIST_CNT1; i++) {
1221 c = &sc->sc_cdata.uaq_tx_chain[i];
1222 if (c->uc_cnt > 0) {
1223 usbd_get_xfer_status(c->uc_xfer, NULL((void *)0), NULL((void *)0), NULL((void *)0),
1224 &err);
1225 uaq_txeof(c->uc_xfer, c, err);
1226 }
1227 }
1228
1229 if (ifq_is_oactive(&ifp->if_snd))
1230 ifq_restart(&ifp->if_snd);
1231 splx(s)spllower(s);
1232}
1233
1234void
1235uaq_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1236{
1237 struct uaq_softc *sc;
1238 struct uaq_chain *c;
1239 struct ifnet *ifp;
1240 int s;
1241
1242 c = priv;
1243 sc = c->uc_sc;
1244 ifp = &sc->sc_ac.ac_if;
1245
1246 if (usbd_is_dying(sc->sc_udev))
1247 return;
1248
1249 if (status != USBD_NORMAL_COMPLETION)
1250 DPRINTF(("%s: %s uc_idx=%u : %s\n", sc->sc_dev.dv_xname,
1251 __func__, c->uc_idx, usbd_errstr(status)));
1252 else
1253 DPRINTF(("%s: txeof\n", sc->sc_dev.dv_xname));
1254
1255 s = splnet()splraise(0x4);
1256
1257 c->uc_cnt = 0;
1258 c->uc_buflen = 0;
1259
1260 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)
;
1261
1262 if (status != USBD_NORMAL_COMPLETION) {
1263 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1264 splx(s)spllower(s);
1265 return;
1266 }
1267
1268 ifp->if_oerrorsif_data.ifi_oerrors++;
1269 printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname,
1270 usbd_errstr(status));
1271
1272 if (status == USBD_STALLED)
1273 usbd_clear_endpoint_stall_async(
1274 sc->sc_ep[UAQ_ENDPT_TX1]);
1275 splx(s)spllower(s);
1276 return;
1277 }
1278
1279 ifp->if_timer = 0;
1280 if (ifq_is_oactive(&ifp->if_snd))
1281 ifq_restart(&ifp->if_snd);
1282 splx(s)spllower(s);
1283}
1284
1285void
1286uaq_start(struct ifnet *ifp)
1287{
1288 struct uaq_softc *sc = ifp->if_softc;
1289 struct uaq_cdata *cd = &sc->sc_cdata;
1290 struct uaq_chain *c;
1291 struct mbuf *m = NULL((void *)0);
1292 int s, mlen;
1293
1294 if ((sc->sc_link_speed == 0) ||
1295 (ifp->if_flags & (IFF_RUNNING0x40|IFF_UP0x1)) !=
1296 (IFF_RUNNING0x40|IFF_UP0x1)) {
1297 return;
1298 }
1299
1300 s = splnet()splraise(0x4);
1301
1302 c = SLIST_FIRST(&cd->uaq_tx_free)((&cd->uaq_tx_free)->slh_first);
1303 while (c != NULL((void *)0)) {
1304 m = ifq_deq_begin(&ifp->if_snd);
1305 if (m == NULL((void *)0))
1306 break;
1307
1308 mlen = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1309
1310 /* Discard packet larger than buffer. */
1311 if (mlen + sizeof(uint64_t) >= c->uc_bufmax) {
1312 ifq_deq_commit(&ifp->if_snd, m);
1313 m_freem(m);
1314 ifp->if_oerrorsif_data.ifi_oerrors++;
1315 continue;
1316 }
1317
1318 /* Append packet to current buffer. */
1319 mlen = uaq_encap_txpkt(sc, m, c->uc_buf + c->uc_buflen,
1320 c->uc_bufmax - c->uc_buflen);
1321 if (mlen <= 0) {
1322 ifq_deq_rollback(&ifp->if_snd, m);
1323 break;
1324 }
1325
1326 ifq_deq_commit(&ifp->if_snd, m);
1327 c->uc_cnt += 1;
1328 c->uc_buflen += mlen;
1329
1330#if NBPFILTER1 > 0
1331 if (ifp->if_bpf)
1332 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1));
1333#endif
1334
1335 m_freem(m);
1336 }
1337
1338 if (c != NULL((void *)0)) {
1339 /* Send current buffer unless empty */
1340 if (c->uc_buflen > 0 && c->uc_cnt > 0) {
1341 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)
;
1342 if (uaq_encap_xfer(sc, c)) {
1343 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)
1344 uc_list)do { (c)->uc_list.sle_next = (&cd->uaq_tx_free)->
slh_first; (&cd->uaq_tx_free)->slh_first = (c); } while
(0)
;
1345 }
1346 c = SLIST_FIRST(&cd->uaq_tx_free)((&cd->uaq_tx_free)->slh_first);
1347
1348 ifp->if_timer = 5;
1349 if (c == NULL((void *)0))
1350 ifq_set_oactive(&ifp->if_snd);
1351 }
1352 }
1353
1354 splx(s)spllower(s);
1355}
1356
1357int
1358uaq_encap_txpkt(struct uaq_softc *sc, struct mbuf *m, char *buf,
1359 uint32_t maxlen)
1360{
1361 uint64_t desc;
1362 int padded;
1363
1364 desc = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1365 padded = roundup(m->m_pkthdr.len, UAQ_TX_BUF_ALIGN)((((m->M_dat.MH.MH_pkthdr.len)+((8)-1))/(8))*(8));
1366 if (((padded + sizeof(desc)) % sc->sc_out_frame_size) == 0) {
1367 desc |= UAQ_TX_PKT_DROP_PADD(1 << 28);
1368 padded += 8;
1369 }
1370
1371 if (padded + sizeof(desc) > maxlen)
1372 return (-1);
1373
1374#if NVLAN1 > 0
1375 if (m->m_flagsm_hdr.mh_flags & M_VLANTAG0x0020)
1376 desc |= (((uint64_t)m->m_pkthdrM_dat.MH.MH_pkthdr.ether_vtag) <<
1377 UAQ_TX_PKT_VLAN_SHIFT0x30) | UAQ_TX_PKT_VLAN(1 << 29);
1378#endif
1379
1380 htolem64((uint64_t *)buf, desc)(*(__uint64_t *)((uint64_t *)buf) = ((__uint64_t)(desc)));
1381 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, buf + sizeof(desc));
1382 return (padded + sizeof(desc));
1383}
1384
1385int
1386uaq_encap_xfer(struct uaq_softc *sc, struct uaq_chain *c)
1387{
1388 usbd_status err;
1389
1390 usbd_setup_xfer(c->uc_xfer, sc->sc_ep[UAQ_ENDPT_TX1], c, c->uc_buf,
1391 c->uc_buflen, USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01, 10000,
1392 uaq_txeof);
1393
1394 err = usbd_transfer(c->uc_xfer);
1395 if (err != USBD_IN_PROGRESS) {
1396 c->uc_cnt = 0;
1397 c->uc_buflen = 0;
1398 uaq_stop(sc);
1399 return (EIO5);
1400 }
1401
1402 return (0);
1403}