Bug Summary

File:dev/usb/if_axe.c
Warning:line 1333, column 9
Assigned value is garbage or undefined

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_axe.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_axe.c
1/* $OpenBSD: if_axe.c,v 1.142 2020/07/31 10:49:32 mglocker Exp $ */
2
3/*
4 * Copyright (c) 2005, 2006, 2007 Jonathan Gray <jsg@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * Copyright (c) 1997, 1998, 1999, 2000-2003
21 * Bill Paul <wpaul@windriver.com>. All rights reserved.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * This product includes software developed by Bill Paul.
34 * 4. Neither the name of the author nor the names of any co-contributors
35 * may be used to endorse or promote products derived from this software
36 * without specific prior written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
42 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
43 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
44 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
48 * THE POSSIBILITY OF SUCH DAMAGE.
49 */
50
51/*
52 * ASIX Electronics AX88172 USB 2.0 ethernet driver. Used in the
53 * LinkSys USB200M and various other adapters.
54 *
55 * Manuals available from:
56 * http://www.asix.com.tw/datasheet/mac/Ax88172.PDF
57 * Note: you need the manual for the AX88170 chip (USB 1.x ethernet
58 * controller) to find the definitions for the RX control register.
59 * http://www.asix.com.tw/datasheet/mac/Ax88170.PDF
60 *
61 * Written by Bill Paul <wpaul@windriver.com>
62 * Senior Engineer
63 * Wind River Systems
64 */
65
66/*
67 * The AX88172 provides USB ethernet supports at 10 and 100Mbps.
68 * It uses an external PHY (reference designs use a Realtek chip),
69 * and has a 64-bit multicast hash filter. There is some information
70 * missing from the manual which one needs to know in order to make
71 * the chip function:
72 *
73 * - You must set bit 7 in the RX control register, otherwise the
74 * chip won't receive any packets.
75 * - You must initialize all 3 IPG registers, or you won't be able
76 * to send any packets.
77 *
78 * Note that this device appears to only support loading the station
79 * address via autoload from the EEPROM (i.e. there's no way to manually
80 * set it).
81 *
82 * (Adam Weinberger wanted me to name this driver if_gir.c.)
83 */
84
85/*
86 * Ported to OpenBSD 3/28/2004 by Greg Taleck <taleck@oz.net>
87 * with bits and pieces from the aue and url drivers.
88 */
89
90#include "bpfilter.h"
91
92#include <sys/param.h>
93#include <sys/systm.h>
94#include <sys/sockio.h>
95#include <sys/rwlock.h>
96#include <sys/mbuf.h>
97#include <sys/kernel.h>
98#include <sys/socket.h>
99
100#include <sys/device.h>
101
102#include <machine/bus.h>
103
104#include <net/if.h>
105#include <net/if_media.h>
106
107#if NBPFILTER1 > 0
108#include <net/bpf.h>
109#endif
110
111#include <netinet/in.h>
112#include <netinet/if_ether.h>
113
114#include <dev/mii/mii.h>
115#include <dev/mii/miivar.h>
116
117#include <dev/usb/usb.h>
118#include <dev/usb/usbdi.h>
119#include <dev/usb/usbdi_util.h>
120#include <dev/usb/usbdivar.h>
121#include <dev/usb/usbdevs.h>
122
123#include <dev/usb/if_axereg.h>
124
125#ifdef AXE_DEBUG
126#define DPRINTF(x) do { if (axedebug) printf x; } while (0)
127#define DPRINTFN(n,x) do { if (axedebug >= (n)) printf x; } while (0)
128int axedebug = 0;
129#else
130#define DPRINTF(x)
131#define DPRINTFN(n,x)
132#endif
133
134/*
135 * Various supported device vendors/products.
136 */
137const struct axe_type axe_devs[] = {
138 { { USB_VENDOR_ABOCOM0x07b8, USB_PRODUCT_ABOCOM_UF2000x420a}, 0 },
139 { { USB_VENDOR_ACERCM0x1189, USB_PRODUCT_ACERCM_EP1427X20x0893}, 0 },
140 { { USB_VENDOR_APPLE0x05ac, USB_PRODUCT_APPLE_ETHERNET0x1402 }, AX7720x0002 },
141 { { USB_VENDOR_ASIX0x0b95, USB_PRODUCT_ASIX_AX881720x1720}, 0 },
142 { { USB_VENDOR_ASIX0x0b95, USB_PRODUCT_ASIX_AX887720x7720}, AX7720x0002 },
143 { { USB_VENDOR_ASIX0x0b95, USB_PRODUCT_ASIX_AX88772A0x772a}, AX7720x0002 },
144 { { USB_VENDOR_ASIX0x0b95, USB_PRODUCT_ASIX_AX88772B0x772b}, AX7720x0002 | AX772B0x0004 },
145 { { USB_VENDOR_ASIX0x0b95, USB_PRODUCT_ASIX_AX88772B_10x7e2b}, AX7720x0002 | AX772B0x0004 },
146 { { USB_VENDOR_ASIX0x0b95, USB_PRODUCT_ASIX_AX881780x1780}, AX1780x0001 },
147 { { USB_VENDOR_ATEN0x0557, USB_PRODUCT_ATEN_UC210T0x2009}, 0 },
148 { { USB_VENDOR_BELKIN0x050d, USB_PRODUCT_BELKIN_F5D50550x5055 }, AX1780x0001 },
149 { { USB_VENDOR_BILLIONTON0x08dd, USB_PRODUCT_BILLIONTON_USB2AR0x90ff}, 0},
150 { { USB_VENDOR_CISCOLINKSYS0x13b1, USB_PRODUCT_CISCOLINKSYS_USB200MV20x0018}, AX7720x0002 },
151 { { USB_VENDOR_COREGA0x07aa, USB_PRODUCT_COREGA_FETHER_USB2_TX0x0017 }, 0},
152 { { USB_VENDOR_DLINK0x2001, USB_PRODUCT_DLINK_DUBE1000x1a00}, 0 },
153 { { USB_VENDOR_DLINK0x2001, USB_PRODUCT_DLINK_DUBE100B10x3c05 }, AX7720x0002 },
154 { { USB_VENDOR_DLINK0x2001, USB_PRODUCT_DLINK_DUBE100C10x1a02 }, AX7720x0002 | AX772B0x0004 },
155 { { USB_VENDOR_GOODWAY0x1631, USB_PRODUCT_GOODWAY_GWUSB2E0x6200}, 0 },
156 { { USB_VENDOR_IODATA0x04bb, USB_PRODUCT_IODATA_ETGUS20x0930 }, AX1780x0001 },
157 { { USB_VENDOR_JVC0x04f1, USB_PRODUCT_JVC_MP_PRX10x3008}, 0 },
158 { { USB_VENDOR_LENOVO0x17ef, USB_PRODUCT_LENOVO_ETHERNET0x7203 }, AX7720x0002 | AX772B0x0004 },
159 { { USB_VENDOR_LINKSYS0x066b, USB_PRODUCT_LINKSYS_HG20F90x20f9}, AX7720x0002 | AX772B0x0004 },
160 { { USB_VENDOR_LINKSYS20x077b, USB_PRODUCT_LINKSYS2_USB200M0x2226}, 0 },
161 { { USB_VENDOR_LINKSYS40x1737, USB_PRODUCT_LINKSYS4_USB10000x0039 }, AX1780x0001 },
162 { { USB_VENDOR_LOGITEC0x0789, USB_PRODUCT_LOGITEC_LAN_GTJU20x0102}, AX1780x0001 },
163 { { USB_VENDOR_MELCO0x0411, USB_PRODUCT_MELCO_LUAU2GT0x006e}, AX1780x0001 },
164 { { USB_VENDOR_MELCO0x0411, USB_PRODUCT_MELCO_LUAU2KTX0x003d}, 0 },
165 { { USB_VENDOR_MSI0x0db0, USB_PRODUCT_MSI_AX88772A0xa877}, AX7720x0002 },
166 { { USB_VENDOR_NETGEAR0x0846, USB_PRODUCT_NETGEAR_FA1200x1040}, 0 },
167 { { USB_VENDOR_OQO0x1557, USB_PRODUCT_OQO_ETHER01PLUS0x7720 }, AX7720x0002 },
168 { { USB_VENDOR_PLANEX30x14ea, USB_PRODUCT_PLANEX3_GU1000T0xab11 }, AX1780x0001 },
169 { { USB_VENDOR_SYSTEMTALKS0x086e, USB_PRODUCT_SYSTEMTALKS_SGCX2UL0x1920}, 0 },
170 { { USB_VENDOR_SITECOM0x6189, USB_PRODUCT_SITECOM_LN0290x182d}, 0 },
171 { { USB_VENDOR_SITECOMEU0x0df6, USB_PRODUCT_SITECOMEU_LN0280x061c }, AX1780x0001 }
172};
173
174#define axe_lookup(v, p)((struct axe_type *)usbd_match_device((const struct usb_devno
*)(axe_devs), sizeof (axe_devs) / sizeof ((axe_devs)[0]), sizeof
((axe_devs)[0]), (v), (p)))
((struct axe_type *)usb_lookup(axe_devs, v, p)usbd_match_device((const struct usb_devno *)(axe_devs), sizeof
(axe_devs) / sizeof ((axe_devs)[0]), sizeof ((axe_devs)[0]),
(v), (p))
)
175
176int axe_match(struct device *, void *, void *);
177void axe_attach(struct device *, struct device *, void *);
178int axe_detach(struct device *, int);
179
180struct cfdriver axe_cd = {
181 NULL((void *)0), "axe", DV_IFNET
182};
183
184const struct cfattach axe_ca = {
185 sizeof(struct axe_softc), axe_match, axe_attach, axe_detach
186};
187
188int axe_tx_list_init(struct axe_softc *);
189int axe_rx_list_init(struct axe_softc *);
190struct mbuf *axe_newbuf(void);
191int axe_encap(struct axe_softc *, struct mbuf *, int);
192void axe_rxeof(struct usbd_xfer *, void *, usbd_status);
193void axe_txeof(struct usbd_xfer *, void *, usbd_status);
194void axe_tick(void *);
195void axe_tick_task(void *);
196void axe_start(struct ifnet *);
197int axe_ioctl(struct ifnet *, u_long, caddr_t);
198void axe_init(void *);
199void axe_stop(struct axe_softc *);
200void axe_watchdog(struct ifnet *);
201int axe_miibus_readreg(struct device *, int, int);
202void axe_miibus_writereg(struct device *, int, int, int);
203void axe_miibus_statchg(struct device *);
204int axe_cmd(struct axe_softc *, int, int, int, void *);
205int axe_ifmedia_upd(struct ifnet *);
206void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
207void axe_reset(struct axe_softc *sc);
208
209void axe_iff(struct axe_softc *);
210void axe_lock_mii(struct axe_softc *sc);
211void axe_unlock_mii(struct axe_softc *sc);
212
213void axe_ax88178_init(struct axe_softc *);
214void axe_ax88772_init(struct axe_softc *);
215
216/* Get exclusive access to the MII registers */
217void
218axe_lock_mii(struct axe_softc *sc)
219{
220 sc->axe_refcnt++;
221 rw_enter_write(&sc->axe_mii_lock);
222}
223
224void
225axe_unlock_mii(struct axe_softc *sc)
226{
227 rw_exit_write(&sc->axe_mii_lock);
228 if (--sc->axe_refcnt < 0)
229 usb_detach_wakeup(&sc->axe_dev);
230}
231
232int
233axe_cmd(struct axe_softc *sc, int cmd, int index, int val, void *buf)
234{
235 usb_device_request_t req;
236 usbd_status err;
237
238 if (usbd_is_dying(sc->axe_udev))
13
Assuming the condition is true
14
Taking true branch
239 return(0);
240
241 if (AXE_CMD_DIR(cmd)(((cmd) & 0x0F00) >> 8))
242 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
243 else
244 req.bmRequestType = UT_READ_VENDOR_DEVICE(0x80 | 0x40 | 0x00);
245 req.bRequest = AXE_CMD_CMD(cmd)((cmd) & 0x00FF);
246 USETW(req.wValue, val)(*(u_int16_t *)(req.wValue) = (val));
247 USETW(req.wIndex, index)(*(u_int16_t *)(req.wIndex) = (index));
248 USETW(req.wLength, AXE_CMD_LEN(cmd))(*(u_int16_t *)(req.wLength) = ((((cmd) & 0xF000) >>
12)))
;
249
250 err = usbd_do_request(sc->axe_udev, &req, buf);
251
252 if (err) {
253 DPRINTF(("axe_cmd err: cmd: %d\n", cmd));
254 return(-1);
255 }
256
257 return(0);
258}
259
260int
261axe_miibus_readreg(struct device *dev, int phy, int reg)
262{
263 struct axe_softc *sc = (void *)dev;
264 usbd_status err;
265 uWord val;
266 int ival;
267
268 if (usbd_is_dying(sc->axe_udev)) {
269 DPRINTF(("axe: dying\n"));
270 return(0);
271 }
272
273#ifdef notdef
274 /*
275 * The chip tells us the MII address of any supported
276 * PHYs attached to the chip, so only read from those.
277 */
278
279 DPRINTF(("axe_miibus_readreg: phy 0x%x reg 0x%x\n", phy, reg));
280
281 if (sc->axe_phyaddrs[0] != AXE_NOPHY && phy != sc->axe_phyaddrs[0])
282 return (0);
283
284 if (sc->axe_phyaddrs[1] != AXE_NOPHY && phy != sc->axe_phyaddrs[1])
285 return (0);
286#endif
287 if (sc->axe_phyno != phy)
288 return (0);
289
290 USETW(val, 0)(*(u_int16_t *)(val) = (0));
291
292 axe_lock_mii(sc);
293 axe_cmd(sc, AXE_CMD_MII_OPMODE_SW0x0106, 0, 0, NULL((void *)0));
294 err = axe_cmd(sc, AXE_CMD_MII_READ_REG0x2007, reg, phy, val);
295 axe_cmd(sc, AXE_CMD_MII_OPMODE_HW0x010A, 0, 0, NULL((void *)0));
296 axe_unlock_mii(sc);
297
298 if (err) {
299 printf("axe%d: read PHY failed\n", sc->axe_unit);
300 return(-1);
301 }
302 DPRINTF(("axe_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n",
303 phy, reg, UGETW(val)));
304
305 ival = UGETW(val)(*(u_int16_t *)(val));
306 if ((sc->axe_flags & AX7720x0002) != 0 && reg == MII_BMSR0x01) {
307 /*
308 * BMSR of AX88772 indicates that it supports extended
309 * capability but the extended status register is
310 * revered for embedded ethernet PHY. So clear the
311 * extended capability bit of BMSR.
312 */
313 ival &= ~BMSR_EXTCAP0x0001;
314 }
315
316 return (ival);
317}
318
319void
320axe_miibus_writereg(struct device *dev, int phy, int reg, int val)
321{
322 struct axe_softc *sc = (void *)dev;
323 usbd_status err;
324 uWord uval;
325
326 if (usbd_is_dying(sc->axe_udev))
327 return;
328 if (sc->axe_phyno != phy)
329 return;
330
331 USETW(uval, val)(*(u_int16_t *)(uval) = (val));
332
333 axe_lock_mii(sc);
334 axe_cmd(sc, AXE_CMD_MII_OPMODE_SW0x0106, 0, 0, NULL((void *)0));
335 err = axe_cmd(sc, AXE_CMD_MII_WRITE_REG0x2108, reg, phy, uval);
336 axe_cmd(sc, AXE_CMD_MII_OPMODE_HW0x010A, 0, 0, NULL((void *)0));
337 axe_unlock_mii(sc);
338
339 if (err) {
340 printf("axe%d: write PHY failed\n", sc->axe_unit);
341 return;
342 }
343}
344
345void
346axe_miibus_statchg(struct device *dev)
347{
348 struct axe_softc *sc = (void *)dev;
349 struct mii_data *mii = GET_MII(sc)(&(sc)->axe_mii);
350 struct ifnet *ifp;
351 int val, err;
352
353 ifp = GET_IFP(sc)(&(sc)->arpcom.ac_if);
354 if (mii == NULL((void *)0) || ifp == NULL((void *)0) ||
355 (ifp->if_flags & IFF_RUNNING0x40) == 0)
356 return;
357
358 sc->axe_link = 0;
359 if ((mii->mii_media_status & (IFM_ACTIVE0x0000000000000002ULL | IFM_AVALID0x0000000000000001ULL)) ==
360 (IFM_ACTIVE0x0000000000000002ULL | IFM_AVALID0x0000000000000001ULL)) {
361 switch (IFM_SUBTYPE(mii->mii_media_active)((mii->mii_media_active) & 0x00000000000000ffULL)) {
362 case IFM_10_T3:
363 case IFM_100_TX6:
364 sc->axe_link++;
365 break;
366 case IFM_1000_T16:
367 if ((sc->axe_flags & AX1780x0001) == 0)
368 break;
369 sc->axe_link++;
370 break;
371 default:
372 break;
373 }
374 }
375
376 /* Lost link, do nothing. */
377 if (sc->axe_link == 0)
378 return;
379
380 val = 0;
381 if ((IFM_OPTIONS(mii->mii_media_active)((mii->mii_media_active) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL
))
& IFM_FDX0x0000010000000000ULL) != 0)
382 val |= AXE_MEDIA_FULL_DUPLEX0x0002;
383
384 if (sc->axe_flags & AX1780x0001 || sc->axe_flags & AX7720x0002) {
385 val |= (AXE_178_MEDIA_RX_EN0x0100 | AXE_178_MEDIA_MAGIC0x0004);
386 if (sc->axe_flags & AX1780x0001)
387 val |= AXE_178_MEDIA_ENCK0x0008;
388
389 switch (IFM_SUBTYPE(mii->mii_media_active)((mii->mii_media_active) & 0x00000000000000ffULL)) {
390 case IFM_1000_T16:
391 val |= AXE_178_MEDIA_GMII0x0001 | AXE_178_MEDIA_ENCK0x0008;
392 break;
393 case IFM_100_TX6:
394 val |= AXE_178_MEDIA_100TX0x0200;
395 break;
396 case IFM_10_T3:
397 /* doesn't need to be handled */
398 break;
399 }
400 }
401
402 DPRINTF(("axe_miibus_statchg: val=0x%x\n", val));
403 err = axe_cmd(sc, AXE_CMD_WRITE_MEDIA0x011B, 0, val, NULL((void *)0));
404 if (err) {
405 printf("%s: media change failed\n", sc->axe_dev.dv_xname);
406 return;
407 }
408}
409
410/*
411 * Set media options.
412 */
413int
414axe_ifmedia_upd(struct ifnet *ifp)
415{
416 struct axe_softc *sc = ifp->if_softc;
417 struct mii_data *mii = GET_MII(sc)(&(sc)->axe_mii);
418
419 if (mii->mii_instance) {
420 struct mii_softc *miisc;
421 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)for((miisc) = ((&mii->mii_phys)->lh_first); (miisc)
!= ((void *)0); (miisc) = ((miisc)->mii_list.le_next))
422 mii_phy_reset(miisc);
423 }
424 mii_mediachg(mii);
425
426 return (0);
427}
428
429/*
430 * Report current media status.
431 */
432void
433axe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
434{
435 struct axe_softc *sc = ifp->if_softc;
436 struct mii_data *mii = GET_MII(sc)(&(sc)->axe_mii);
437
438 mii_pollstat(mii);
439 ifmr->ifm_active = mii->mii_media_active;
440 ifmr->ifm_status = mii->mii_media_status;
441}
442
443void
444axe_iff(struct axe_softc *sc)
445{
446 struct ifnet *ifp = GET_IFP(sc)(&(sc)->arpcom.ac_if);
447 struct arpcom *ac = &sc->arpcom;
448 struct ether_multi *enm;
449 struct ether_multistep step;
450 u_int32_t h = 0;
451 uWord urxmode;
452 u_int16_t rxmode;
453 u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
454
455 if (usbd_is_dying(sc->axe_udev))
456 return;
457
458 axe_cmd(sc, AXE_CMD_RXCTL_READ0x200F, 0, 0, urxmode);
459 rxmode = UGETW(urxmode)(*(u_int16_t *)(urxmode));
460 rxmode &= ~(AXE_RXCMD_ALLMULTI0x0002 | AXE_RXCMD_MULTICAST0x0010 |
461 AXE_RXCMD_PROMISC0x0001);
462 ifp->if_flags &= ~IFF_ALLMULTI0x200;
463
464 /*
465 * Always accept broadcast frames.
466 * Always accept frames destined to our station address.
467 */
468 rxmode |= AXE_RXCMD_BROADCAST0x0008;
469 if ((sc->axe_flags & (AX1780x0001 | AX7720x0002)) == 0)
470 rxmode |= AXE_172_RXCMD_UNICAST0x0004;
471
472 if (ifp->if_flags & IFF_PROMISC0x100 || ac->ac_multirangecnt > 0) {
473 ifp->if_flags |= IFF_ALLMULTI0x200;
474 rxmode |= AXE_RXCMD_ALLMULTI0x0002;
475 if (ifp->if_flags & IFF_PROMISC0x100)
476 rxmode |= AXE_RXCMD_PROMISC0x0001;
477 } else {
478 rxmode |= AXE_RXCMD_MULTICAST0x0010;
479
480 /* now program new ones */
481 ETHER_FIRST_MULTI(step, ac, enm)do { (step).e_enm = ((&(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)
;
482 while (enm != NULL((void *)0)) {
483 h = ether_crc32_be(enm->enm_addrlo,
484 ETHER_ADDR_LEN6) >> 26;
485
486 hashtbl[h / 8] |= 1 << (h % 8);
487
488 ETHER_NEXT_MULTI(step, enm)do { if (((enm) = (step).e_enm) != ((void *)0)) (step).e_enm =
(((enm))->enm_list.le_next); } while ( 0)
;
489 }
490 }
491
492 axe_cmd(sc, AXE_CMD_WRITE_MCAST0x8116, 0, 0, (void *)&hashtbl);
493 axe_cmd(sc, AXE_CMD_RXCTL_WRITE0x0110, 0, rxmode, NULL((void *)0));
494}
495
496void
497axe_reset(struct axe_softc *sc)
498{
499 if (usbd_is_dying(sc->axe_udev))
500 return;
501 /* XXX What to reset? */
502
503 /* Wait a little while for the chip to get its brains in order. */
504 DELAY(1000)(*delay_func)(1000);
505 return;
506}
507
508#define AXE_GPIO_WRITE(x,y)do { axe_cmd(sc, 0x011F, 0, (x), ((void *)0)); usbd_delay_ms(
sc->axe_udev, (y)); } while (0)
do { \
509 axe_cmd(sc, AXE_CMD_WRITE_GPIO0x011F, 0, (x), NULL((void *)0)); \
510 usbd_delay_ms(sc->axe_udev, (y)); \
511} while (0)
512
513void
514axe_ax88178_init(struct axe_softc *sc)
515{
516 int gpio0 = 0, phymode = 0, ledmode;
517 u_int16_t eeprom, val;
518
519 axe_cmd(sc, AXE_CMD_SROM_WR_ENABLE0x010D, 0, 0, NULL((void *)0));
520 /* XXX magic */
521 axe_cmd(sc, AXE_CMD_SROM_READ0x200B, 0, 0x0017, &eeprom);
522 axe_cmd(sc, AXE_CMD_SROM_WR_DISABLE0x010E, 0, 0, NULL((void *)0));
523
524 eeprom = letoh16(eeprom)((__uint16_t)(eeprom));
525
526 DPRINTF((" EEPROM is 0x%x\n", eeprom));
527
528 /* if EEPROM is invalid we have to use to GPIO0 */
529 if (eeprom == 0xffff) {
530 phymode = AXE_PHY_MODE_MARVELL0x00;
531 gpio0 = 1;
532 ledmode = 0;
533 } else {
534 phymode = eeprom & 0x7f;
535 gpio0 = (eeprom & 0x80) ? 0 : 1;
536 ledmode = eeprom >> 8;
537 }
538
539 DPRINTF(("use gpio0: %d, phymode 0x%02x, eeprom 0x%04x\n",
540 gpio0, phymode, eeprom));
541
542 /* power up external phy */
543 AXE_GPIO_WRITE(AXE_GPIO1|AXE_GPIO1_EN | AXE_GPIO_RELOAD_EEPROM, 40)do { axe_cmd(sc, 0x011F, 0, (0x08|0x04 | 0x80), ((void *)0));
usbd_delay_ms(sc->axe_udev, (40)); } while (0)
;
544 if (ledmode == 1) {
545 AXE_GPIO_WRITE(AXE_GPIO1_EN, 30)do { axe_cmd(sc, 0x011F, 0, (0x04), ((void *)0)); usbd_delay_ms
(sc->axe_udev, (30)); } while (0)
;
546 AXE_GPIO_WRITE(AXE_GPIO1_EN | AXE_GPIO1, 30)do { axe_cmd(sc, 0x011F, 0, (0x04 | 0x08), ((void *)0)); usbd_delay_ms
(sc->axe_udev, (30)); } while (0)
;
547 } else {
548 val = gpio0 == 1 ? AXE_GPIO00x02 | AXE_GPIO0_EN0x01 :
549 AXE_GPIO10x08 | AXE_GPIO1_EN0x04;
550 AXE_GPIO_WRITE(val | AXE_GPIO2 | AXE_GPIO2_EN, 30)do { axe_cmd(sc, 0x011F, 0, (val | 0x20 | 0x10), ((void *)0))
; usbd_delay_ms(sc->axe_udev, (30)); } while (0)
;
551 AXE_GPIO_WRITE(val | AXE_GPIO2_EN, 300)do { axe_cmd(sc, 0x011F, 0, (val | 0x10), ((void *)0)); usbd_delay_ms
(sc->axe_udev, (300)); } while (0)
;
552 AXE_GPIO_WRITE(val | AXE_GPIO2 | AXE_GPIO2_EN, 30)do { axe_cmd(sc, 0x011F, 0, (val | 0x20 | 0x10), ((void *)0))
; usbd_delay_ms(sc->axe_udev, (30)); } while (0)
;
553 }
554
555 /* initialize phy */
556 if (phymode == AXE_PHY_MODE_REALTEK_8211CL0x0c) {
557 axe_miibus_writereg(&sc->axe_dev, sc->axe_phyno, 0x1f, 0x0005);
558 axe_miibus_writereg(&sc->axe_dev, sc->axe_phyno, 0x0c, 0x0000);
559 val = axe_miibus_readreg(&sc->axe_dev, sc->axe_phyno, 0x0001);
560 axe_miibus_writereg(&sc->axe_dev, sc->axe_phyno, 0x01,
561 val | 0x0080);
562 axe_miibus_writereg(&sc->axe_dev, sc->axe_phyno, 0x1f, 0x0000);
563 }
564
565 /* soft reset */
566 axe_cmd(sc, AXE_CMD_SW_RESET_REG0x0120, 0, AXE_SW_RESET_CLEAR0x00, NULL((void *)0));
567 usbd_delay_ms(sc->axe_udev, 150);
568 axe_cmd(sc, AXE_CMD_SW_RESET_REG0x0120, 0,
569 AXE_SW_RESET_PRL0x08 | AXE_178_RESET_MAGIC0x40, NULL((void *)0));
570 usbd_delay_ms(sc->axe_udev, 150);
571 /* Enable MII/GMII/RGMII for external PHY */
572 axe_cmd(sc, AXE_CMD_SW_PHY_SELECT0x0122, 0, 0, NULL((void *)0));
573 usbd_delay_ms(sc->axe_udev, 10);
574 axe_cmd(sc, AXE_CMD_RXCTL_WRITE0x0110, 0, 0, NULL((void *)0));
575}
576
577/* Read Ethernet Address from EEPROM if it is zero */
578void
579axe_ax88772b_nodeid(struct axe_softc *sc, u_char *eaddr)
580{
581 int i;
582 uint16_t val;
583
584 for (i = 0; i < ETHER_ADDR_LEN6; i++) {
585 if (eaddr[i] != 0)
586 break;
587 }
588
589 /* We already have an ethernet address */
590 if (i != ETHER_ADDR_LEN6)
591 return;
592
593 /* read from EEPROM */
594 for (i = 0; i < ETHER_ADDR_LEN6/2; i++) {
595 axe_cmd(sc, AXE_CMD_SROM_READ0x200B, 0, AXE_EEPROM_772B_NODEID0x04 + i, &val);
596 val = ntohs(val)(__uint16_t)(__builtin_constant_p(val) ? (__uint16_t)(((__uint16_t
)(val) & 0xffU) << 8 | ((__uint16_t)(val) & 0xff00U
) >> 8) : __swap16md(val))
;
597 *eaddr++ = (u_char)((val >> 8) & 0xff);
598 *eaddr++ = (u_char)(val & 0xff);
599 }
600}
601
602void
603axe_ax88772_init(struct axe_softc *sc)
604{
605 axe_cmd(sc, AXE_CMD_WRITE_GPIO0x011F, 0, 0x00b0, NULL((void *)0));
606 usbd_delay_ms(sc->axe_udev, 40);
607
608 if (sc->axe_phyno == AXE_PHY_NO_AX772_EPHY0x10) {
609 /* ask for the embedded PHY */
610 axe_cmd(sc, AXE_CMD_SW_PHY_SELECT0x0122, 0, 0x01, NULL((void *)0));
611 usbd_delay_ms(sc->axe_udev, 10);
612
613 /* power down and reset state, pin reset state */
614 axe_cmd(sc, AXE_CMD_SW_RESET_REG0x0120, 0, AXE_SW_RESET_CLEAR0x00, NULL((void *)0));
615 usbd_delay_ms(sc->axe_udev, 60);
616
617 /* power down/reset state, pin operating state */
618 axe_cmd(sc, AXE_CMD_SW_RESET_REG0x0120, 0,
619 AXE_SW_RESET_IPPD0x40 | AXE_SW_RESET_PRL0x08, NULL((void *)0));
620 usbd_delay_ms(sc->axe_udev, 150);
621
622 /* power up, reset */
623 axe_cmd(sc, AXE_CMD_SW_RESET_REG0x0120, 0, AXE_SW_RESET_PRL0x08, NULL((void *)0));
624
625 /* power up, operating */
626 axe_cmd(sc, AXE_CMD_SW_RESET_REG0x0120, 0,
627 AXE_SW_RESET_IPRL0x20 | AXE_SW_RESET_PRL0x08, NULL((void *)0));
628 } else {
629 /* ask for external PHY */
630 axe_cmd(sc, AXE_CMD_SW_PHY_SELECT0x0122, 0, 0x00, NULL((void *)0));
631 usbd_delay_ms(sc->axe_udev, 10);
632
633 /* power down internal PHY */
634 axe_cmd(sc, AXE_CMD_SW_RESET_REG0x0120, 0,
635 AXE_SW_RESET_IPPD0x40 | AXE_SW_RESET_PRL0x08, NULL((void *)0));
636 }
637
638 usbd_delay_ms(sc->axe_udev, 150);
639 axe_cmd(sc, AXE_CMD_RXCTL_WRITE0x0110, 0, 0, NULL((void *)0));
640}
641
642static int
643axe_get_phyno(struct axe_softc *sc, int sel)
644{
645 int phyno = -1;
646
647 switch (AXE_PHY_TYPE(sc->axe_phyaddrs[sel])(((sc->axe_phyaddrs[sel]) & 0xE0) >> 5)) {
648 case PHY_TYPE_100_HOME0:
649 case PHY_TYPE_GIG1:
650 phyno = AXE_PHY_NO(sc->axe_phyaddrs[sel])((sc->axe_phyaddrs[sel]) & 0x1F);
651 break;
652 case PHY_TYPE_SPECIAL4:
653 /* FALLTHROUGH */
654 case PHY_TYPE_RSVD5:
655 /* FALLTHROUGH */
656 case PHY_TYPE_NON_SUP7:
657 /* FALLTHROUGH */
658 default:
659 break;
660 }
661
662 return (phyno);
663}
664
665/*
666 * Probe for a AX88172 chip.
667 */
668int
669axe_match(struct device *parent, void *match, void *aux)
670{
671 struct usb_attach_arg *uaa = aux;
672
673 if (uaa->iface == NULL((void *)0) || uaa->configno != 1)
674 return (UMATCH_NONE0);
675
676 return (axe_lookup(uaa->vendor, uaa->product)((struct axe_type *)usbd_match_device((const struct usb_devno
*)(axe_devs), sizeof (axe_devs) / sizeof ((axe_devs)[0]), sizeof
((axe_devs)[0]), (uaa->vendor), (uaa->product)))
!= NULL((void *)0) ?
677 UMATCH_VENDOR_PRODUCT_CONF_IFACE8 : UMATCH_NONE0);
678}
679
680/*
681 * Attach the interface. Allocate softc structures, do ifmedia
682 * setup and ethernet/BPF attach.
683 */
684void
685axe_attach(struct device *parent, struct device *self, void *aux)
686{
687 struct axe_softc *sc = (struct axe_softc *)self;
688 struct usb_attach_arg *uaa = aux;
689 usb_interface_descriptor_t *id;
690 usb_endpoint_descriptor_t *ed;
691 struct mii_data *mii;
692 u_char eaddr[ETHER_ADDR_LEN6];
693 char *devname = sc->axe_dev.dv_xname;
694 struct ifnet *ifp;
695 int i, s;
696
697 sc->axe_unit = self->dv_unit; /*device_get_unit(self);*/
698 sc->axe_udev = uaa->device;
699 sc->axe_iface = uaa->iface;
700 sc->axe_flags = axe_lookup(uaa->vendor, uaa->product)((struct axe_type *)usbd_match_device((const struct usb_devno
*)(axe_devs), sizeof (axe_devs) / sizeof ((axe_devs)[0]), sizeof
((axe_devs)[0]), (uaa->vendor), (uaa->product)))
->axe_flags;
701
702 usb_init_task(&sc->axe_tick_task, axe_tick_task, sc,((&sc->axe_tick_task)->fun = (axe_tick_task), (&
sc->axe_tick_task)->arg = (sc), (&sc->axe_tick_task
)->type = (0), (&sc->axe_tick_task)->state = 0x0
)
703 USB_TASK_TYPE_GENERIC)((&sc->axe_tick_task)->fun = (axe_tick_task), (&
sc->axe_tick_task)->arg = (sc), (&sc->axe_tick_task
)->type = (0), (&sc->axe_tick_task)->state = 0x0
)
;
704 rw_init(&sc->axe_mii_lock, "axemii")_rw_init_flags(&sc->axe_mii_lock, "axemii", 0, ((void *
)0))
;
705 usb_init_task(&sc->axe_stop_task, (void (*)(void *))axe_stop, sc,((&sc->axe_stop_task)->fun = ((void (*)(void *))axe_stop
), (&sc->axe_stop_task)->arg = (sc), (&sc->axe_stop_task
)->type = (0), (&sc->axe_stop_task)->state = 0x0
)
706 USB_TASK_TYPE_GENERIC)((&sc->axe_stop_task)->fun = ((void (*)(void *))axe_stop
), (&sc->axe_stop_task)->arg = (sc), (&sc->axe_stop_task
)->type = (0), (&sc->axe_stop_task)->state = 0x0
)
;
707
708 sc->axe_product = uaa->product;
709 sc->axe_vendor = uaa->vendor;
710
711 id = usbd_get_interface_descriptor(sc->axe_iface);
712
713 /* decide on what our bufsize will be */
714 if (sc->axe_flags & (AX1780x0001 | AX7720x0002))
715 sc->axe_bufsz = (sc->axe_udev->speed == USB_SPEED_HIGH3) ?
716 AXE_178_MAX_BUFSZ16384 : AXE_178_MIN_BUFSZ2048;
717 else
718 sc->axe_bufsz = AXE_172_BUFSZ1536;
719
720 /* Find endpoints. */
721 for (i = 0; i < id->bNumEndpoints; i++) {
722 ed = usbd_interface2endpoint_descriptor(sc->axe_iface, i);
723 if (!ed) {
724 printf("%s: couldn't get ep %d\n",
725 sc->axe_dev.dv_xname, i);
726 return;
727 }
728 if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80 &&
729 UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02) {
730 sc->axe_ed[AXE_ENDPT_RX0x0] = ed->bEndpointAddress;
731 } else if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_OUT0x00 &&
732 UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02) {
733 sc->axe_ed[AXE_ENDPT_TX0x1] = ed->bEndpointAddress;
734 } else if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80 &&
735 UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_INTERRUPT0x03) {
736 sc->axe_ed[AXE_ENDPT_INTR0x2] = ed->bEndpointAddress;
737 }
738 }
739
740 s = splnet()splraise(0x7);
741
742 /* We need the PHYID for init dance in some cases */
743 axe_cmd(sc, AXE_CMD_READ_PHYID0x2019, 0, 0, (void *)&sc->axe_phyaddrs);
744
745 DPRINTF((" phyaddrs[0]: %x phyaddrs[1]: %x\n",
746 sc->axe_phyaddrs[0], sc->axe_phyaddrs[1]));
747
748 sc->axe_phyno = axe_get_phyno(sc, AXE_PHY_SEL_PRI1);
749 if (sc->axe_phyno == -1)
750 sc->axe_phyno = axe_get_phyno(sc, AXE_PHY_SEL_SEC0);
751 if (sc->axe_phyno == -1) {
752 printf("%s:", sc->axe_dev.dv_xname);
753 printf(" no valid PHY address found, assuming PHY address 0\n");
754 sc->axe_phyno = 0;
755 }
756
757 DPRINTF((" get_phyno %d\n", sc->axe_phyno));
758
759 if (sc->axe_flags & AX1780x0001)
760 axe_ax88178_init(sc);
761 else if (sc->axe_flags & AX7720x0002)
762 axe_ax88772_init(sc);
763
764 /*
765 * Get station address.
766 */
767 if (sc->axe_flags & (AX1780x0001 | AX7720x0002))
768 axe_cmd(sc, AXE_178_CMD_READ_NODEID0x6013, 0, 0, &eaddr);
769 else
770 axe_cmd(sc, AXE_172_CMD_READ_NODEID0x6017, 0, 0, &eaddr);
771
772 if (sc->axe_flags & AX772B0x0004)
773 axe_ax88772b_nodeid(sc, eaddr);
774
775 /*
776 * Load IPG values
777 */
778 axe_cmd(sc, AXE_CMD_READ_IPG0120x3011, 0, 0, (void *)&sc->axe_ipgs);
779
780 /*
781 * An ASIX chip was detected. Inform the world.
782 */
783 printf("%s:", sc->axe_dev.dv_xname);
784 if (sc->axe_flags & AX1780x0001)
785 printf(" AX88178");
786 else if (sc->axe_flags & AX772B0x0004)
787 printf(" AX88772B");
788 else if (sc->axe_flags & AX7720x0002)
789 printf(" AX88772");
790 else
791 printf(" AX88172");
792 printf(", address %s\n", ether_sprintf(eaddr));
793
794 bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN6);
795
796 /* Initialize interface info.*/
797 ifp = &sc->arpcom.ac_if;
798 ifp->if_softc = sc;
799 strlcpy(ifp->if_xname, devname, IFNAMSIZ16);
800 ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
801 ifp->if_ioctl = axe_ioctl;
802 ifp->if_start = axe_start;
803 ifp->if_watchdog = axe_watchdog;
804
805 ifp->if_capabilitiesif_data.ifi_capabilities = IFCAP_VLAN_MTU0x00000010;
806
807 /* Initialize MII/media info. */
808 mii = &sc->axe_mii;
809 mii->mii_ifp = ifp;
810 mii->mii_readreg = axe_miibus_readreg;
811 mii->mii_writereg = axe_miibus_writereg;
812 mii->mii_statchg = axe_miibus_statchg;
813 mii->mii_flags = MIIF_AUTOTSLEEP0x0010;
814
815 ifmedia_init(&mii->mii_media, 0, axe_ifmedia_upd, axe_ifmedia_sts);
816 mii_attach(self, mii, 0xffffffff, MII_PHY_ANY-1, MII_OFFSET_ANY-1, 0);
817
818 if (LIST_FIRST(&mii->mii_phys)((&mii->mii_phys)->lh_first) == NULL((void *)0)) {
819 ifmedia_add(&mii->mii_media, IFM_ETHER0x0000000000000100ULL | IFM_NONE2ULL, 0, NULL((void *)0));
820 ifmedia_set(&mii->mii_media, IFM_ETHER0x0000000000000100ULL | IFM_NONE2ULL);
821 } else
822 ifmedia_set(&mii->mii_media, IFM_ETHER0x0000000000000100ULL | IFM_AUTO0ULL);
823
824 /* Attach the interface. */
825 if_attach(ifp);
826 ether_ifattach(ifp);
827
828 timeout_set(&sc->axe_stat_ch, axe_tick, sc);
829
830 splx(s)spllower(s);
831}
832
833int
834axe_detach(struct device *self, int flags)
835{
836 struct axe_softc *sc = (struct axe_softc *)self;
837 int s;
838 struct ifnet *ifp = GET_IFP(sc)(&(sc)->arpcom.ac_if);
839
840 DPRINTFN(2,("%s: %s: enter\n", sc->axe_dev.dv_xname, __func__));
841
842 if (timeout_initialized(&sc->axe_stat_ch)((&sc->axe_stat_ch)->to_flags & 0x04))
843 timeout_del(&sc->axe_stat_ch);
844
845 if (sc->axe_ep[AXE_ENDPT_TX0x1] != NULL((void *)0))
846 usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_TX0x1]);
847 if (sc->axe_ep[AXE_ENDPT_RX0x0] != NULL((void *)0))
848 usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_RX0x0]);
849 if (sc->axe_ep[AXE_ENDPT_INTR0x2] != NULL((void *)0))
850 usbd_abort_pipe(sc->axe_ep[AXE_ENDPT_INTR0x2]);
851
852 /*
853 * Remove any pending tasks. They cannot be executing because they run
854 * in the same thread as detach.
855 */
856 usb_rem_task(sc->axe_udev, &sc->axe_tick_task);
857 usb_rem_task(sc->axe_udev, &sc->axe_stop_task);
858
859 s = splusb()splraise(0x5);
860
861 if (--sc->axe_refcnt >= 0) {
862 /* Wait for processes to go away */
863 usb_detach_wait(&sc->axe_dev);
864 }
865
866 if (ifp->if_flags & IFF_RUNNING0x40)
867 axe_stop(sc);
868
869 mii_detach(&sc->axe_mii, MII_PHY_ANY-1, MII_OFFSET_ANY-1);
870 ifmedia_delete_instance(&sc->axe_mii.mii_media, IFM_INST_ANY((uint64_t) -1));
871 if (ifp->if_softc != NULL((void *)0)) {
872 ether_ifdetach(ifp);
873 if_detach(ifp);
874 }
875
876#ifdef DIAGNOSTIC1
877 if (sc->axe_ep[AXE_ENDPT_TX0x1] != NULL((void *)0) ||
878 sc->axe_ep[AXE_ENDPT_RX0x0] != NULL((void *)0) ||
879 sc->axe_ep[AXE_ENDPT_INTR0x2] != NULL((void *)0))
880 printf("%s: detach has active endpoints\n",
881 sc->axe_dev.dv_xname);
882#endif
883
884 splx(s)spllower(s);
885
886 return (0);
887}
888
889struct mbuf *
890axe_newbuf(void)
891{
892 struct mbuf *m;
893
894 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
895 if (m == NULL((void *)0))
896 return (NULL((void *)0));
897
898 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
899 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
900 m_freem(m);
901 return (NULL((void *)0));
902 }
903
904 m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = MCLBYTES(1 << 11);
905 m_adj(m, ETHER_ALIGN2);
906
907 return (m);
908}
909
910int
911axe_rx_list_init(struct axe_softc *sc)
912{
913 struct axe_cdata *cd;
914 struct axe_chain *c;
915 int i;
916
917 DPRINTF(("%s: %s: enter\n", sc->axe_dev.dv_xname, __func__));
918
919 cd = &sc->axe_cdata;
920 for (i = 0; i < AXE_RX_LIST_CNT1; i++) {
921 c = &cd->axe_rx_chain[i];
922 c->axe_sc = sc;
923 c->axe_idx = i;
924 c->axe_mbuf = NULL((void *)0);
925 if (c->axe_xfer == NULL((void *)0)) {
926 c->axe_xfer = usbd_alloc_xfer(sc->axe_udev);
927 if (c->axe_xfer == NULL((void *)0))
928 return (ENOBUFS55);
929 c->axe_buf = usbd_alloc_buffer(c->axe_xfer,
930 sc->axe_bufsz);
931 if (c->axe_buf == NULL((void *)0)) {
932 usbd_free_xfer(c->axe_xfer);
933 return (ENOBUFS55);
934 }
935 }
936 }
937
938 return (0);
939}
940
941int
942axe_tx_list_init(struct axe_softc *sc)
943{
944 struct axe_cdata *cd;
945 struct axe_chain *c;
946 int i;
947
948 DPRINTF(("%s: %s: enter\n", sc->axe_dev.dv_xname, __func__));
949
950 cd = &sc->axe_cdata;
951 for (i = 0; i < AXE_TX_LIST_CNT1; i++) {
952 c = &cd->axe_tx_chain[i];
953 c->axe_sc = sc;
954 c->axe_idx = i;
955 c->axe_mbuf = NULL((void *)0);
956 if (c->axe_xfer == NULL((void *)0)) {
957 c->axe_xfer = usbd_alloc_xfer(sc->axe_udev);
958 if (c->axe_xfer == NULL((void *)0))
959 return (ENOBUFS55);
960 c->axe_buf = usbd_alloc_buffer(c->axe_xfer,
961 sc->axe_bufsz);
962 if (c->axe_buf == NULL((void *)0)) {
963 usbd_free_xfer(c->axe_xfer);
964 return (ENOBUFS55);
965 }
966 }
967 }
968
969 return (0);
970}
971
972/*
973 * A frame has been uploaded: pass the resulting mbuf chain up to
974 * the higher level protocols.
975 */
976void
977axe_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
978{
979 struct axe_chain *c = (struct axe_chain *)priv;
980 struct axe_softc *sc = c->axe_sc;
981 struct ifnet *ifp = GET_IFP(sc)(&(sc)->arpcom.ac_if);
982 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
983 u_char *buf = c->axe_buf;
984 u_int32_t total_len;
985 u_int16_t pktlen = 0;
986 struct mbuf *m;
987 struct axe_sframe_hdr hdr;
988 int s;
989
990 DPRINTFN(10,("%s: %s: enter\n", sc->axe_dev.dv_xname,__func__));
991
992 if (usbd_is_dying(sc->axe_udev))
993 return;
994
995 if (!(ifp->if_flags & IFF_RUNNING0x40))
996 return;
997
998 if (status != USBD_NORMAL_COMPLETION) {
999 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1000 return;
1001 if (usbd_ratecheck(&sc->axe_rx_notice)) {
1002 printf("%s: usb errors on rx: %s\n",
1003 sc->axe_dev.dv_xname, usbd_errstr(status));
1004 }
1005 if (status == USBD_STALLED)
1006 usbd_clear_endpoint_stall_async(sc->axe_ep[AXE_ENDPT_RX0x0]);
1007 goto done;
1008 }
1009
1010 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &total_len, NULL((void *)0));
1011
1012 do {
1013 if (sc->axe_flags & (AX1780x0001 | AX7720x0002)) {
1014 if (total_len < sizeof(hdr)) {
1015 ifp->if_ierrorsif_data.ifi_ierrors++;
1016 goto done;
1017 }
1018
1019 buf += pktlen;
1020
1021 memcpy(&hdr, buf, sizeof(hdr))__builtin_memcpy((&hdr), (buf), (sizeof(hdr)));
1022 total_len -= sizeof(hdr);
1023
1024 if (((letoh16(hdr.len)((__uint16_t)(hdr.len)) & AXE_RH1M_RXLEN_MASK0x07ff) ^
1025 (letoh16(hdr.ilen)((__uint16_t)(hdr.ilen)) & AXE_RH1M_RXLEN_MASK0x07ff)) !=
1026 AXE_RH1M_RXLEN_MASK0x07ff) {
1027 ifp->if_ierrorsif_data.ifi_ierrors++;
1028 goto done;
1029 }
1030 pktlen = letoh16(hdr.len)((__uint16_t)(hdr.len)) & AXE_RH1M_RXLEN_MASK0x07ff;
1031 if (pktlen > total_len) {
1032 ifp->if_ierrorsif_data.ifi_ierrors++;
1033 goto done;
1034 }
1035
1036 buf += sizeof(hdr);
1037
1038 if ((pktlen % 2) != 0)
1039 pktlen++;
1040
1041 if (total_len < pktlen)
1042 total_len = 0;
1043 else
1044 total_len -= pktlen;
1045 } else {
1046 pktlen = total_len; /* crc on the end? */
1047 total_len = 0;
1048 }
1049
1050 m = axe_newbuf();
1051 if (m == NULL((void *)0)) {
1052 ifp->if_ierrorsif_data.ifi_ierrors++;
1053 goto done;
1054 }
1055
1056 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = pktlen;
1057
1058 memcpy(mtod(m, char *), buf, pktlen)__builtin_memcpy((((char *)((m)->m_hdr.mh_data))), (buf), (
pktlen))
;
1059
1060 ml_enqueue(&ml, m);
1061
1062 } while (total_len > 0);
1063
1064done:
1065 /* push the packet up */
1066 s = splnet()splraise(0x7);
1067 if_input(ifp, &ml);
1068 splx(s)spllower(s);
1069
1070 memset(c->axe_buf, 0, sc->axe_bufsz)__builtin_memset((c->axe_buf), (0), (sc->axe_bufsz));
1071
1072 /* Setup new transfer. */
1073 usbd_setup_xfer(xfer, sc->axe_ep[AXE_ENDPT_RX0x0],
1074 c, c->axe_buf, sc->axe_bufsz,
1075 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
1076 USBD_NO_TIMEOUT0, axe_rxeof);
1077 usbd_transfer(xfer);
1078
1079 DPRINTFN(10,("%s: %s: start rx\n", sc->axe_dev.dv_xname, __func__));
1080
1081 return;
1082}
1083
1084/*
1085 * A frame was downloaded to the chip. It's safe for us to clean up
1086 * the list buffers.
1087 */
1088
1089void
1090axe_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1091{
1092 struct axe_softc *sc;
1093 struct axe_chain *c;
1094 struct ifnet *ifp;
1095 int s;
1096
1097 c = priv;
1098 sc = c->axe_sc;
1099 ifp = &sc->arpcom.ac_if;
1100
1101 if (usbd_is_dying(sc->axe_udev))
1102 return;
1103
1104 s = splnet()splraise(0x7);
1105
1106 if (status != USBD_NORMAL_COMPLETION) {
1107 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1108 splx(s)spllower(s);
1109 return;
1110 }
1111 ifp->if_oerrorsif_data.ifi_oerrors++;
1112 printf("axe%d: usb error on tx: %s\n", sc->axe_unit,
1113 usbd_errstr(status));
1114 if (status == USBD_STALLED)
1115 usbd_clear_endpoint_stall_async(sc->axe_ep[AXE_ENDPT_TX0x1]);
1116 splx(s)spllower(s);
1117 return;
1118 }
1119
1120 ifp->if_timer = 0;
1121 ifq_clr_oactive(&ifp->if_snd);
1122
1123 m_freem(c->axe_mbuf);
1124 c->axe_mbuf = NULL((void *)0);
1125
1126 if (ifq_empty(&ifp->if_snd)(((&ifp->if_snd)->ifq_len) == 0) == 0)
1127 axe_start(ifp);
1128
1129 splx(s)spllower(s);
1130 return;
1131}
1132
1133void
1134axe_tick(void *xsc)
1135{
1136 struct axe_softc *sc = xsc;
1137
1138 if (sc == NULL((void *)0))
1139 return;
1140
1141 DPRINTFN(0xff, ("%s: %s: enter\n", sc->axe_dev.dv_xname,
1142 __func__));
1143
1144 if (usbd_is_dying(sc->axe_udev))
1145 return;
1146
1147 /* Perform periodic stuff in process context */
1148 usb_add_task(sc->axe_udev, &sc->axe_tick_task);
1149
1150}
1151
1152void
1153axe_tick_task(void *xsc)
1154{
1155 int s;
1156 struct axe_softc *sc;
1157 struct ifnet *ifp;
1158 struct mii_data *mii;
1159
1160 sc = xsc;
1161
1162 if (sc == NULL((void *)0))
1163 return;
1164
1165 if (usbd_is_dying(sc->axe_udev))
1166 return;
1167
1168 ifp = GET_IFP(sc)(&(sc)->arpcom.ac_if);
1169 mii = GET_MII(sc)(&(sc)->axe_mii);
1170 if (mii == NULL((void *)0))
1171 return;
1172
1173 s = splnet()splraise(0x7);
1174
1175 mii_tick(mii);
1176 if (sc->axe_link == 0)
1177 axe_miibus_statchg(&sc->axe_dev);
1178 timeout_add_sec(&sc->axe_stat_ch, 1);
1179
1180 splx(s)spllower(s);
1181}
1182
1183int
1184axe_encap(struct axe_softc *sc, struct mbuf *m, int idx)
1185{
1186 struct axe_chain *c;
1187 usbd_status err;
1188 struct axe_sframe_hdr hdr;
1189 int length, boundary;
1190
1191 c = &sc->axe_cdata.axe_tx_chain[idx];
1192
1193 if (sc->axe_flags & (AX1780x0001 | AX7720x0002)) {
1194 boundary = (sc->axe_udev->speed == USB_SPEED_HIGH3) ? 512 : 64;
1195
1196 hdr.len = htole16(m->m_pkthdr.len)((__uint16_t)(m->M_dat.MH.MH_pkthdr.len));
1197 hdr.ilen = ~hdr.len;
1198
1199 memcpy(c->axe_buf, &hdr, sizeof(hdr))__builtin_memcpy((c->axe_buf), (&hdr), (sizeof(hdr)));
1200 length = sizeof(hdr);
1201
1202 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, c->axe_buf + length);
1203 length += m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1204
1205 if ((length % boundary) == 0) {
1206 hdr.len = 0x0000;
1207 hdr.ilen = 0xffff;
1208 memcpy(c->axe_buf + length, &hdr, sizeof(hdr))__builtin_memcpy((c->axe_buf + length), (&hdr), (sizeof
(hdr)))
;
1209 length += sizeof(hdr);
1210 }
1211
1212 } else {
1213 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, c->axe_buf);
1214 length = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1215 }
1216
1217 c->axe_mbuf = m;
1218
1219 usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_TX0x1],
1220 c, c->axe_buf, length, USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01,
1221 10000, axe_txeof);
1222
1223 /* Transmit */
1224 err = usbd_transfer(c->axe_xfer);
1225 if (err != USBD_IN_PROGRESS) {
1226 c->axe_mbuf = NULL((void *)0);
1227 axe_stop(sc);
1228 return(EIO5);
1229 }
1230
1231 sc->axe_cdata.axe_tx_cnt++;
1232
1233 return(0);
1234}
1235
1236void
1237axe_start(struct ifnet *ifp)
1238{
1239 struct axe_softc *sc;
1240 struct mbuf *m_head = NULL((void *)0);
1241
1242 sc = ifp->if_softc;
1243
1244 if (!sc->axe_link)
1245 return;
1246
1247 if (ifq_is_oactive(&ifp->if_snd))
1248 return;
1249
1250 m_head = ifq_dequeue(&ifp->if_snd);
1251 if (m_head == NULL((void *)0))
1252 return;
1253
1254 if (axe_encap(sc, m_head, 0)) {
1255 m_freem(m_head);
1256 ifq_set_oactive(&ifp->if_snd);
1257 return;
1258 }
1259
1260 /*
1261 * If there's a BPF listener, bounce a copy of this frame
1262 * to him.
1263 */
1264#if NBPFILTER1 > 0
1265 if (ifp->if_bpf)
1266 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT(1 << 1));
1267#endif
1268
1269 ifq_set_oactive(&ifp->if_snd);
1270
1271 /*
1272 * Set a timeout in case the chip goes out to lunch.
1273 */
1274 ifp->if_timer = 5;
1275
1276 return;
1277}
1278
1279void
1280axe_init(void *xsc)
1281{
1282 struct axe_softc *sc = xsc;
1283 struct ifnet *ifp = &sc->arpcom.ac_if;
1284 struct axe_chain *c;
1285 usbd_status err;
1286 uWord urxmode;
1287 int rxmode;
1288 int i, s;
1289
1290 s = splnet()splraise(0x7);
1291
1292 /*
1293 * Cancel pending I/O and free all RX/TX buffers.
1294 */
1295 axe_reset(sc);
1296
1297 /* set MAC address */
1298 if (sc->axe_flags & (AX1780x0001 | AX7720x0002))
7
Assuming the condition is true
8
Taking true branch
1299 axe_cmd(sc, AXE_178_CMD_WRITE_NODEID0x6114, 0, 0,
1300 &sc->arpcom.ac_enaddr);
1301
1302 /* Enable RX logic. */
1303
1304 /* Init RX ring. */
1305 if (axe_rx_list_init(sc) == ENOBUFS55) {
9
Taking false branch
1306 printf("axe%d: rx list init failed\n", sc->axe_unit);
1307 splx(s)spllower(s);
1308 return;
1309 }
1310
1311 /* Init TX ring. */
1312 if (axe_tx_list_init(sc) == ENOBUFS55) {
10
Taking false branch
1313 printf("axe%d: tx list init failed\n", sc->axe_unit);
1314 splx(s)spllower(s);
1315 return;
1316 }
1317
1318 /* Set transmitter IPG values */
1319 if (sc->axe_flags & (AX1780x0001 | AX7720x0002))
11
Taking true branch
1320 axe_cmd(sc, AXE_178_CMD_WRITE_IPG0120x0112, sc->axe_ipgs[2],
1321 (sc->axe_ipgs[1] << 8) | (sc->axe_ipgs[0]), NULL((void *)0));
1322 else {
1323 axe_cmd(sc, AXE_172_CMD_WRITE_IPG00x0112, 0, sc->axe_ipgs[0], NULL((void *)0));
1324 axe_cmd(sc, AXE_172_CMD_WRITE_IPG10x0113, 0, sc->axe_ipgs[1], NULL((void *)0));
1325 axe_cmd(sc, AXE_172_CMD_WRITE_IPG20x0114, 0, sc->axe_ipgs[2], NULL((void *)0));
1326 }
1327
1328 /* Program promiscuous mode and multicast filters. */
1329 axe_iff(sc);
1330
1331 /* Enable receiver, set RX mode */
1332 axe_cmd(sc, AXE_CMD_RXCTL_READ0x200F, 0, 0, urxmode);
12
Calling 'axe_cmd'
15
Returning from 'axe_cmd'
1333 rxmode = UGETW(urxmode)(*(u_int16_t *)(urxmode));
16
Assigned value is garbage or undefined
1334 rxmode |= AXE_RXCMD_ENABLE0x0080;
1335 if (sc->axe_flags & AX772B0x0004)
1336 rxmode |= AXE_772B_RXCMD_RH1M0x0100;
1337 else if (sc->axe_flags & (AX1780x0001 | AX7720x0002)) {
1338 if (sc->axe_udev->speed == USB_SPEED_HIGH3) {
1339 /* largest possible USB buffer size for AX88178 */
1340 rxmode |= AXE_178_RXCMD_MFB0x0300;
1341 }
1342 }
1343 axe_cmd(sc, AXE_CMD_RXCTL_WRITE0x0110, 0, rxmode, NULL((void *)0));
1344
1345 /* Open RX and TX pipes. */
1346 err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_RX0x0],
1347 USBD_EXCLUSIVE_USE0x01, &sc->axe_ep[AXE_ENDPT_RX0x0]);
1348 if (err) {
1349 printf("axe%d: open rx pipe failed: %s\n",
1350 sc->axe_unit, usbd_errstr(err));
1351 splx(s)spllower(s);
1352 return;
1353 }
1354
1355 err = usbd_open_pipe(sc->axe_iface, sc->axe_ed[AXE_ENDPT_TX0x1],
1356 USBD_EXCLUSIVE_USE0x01, &sc->axe_ep[AXE_ENDPT_TX0x1]);
1357 if (err) {
1358 printf("axe%d: open tx pipe failed: %s\n",
1359 sc->axe_unit, usbd_errstr(err));
1360 splx(s)spllower(s);
1361 return;
1362 }
1363
1364 /* Start up the receive pipe. */
1365 for (i = 0; i < AXE_RX_LIST_CNT1; i++) {
1366 c = &sc->axe_cdata.axe_rx_chain[i];
1367 usbd_setup_xfer(c->axe_xfer, sc->axe_ep[AXE_ENDPT_RX0x0],
1368 c, c->axe_buf, sc->axe_bufsz,
1369 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
1370 USBD_NO_TIMEOUT0, axe_rxeof);
1371 usbd_transfer(c->axe_xfer);
1372 }
1373
1374 sc->axe_link = 0;
1375 ifp->if_flags |= IFF_RUNNING0x40;
1376 ifq_clr_oactive(&ifp->if_snd);
1377
1378 splx(s)spllower(s);
1379
1380 timeout_add_sec(&sc->axe_stat_ch, 1);
1381 return;
1382}
1383
1384int
1385axe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1386{
1387 struct axe_softc *sc = ifp->if_softc;
1388 struct ifreq *ifr = (struct ifreq *)data;
1389 int s, error = 0;
1390
1391 s = splnet()splraise(0x7);
1392
1393 switch(cmd) {
1
Control jumps to 'case 2149607696:' at line 1400
1394 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
1395 ifp->if_flags |= IFF_UP0x1;
1396 if (!(ifp->if_flags & IFF_RUNNING0x40))
1397 axe_init(sc);
1398 break;
1399
1400 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
1401 if (ifp->if_flags & IFF_UP0x1) {
2
Assuming the condition is true
3
Taking true branch
1402 if (ifp->if_flags & IFF_RUNNING0x40)
4
Assuming the condition is false
5
Taking false branch
1403 error = ENETRESET52;
1404 else
1405 axe_init(sc);
6
Calling 'axe_init'
1406 } else {
1407 if (ifp->if_flags & IFF_RUNNING0x40)
1408 axe_stop(sc);
1409 }
1410 break;
1411
1412 case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
:
1413 case SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((55)))
:
1414 error = ifmedia_ioctl(ifp, ifr, &sc->axe_mii.mii_media, cmd);
1415 break;
1416
1417 default:
1418 error = ether_ioctl(ifp, &sc->arpcom, cmd, data);
1419 }
1420
1421 if (error == ENETRESET52) {
1422 if (ifp->if_flags & IFF_RUNNING0x40)
1423 axe_iff(sc);
1424 error = 0;
1425 }
1426
1427 splx(s)spllower(s);
1428 return(error);
1429}
1430
1431void
1432axe_watchdog(struct ifnet *ifp)
1433{
1434 struct axe_softc *sc;
1435 struct axe_chain *c;
1436 usbd_status stat;
1437 int s;
1438
1439 sc = ifp->if_softc;
1440
1441 ifp->if_oerrorsif_data.ifi_oerrors++;
1442 printf("axe%d: watchdog timeout\n", sc->axe_unit);
1443
1444 s = splusb()splraise(0x5);
1445 c = &sc->axe_cdata.axe_tx_chain[0];
1446 usbd_get_xfer_status(c->axe_xfer, NULL((void *)0), NULL((void *)0), NULL((void *)0), &stat);
1447 axe_txeof(c->axe_xfer, c, stat);
1448
1449 if (!ifq_empty(&ifp->if_snd)(((&ifp->if_snd)->ifq_len) == 0))
1450 axe_start(ifp);
1451 splx(s)spllower(s);
1452}
1453
1454/*
1455 * Stop the adapter and free any mbufs allocated to the
1456 * RX and TX lists.
1457 */
1458void
1459axe_stop(struct axe_softc *sc)
1460{
1461 usbd_status err;
1462 struct ifnet *ifp;
1463 int i;
1464
1465 axe_reset(sc);
1466
1467 ifp = &sc->arpcom.ac_if;
1468 ifp->if_timer = 0;
1469 ifp->if_flags &= ~IFF_RUNNING0x40;
1470 ifq_clr_oactive(&ifp->if_snd);
1471
1472 timeout_del(&sc->axe_stat_ch);
1473
1474 /* Stop transfers. */
1475 if (sc->axe_ep[AXE_ENDPT_RX0x0] != NULL((void *)0)) {
1476 err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_RX0x0]);
1477 if (err) {
1478 printf("axe%d: close rx pipe failed: %s\n",
1479 sc->axe_unit, usbd_errstr(err));
1480 }
1481 sc->axe_ep[AXE_ENDPT_RX0x0] = NULL((void *)0);
1482 }
1483
1484 if (sc->axe_ep[AXE_ENDPT_TX0x1] != NULL((void *)0)) {
1485 err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_TX0x1]);
1486 if (err) {
1487 printf("axe%d: close tx pipe failed: %s\n",
1488 sc->axe_unit, usbd_errstr(err));
1489 }
1490 sc->axe_ep[AXE_ENDPT_TX0x1] = NULL((void *)0);
1491 }
1492
1493 if (sc->axe_ep[AXE_ENDPT_INTR0x2] != NULL((void *)0)) {
1494 err = usbd_close_pipe(sc->axe_ep[AXE_ENDPT_INTR0x2]);
1495 if (err) {
1496 printf("axe%d: close intr pipe failed: %s\n",
1497 sc->axe_unit, usbd_errstr(err));
1498 }
1499 sc->axe_ep[AXE_ENDPT_INTR0x2] = NULL((void *)0);
1500 }
1501
1502 /* Free RX resources. */
1503 for (i = 0; i < AXE_RX_LIST_CNT1; i++) {
1504 if (sc->axe_cdata.axe_rx_chain[i].axe_mbuf != NULL((void *)0)) {
1505 m_freem(sc->axe_cdata.axe_rx_chain[i].axe_mbuf);
1506 sc->axe_cdata.axe_rx_chain[i].axe_mbuf = NULL((void *)0);
1507 }
1508 if (sc->axe_cdata.axe_rx_chain[i].axe_xfer != NULL((void *)0)) {
1509 usbd_free_xfer(sc->axe_cdata.axe_rx_chain[i].axe_xfer);
1510 sc->axe_cdata.axe_rx_chain[i].axe_xfer = NULL((void *)0);
1511 }
1512 }
1513
1514 /* Free TX resources. */
1515 for (i = 0; i < AXE_TX_LIST_CNT1; i++) {
1516 if (sc->axe_cdata.axe_tx_chain[i].axe_mbuf != NULL((void *)0)) {
1517 m_freem(sc->axe_cdata.axe_tx_chain[i].axe_mbuf);
1518 sc->axe_cdata.axe_tx_chain[i].axe_mbuf = NULL((void *)0);
1519 }
1520 if (sc->axe_cdata.axe_tx_chain[i].axe_xfer != NULL((void *)0)) {
1521 usbd_free_xfer(sc->axe_cdata.axe_tx_chain[i].axe_xfer);
1522 sc->axe_cdata.axe_tx_chain[i].axe_xfer = NULL((void *)0);
1523 }
1524 }
1525
1526 sc->axe_link = 0;
1527}
1528