Bug Summary

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

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_axen.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_axen.c
1/* $OpenBSD: if_axen.c,v 1.32 2024/01/04 08:41:59 kevlo Exp $ */
2
3/*
4 * Copyright (c) 2013 Yojiro UO <yuo@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 * ASIX Electronics AX88178a USB 2.0 ethernet and
21 * AX88179/AX88179a USB 3.0 Ethernet driver.
22 */
23
24#include "bpfilter.h"
25
26#include <sys/param.h>
27#include <sys/systm.h>
28#include <sys/sockio.h>
29#include <sys/rwlock.h>
30#include <sys/mbuf.h>
31#include <sys/kernel.h>
32#include <sys/socket.h>
33
34#include <sys/device.h>
35
36#include <machine/bus.h>
37
38#include <net/if.h>
39#include <net/if_media.h>
40
41#if NBPFILTER1 > 0
42#include <net/bpf.h>
43#endif
44
45#include <netinet/in.h>
46#include <netinet/if_ether.h>
47
48#include <dev/mii/mii.h>
49#include <dev/mii/miivar.h>
50
51#include <dev/usb/usb.h>
52#include <dev/usb/usbdi.h>
53#include <dev/usb/usbdi_util.h>
54#include <dev/usb/usbdivar.h>
55#include <dev/usb/usbdevs.h>
56
57#include <dev/usb/if_axenreg.h>
58
59#ifdef AXEN_DEBUG
60#define DPRINTF(x) do { if (axendebug) printf x; } while (0)
61#define DPRINTFN(n,x) do { if (axendebug >= (n)) printf x; } while (0)
62int axendebug = 0;
63#else
64#define DPRINTF(x)
65#define DPRINTFN(n,x)
66#endif
67
68#define AXEN_TOE /* enable checksum offload function */
69
70/*
71 * Various supported device vendors/products.
72 */
73const struct axen_type axen_devs[] = {
74#if 0 /* not tested */
75 { { USB_VENDOR_ASIX0x0b95, USB_PRODUCT_ASIX_AX88178A}, AX178A0x0001 },
76#endif
77 { { USB_VENDOR_ASIX0x0b95, USB_PRODUCT_ASIX_AX881790x1790}, AX1790x0002 },
78 { { USB_VENDOR_DLINK0x2001, USB_PRODUCT_DLINK_DUB13120x4a00}, AX1790x0002 },
79 { { USB_VENDOR_LENOVO0x17ef, USB_PRODUCT_LENOVO_AX881790x304b}, AX1790x0002 },
80 { { USB_VENDOR_SAMSUNG20x04e8, USB_PRODUCT_SAMSUNG2_AX881790xa100}, AX1790x0002 },
81 { { USB_VENDOR_SITECOMEU0x0df6, USB_PRODUCT_SITECOMEU_LN0320x0072}, AX1790x0002 }
82};
83
84#define axen_lookup(v, p)((struct axen_type *)usbd_match_device((const struct usb_devno
*)(axen_devs), sizeof (axen_devs) / sizeof ((axen_devs)[0]),
sizeof ((axen_devs)[0]), (v), (p)))
((struct axen_type *)usb_lookup(axen_devs, v, p)usbd_match_device((const struct usb_devno *)(axen_devs), sizeof
(axen_devs) / sizeof ((axen_devs)[0]), sizeof ((axen_devs)[0
]), (v), (p))
)
85
86int axen_match(struct device *, void *, void *);
87void axen_attach(struct device *, struct device *, void *);
88int axen_detach(struct device *, int);
89
90struct cfdriver axen_cd = {
91 NULL((void *)0), "axen", DV_IFNET
92};
93
94const struct cfattach axen_ca = {
95 sizeof(struct axen_softc), axen_match, axen_attach, axen_detach
96};
97
98int axen_tx_list_init(struct axen_softc *);
99int axen_rx_list_init(struct axen_softc *);
100struct mbuf *axen_newbuf(void);
101int axen_encap(struct axen_softc *, struct mbuf *, int);
102void axen_rxeof(struct usbd_xfer *, void *, usbd_status);
103void axen_txeof(struct usbd_xfer *, void *, usbd_status);
104void axen_tick(void *);
105void axen_tick_task(void *);
106void axen_start(struct ifnet *);
107int axen_ioctl(struct ifnet *, u_long, caddr_t);
108void axen_init(void *);
109void axen_stop(struct axen_softc *);
110void axen_watchdog(struct ifnet *);
111int axen_miibus_readreg(struct device *, int, int);
112void axen_miibus_writereg(struct device *, int, int, int);
113void axen_miibus_statchg(struct device *);
114int axen_cmd(struct axen_softc *, int, int, int, void *);
115int axen_ifmedia_upd(struct ifnet *);
116void axen_ifmedia_sts(struct ifnet *, struct ifmediareq *);
117void axen_reset(struct axen_softc *sc);
118void axen_iff(struct axen_softc *);
119void axen_lock_mii(struct axen_softc *sc);
120void axen_unlock_mii(struct axen_softc *sc);
121
122void axen_ax88179_init(struct axen_softc *);
123
124/* Get exclusive access to the MII registers */
125void
126axen_lock_mii(struct axen_softc *sc)
127{
128 sc->axen_refcnt++;
129 rw_enter_write(&sc->axen_mii_lock);
130}
131
132void
133axen_unlock_mii(struct axen_softc *sc)
134{
135 rw_exit_write(&sc->axen_mii_lock);
136 if (--sc->axen_refcnt < 0)
137 usb_detach_wakeup(&sc->axen_dev);
138}
139
140int
141axen_cmd(struct axen_softc *sc, int cmd, int index, int val, void *buf)
142{
143 usb_device_request_t req;
144 usbd_status err;
145
146 if (usbd_is_dying(sc->axen_udev))
10
Assuming the condition is true
11
Taking true branch
147 return 0;
148
149 if (AXEN_CMD_DIR(cmd)(((cmd) & 0x0F00) >> 8))
150 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
151 else
152 req.bmRequestType = UT_READ_VENDOR_DEVICE(0x80 | 0x40 | 0x00);
153 req.bRequest = AXEN_CMD_CMD(cmd)((cmd) & 0x00FF);
154 USETW(req.wValue, val)(*(u_int16_t *)(req.wValue) = (val));
155 USETW(req.wIndex, index)(*(u_int16_t *)(req.wIndex) = (index));
156 USETW(req.wLength, AXEN_CMD_LEN(cmd))(*(u_int16_t *)(req.wLength) = ((((cmd) & 0xF000) >>
12)))
;
157
158 err = usbd_do_request(sc->axen_udev, &req, buf);
159 DPRINTFN(5, ("axen_cmd: cmd 0x%04x val 0x%04x len %d\n",
160 cmd, val, AXEN_CMD_LEN(cmd)));
161
162 if (err) {
163 DPRINTF(("axen_cmd err: cmd: %d, error: %d\n", cmd, err));
164 return -1;
165 }
166
167 return 0;
168}
169
170int
171axen_miibus_readreg(struct device *dev, int phy, int reg)
172{
173 struct axen_softc *sc = (void *)dev;
174 int err;
175 uWord val;
176 int ival;
177
178 if (usbd_is_dying(sc->axen_udev)) {
179 DPRINTF(("axen: dying\n"));
180 return 0;
181 }
182
183 if (sc->axen_phyno != phy)
184 return 0;
185
186 axen_lock_mii(sc);
187 err = axen_cmd(sc, AXEN_CMD_MII_READ_REG0x2002, reg, phy, &val);
188 axen_unlock_mii(sc);
189
190 if (err) {
191 printf("axen%d: read PHY failed\n", sc->axen_unit);
192 return -1;
193 }
194
195 ival = UGETW(val)(*(u_int16_t *)(val));
196 DPRINTFN(2,("axen_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n",
197 phy, reg, ival));
198
199 if (reg == MII_BMSR0x01) {
200 ival &= ~BMSR_EXTCAP0x0001;
201 }
202
203 return ival;
204}
205
206void
207axen_miibus_writereg(struct device *dev, int phy, int reg, int val)
208{
209 struct axen_softc *sc = (void *)dev;
210 int err;
211 uWord uval;
212
213 if (usbd_is_dying(sc->axen_udev))
214 return;
215
216 if (sc->axen_phyno != phy)
217 return;
218
219 USETW(uval, val)(*(u_int16_t *)(uval) = (val));
220 axen_lock_mii(sc);
221 err = axen_cmd(sc, AXEN_CMD_MII_WRITE_REG0x2102, reg, phy, &uval);
222 axen_unlock_mii(sc);
223 DPRINTFN(2, ("axen_miibus_writereg: phy 0x%x reg 0x%x val 0x%0x\n",
224 phy, reg, val));
225
226 if (err) {
227 printf("axen%d: write PHY failed\n", sc->axen_unit);
228 return;
229 }
230}
231
232void
233axen_miibus_statchg(struct device *dev)
234{
235 struct axen_softc *sc = (void *)dev;
236 struct mii_data *mii = GET_MII(sc)(&(sc)->axen_mii);
237 struct ifnet *ifp;
238 int err;
239 uint16_t val;
240 uWord wval;
241
242 ifp = GET_IFP(sc)(&(sc)->arpcom.ac_if);
243 if (mii == NULL((void *)0) || ifp == NULL((void *)0) ||
244 (ifp->if_flags & IFF_RUNNING0x40) == 0)
245 return;
246
247 sc->axen_link = 0;
248 if ((mii->mii_media_status & (IFM_ACTIVE0x0000000000000002ULL | IFM_AVALID0x0000000000000001ULL)) ==
249 (IFM_ACTIVE0x0000000000000002ULL | IFM_AVALID0x0000000000000001ULL)) {
250 switch (IFM_SUBTYPE(mii->mii_media_active)((mii->mii_media_active) & 0x00000000000000ffULL)) {
251 case IFM_10_T3:
252 case IFM_100_TX6:
253 sc->axen_link++;
254 break;
255 case IFM_1000_T16:
256 sc->axen_link++;
257 break;
258 default:
259 break;
260 }
261 }
262
263 /* Lost link, do nothing. */
264 if (sc->axen_link == 0)
265 return;
266
267 val = 0;
268 if ((IFM_OPTIONS(mii->mii_media_active)((mii->mii_media_active) & (0x00000000ffff0000ULL|0x00ffff0000000000ULL
))
& IFM_FDX0x0000010000000000ULL) != 0)
269 val |= AXEN_MEDIUM_FDX0x0002;
270
271 val |= (AXEN_MEDIUM_RECV_EN0x0100 | AXEN_MEDIUM_ALWAYS_ONE0x0004);
272 val |= (AXEN_MEDIUM_RXFLOW_CTRL_EN0x0010 | AXEN_MEDIUM_TXFLOW_CTRL_EN0x0020);
273
274 switch (IFM_SUBTYPE(mii->mii_media_active)((mii->mii_media_active) & 0x00000000000000ffULL)) {
275 case IFM_1000_T16:
276 val |= AXEN_MEDIUM_GIGA0x0001 | AXEN_MEDIUM_EN_125MHZ0x0008;
277 break;
278 case IFM_100_TX6:
279 val |= AXEN_MEDIUM_PS0x0200;
280 break;
281 case IFM_10_T3:
282 /* doesn't need to be handled */
283 break;
284 }
285
286 DPRINTF(("axen_miibus_statchg: val=0x%x\n", val));
287 USETW(wval, val)(*(u_int16_t *)(wval) = (val));
288 axen_lock_mii(sc);
289 err = axen_cmd(sc, AXEN_CMD_MAC_WRITE20x2101, 2, AXEN_MEDIUM_STATUS0x22, &wval);
290 axen_unlock_mii(sc);
291 if (err) {
292 printf("%s: media change failed\n", sc->axen_dev.dv_xname);
293 return;
294 }
295}
296
297/*
298 * Set media options.
299 */
300int
301axen_ifmedia_upd(struct ifnet *ifp)
302{
303 struct axen_softc *sc = ifp->if_softc;
304 struct mii_data *mii = GET_MII(sc)(&(sc)->axen_mii);
305 int err;
306
307 sc->axen_link = 0;
308
309 if (mii->mii_instance) {
310 struct mii_softc *miisc;
311 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)for((miisc) = ((&mii->mii_phys)->lh_first); (miisc)
!= ((void *)0); (miisc) = ((miisc)->mii_list.le_next))
312 mii_phy_reset(miisc);
313 }
314
315 err = mii_mediachg(mii);
316 if (err == ENXIO6)
317 return 0;
318 else
319 return err;
320}
321
322/*
323 * Report current media status.
324 */
325void
326axen_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
327{
328 struct axen_softc *sc = ifp->if_softc;
329 struct mii_data *mii = GET_MII(sc)(&(sc)->axen_mii);
330
331 mii_pollstat(mii);
332 ifmr->ifm_active = mii->mii_media_active;
333 ifmr->ifm_status = mii->mii_media_status;
334}
335
336void
337axen_iff(struct axen_softc *sc)
338{
339 struct ifnet *ifp = GET_IFP(sc)(&(sc)->arpcom.ac_if);
340 struct arpcom *ac = &sc->arpcom;
341 struct ether_multi *enm;
342 struct ether_multistep step;
343 u_int32_t h = 0;
344 u_int16_t rxmode;
345 u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
346 uWord wval;
347
348 if (usbd_is_dying(sc->axen_udev))
7
Assuming the condition is false
8
Taking false branch
349 return;
350
351 rxmode = 0;
352
353 /* Enable receiver, set RX mode */
354 axen_lock_mii(sc);
355 axen_cmd(sc, AXEN_CMD_MAC_READ20x2001, 2, AXEN_MAC_RXCTL0x0b, &wval);
9
Calling 'axen_cmd'
12
Returning from 'axen_cmd'
356 rxmode = UGETW(wval)(*(u_int16_t *)(wval));
13
Assigned value is garbage or undefined
357 rxmode &= ~(AXEN_RXCTL_ACPT_ALL_MCAST0x0002 | AXEN_RXCTL_ACPT_PHY_MCAST0x0020 |
358 AXEN_RXCTL_PROMISC0x0001);
359 ifp->if_flags &= ~IFF_ALLMULTI0x200;
360
361 /*
362 * Always accept broadcast frames.
363 * Always accept frames destined to our station address.
364 */
365 rxmode |= AXEN_RXCTL_ACPT_BCAST0x0010;
366
367 if (ifp->if_flags & IFF_PROMISC0x100 || ac->ac_multirangecnt > 0) {
368 ifp->if_flags |= IFF_ALLMULTI0x200;
369 rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST0x0002 | AXEN_RXCTL_ACPT_PHY_MCAST0x0020;
370 if (ifp->if_flags & IFF_PROMISC0x100)
371 rxmode |= AXEN_RXCTL_PROMISC0x0001;
372 } else {
373 rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST0x0002 | AXEN_RXCTL_ACPT_PHY_MCAST0x0020;
374
375 /* now program new ones */
376 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)
;
377 while (enm != NULL((void *)0)) {
378 h = ether_crc32_be(enm->enm_addrlo,
379 ETHER_ADDR_LEN6) >> 26;
380 hashtbl[h / 8] |= 1 << (h % 8);
381 ETHER_NEXT_MULTI(step, enm)do { if (((enm) = (step).e_enm) != ((void *)0)) (step).e_enm =
(((enm))->enm_list.le_next); } while ( 0)
;
382 }
383 }
384
385 axen_cmd(sc, AXEN_CMD_MAC_WRITE_FILTER0x8101, 8, AXEN_FILTER_MULTI0x16,
386 (void *)&hashtbl);
387 USETW(wval, rxmode)(*(u_int16_t *)(wval) = (rxmode));
388 axen_cmd(sc, AXEN_CMD_MAC_WRITE20x2101, 2, AXEN_MAC_RXCTL0x0b, &wval);
389 axen_unlock_mii(sc);
390}
391
392void
393axen_reset(struct axen_softc *sc)
394{
395 if (usbd_is_dying(sc->axen_udev))
396 return;
397
398 axen_ax88179_init(sc);
399
400 /* Wait a little while for the chip to get its brains in order. */
401 DELAY(1000)(*delay_func)(1000);
402 return;
403}
404
405void
406axen_ax88179_init(struct axen_softc *sc)
407{
408 uWord wval;
409 uByte val;
410 u_int16_t ctl, temp;
411 struct axen_qctrl qctrl;
412
413 axen_lock_mii(sc);
414
415 /* XXX: ? */
416 axen_cmd(sc, AXEN_CMD_MAC_READ0x1001, 1, AXEN_UNK_050x05, &val);
417 DPRINTFN(5, ("AXEN_CMD_MAC_READ(0x05): 0x%02x\n", val));
418
419 /* check AX88179 version, UA1 / UA2 */
420 axen_cmd(sc, AXEN_CMD_MAC_READ0x1001, 1, AXEN_GENERAL_STATUS0x03, &val);
421 /* UA1 */
422 if (!(val & AXEN_GENERAL_STATUS_MASK0x4)) {
423 sc->axen_rev = AXEN_REV_UA10;
424 DPRINTF(("AX88179 ver. UA1\n"));
425 } else {
426 sc->axen_rev = AXEN_REV_UA21;
427 DPRINTF(("AX88179 ver. UA2\n"));
428 }
429
430 /* power up ethernet PHY */
431 USETW(wval, 0)(*(u_int16_t *)(wval) = (0));
432 axen_cmd(sc, AXEN_CMD_MAC_WRITE20x2101, 2, AXEN_PHYPWR_RSTCTL0x26, &wval);
433
434 USETW(wval, AXEN_PHYPWR_RSTCTL_IPRL)(*(u_int16_t *)(wval) = (0x0020));
435 axen_cmd(sc, AXEN_CMD_MAC_WRITE20x2101, 2, AXEN_PHYPWR_RSTCTL0x26, &wval);
436 usbd_delay_ms(sc->axen_udev, 200);
437
438 /* set clock mode */
439 val = AXEN_PHYCLK_ACS0x02 | AXEN_PHYCLK_BCS0x01;
440 axen_cmd(sc, AXEN_CMD_MAC_WRITE0x1101, 1, AXEN_PHYCLK0x33, &val);
441 usbd_delay_ms(sc->axen_udev, 100);
442
443 /* set monitor mode (disable) */
444 val = AXEN_MONITOR_NONE0x00;
445 axen_cmd(sc, AXEN_CMD_MAC_WRITE0x1101, 1, AXEN_MONITOR_MODE0x24, &val);
446
447 /* enable auto detach */
448 axen_cmd(sc, AXEN_CMD_EEPROM_READ0x2004, 2, AXEN_EEPROM_STAT0x43, &wval);
449 temp = UGETW(wval)(*(u_int16_t *)(wval));
450 DPRINTFN(2,("EEPROM0x43 = 0x%04x\n", temp));
451 if (!(temp == 0xffff) && !(temp & 0x0100)) {
452 /* Enable auto detach bit */
453 val = 0;
454 axen_cmd(sc, AXEN_CMD_MAC_WRITE0x1101, 1, AXEN_PHYCLK0x33, &val);
455 val = AXEN_PHYCLK_ULR0x08;
456 axen_cmd(sc, AXEN_CMD_MAC_WRITE0x1101, 1, AXEN_PHYCLK0x33, &val);
457 usbd_delay_ms(sc->axen_udev, 100);
458
459 axen_cmd(sc, AXEN_CMD_MAC_READ20x2001, 2, AXEN_PHYPWR_RSTCTL0x26, &wval);
460 ctl = UGETW(wval)(*(u_int16_t *)(wval));
461 ctl |= AXEN_PHYPWR_RSTCTL_AUTODETACH0x1000;
462 USETW(wval, ctl)(*(u_int16_t *)(wval) = (ctl));
463 axen_cmd(sc, AXEN_CMD_MAC_WRITE20x2101, 2, AXEN_PHYPWR_RSTCTL0x26, &wval);
464 usbd_delay_ms(sc->axen_udev, 200);
465 printf("%s: enable auto detach (0x%04x)\n",
466 sc->axen_dev.dv_xname, ctl);
467 }
468
469 /* bulkin queue setting */
470 axen_cmd(sc, AXEN_CMD_MAC_READ0x1001, 1, AXEN_USB_UPLINK0x02, &val);
471 switch (val) {
472 case AXEN_USB_FS0x01:
473 DPRINTF(("uplink: USB1.1\n"));
474 qctrl.ctrl = 0x07;
475 qctrl.timer_low = 0xcc;
476 qctrl.timer_high= 0x4c;
477 qctrl.bufsize = AXEN_BUFSZ_LS8 - 1;
478 qctrl.ifg = 0x08;
479 break;
480 case AXEN_USB_HS0x02:
481 DPRINTF(("uplink: USB2.0\n"));
482 qctrl.ctrl = 0x07;
483 qctrl.timer_low = 0x02;
484 qctrl.timer_high= 0xa0;
485 qctrl.bufsize = AXEN_BUFSZ_HS16 - 1;
486 qctrl.ifg = 0xff;
487 break;
488 case AXEN_USB_SS0x04:
489 DPRINTF(("uplink: USB3.0\n"));
490 qctrl.ctrl = 0x07;
491 qctrl.timer_low = 0x4f;
492 qctrl.timer_high= 0x00;
493 qctrl.bufsize = AXEN_BUFSZ_SS24 - 1;
494 qctrl.ifg = 0xff;
495 break;
496 default:
497 printf("%s: unknown uplink bus:0x%02x\n",
498 sc->axen_dev.dv_xname, val);
499 axen_unlock_mii(sc);
500 return;
501 }
502 axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR0x5101, 5, AXEN_RX_BULKIN_QCTRL0x2e, &qctrl);
503
504 /* Set MAC address. */
505 axen_cmd(sc, AXEN_CMD_MAC_WRITE_ETHER0x6101, ETHER_ADDR_LEN6,
506 AXEN_CMD_MAC_NODE_ID0x10, &sc->arpcom.ac_enaddr);
507
508 /*
509 * set buffer high/low watermark to pause/resume.
510 * write 2byte will set high/log simultaneous with AXEN_PAUSE_HIGH.
511 * XXX: what is the best value? OSX driver uses 0x3c-0x4c as LOW-HIGH
512 * watermark parameters.
513 */
514 val = 0x34;
515 axen_cmd(sc, AXEN_CMD_MAC_WRITE0x1101, 1, AXEN_PAUSE_LOW_WATERMARK0x55, &val);
516 val = 0x52;
517 axen_cmd(sc, AXEN_CMD_MAC_WRITE0x1101, 1, AXEN_PAUSE_HIGH_WATERMARK0x54, &val);
518
519 /* Set RX/TX configuration. */
520 /* Offloading enable */
521#ifdef AXEN_TOE
522 val = AXEN_RXCOE_IPv40x01 | AXEN_RXCOE_TCPv40x02 | AXEN_RXCOE_UDPv40x04 |
523 AXEN_RXCOE_TCPv60x20 | AXEN_RXCOE_UDPv60x40;
524#else
525 val = AXEN_RXCOE_OFF0x00;
526#endif
527 axen_cmd(sc, AXEN_CMD_MAC_WRITE0x1101, 1, AXEN_RX_COE0x34, &val);
528
529#ifdef AXEN_TOE
530 val = AXEN_TXCOE_IPv40x01 | AXEN_TXCOE_TCPv40x02 | AXEN_TXCOE_UDPv40x04 |
531 AXEN_TXCOE_TCPv60x20 | AXEN_TXCOE_UDPv60x40;
532#else
533 val = AXEN_TXCOE_OFF0x00;
534#endif
535 axen_cmd(sc, AXEN_CMD_MAC_WRITE0x1101, 1, AXEN_TX_COE0x35, &val);
536
537 /* Set RX control register */
538 ctl = AXEN_RXCTL_IPE0x0200 | AXEN_RXCTL_DROPCRCERR0x0100 | AXEN_RXCTL_AUTOB0x0008;
539 ctl |= AXEN_RXCTL_ACPT_PHY_MCAST0x0020 | AXEN_RXCTL_ACPT_ALL_MCAST0x0002;
540 ctl |= AXEN_RXCTL_START0x0080;
541 USETW(wval, ctl)(*(u_int16_t *)(wval) = (ctl));
542 axen_cmd(sc, AXEN_CMD_MAC_WRITE20x2101, 2, AXEN_MAC_RXCTL0x0b, &wval);
543
544 /* set monitor mode (enable) */
545 val = AXEN_MONITOR_PMETYPE0x40 | AXEN_MONITOR_PMEPOL0x20 | AXEN_MONITOR_RWMP0x04;
546 axen_cmd(sc, AXEN_CMD_MAC_WRITE0x1101, 1, AXEN_MONITOR_MODE0x24, &val);
547 axen_cmd(sc, AXEN_CMD_MAC_READ0x1001, 1, AXEN_MONITOR_MODE0x24, &val);
548 DPRINTF(("axen: Monitor mode = 0x%02x\n", val));
549
550 /* set medium type */
551 ctl = AXEN_MEDIUM_GIGA0x0001 | AXEN_MEDIUM_FDX0x0002 | AXEN_MEDIUM_ALWAYS_ONE0x0004 |
552 AXEN_MEDIUM_RXFLOW_CTRL_EN0x0010 | AXEN_MEDIUM_TXFLOW_CTRL_EN0x0020;
553 ctl |= AXEN_MEDIUM_RECV_EN0x0100;
554 USETW(wval, ctl)(*(u_int16_t *)(wval) = (ctl));
555 DPRINTF(("axen: set to medium mode: 0x%04x\n", UGETW(wval)));
556 axen_cmd(sc, AXEN_CMD_MAC_WRITE20x2101, 2, AXEN_MEDIUM_STATUS0x22, &wval);
557 usbd_delay_ms(sc->axen_udev, 100);
558
559 axen_cmd(sc, AXEN_CMD_MAC_READ20x2001, 2, AXEN_MEDIUM_STATUS0x22, &wval);
560 DPRINTF(("axen: current medium mode: 0x%04x\n", UGETW(wval)));
561 axen_unlock_mii(sc);
562
563#if 0 /* XXX: TBD.... */
564#define GMII_LED_ACTIVE 0x1a
565#define GMII_PHY_PAGE_SEL 0x1e
566#define GMII_PHY_PAGE_SEL 0x1f
567#define GMII_PAGE_EXT 0x0007
568 axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, GMII_PHY_PAGE_SEL,
569 GMII_PAGE_EXT);
570 axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, GMII_PHY_PAGE,
571 0x002c);
572#endif
573
574#if 1 /* XXX: phy hack ? */
575 axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x1F, 0x0005);
576 axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x0C, 0x0000);
577 val = axen_miibus_readreg(&sc->axen_dev, sc->axen_phyno, 0x0001);
578 axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x01,
579 val | 0x0080);
580 axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x1F, 0x0000);
581#endif
582}
583
584int
585axen_match(struct device *parent, void *match, void *aux)
586{
587 struct usb_attach_arg *uaa = aux;
588
589 if (uaa->iface == NULL((void *)0) || uaa->configno != 1)
590 return (UMATCH_NONE0);
591
592 return (axen_lookup(uaa->vendor, uaa->product)((struct axen_type *)usbd_match_device((const struct usb_devno
*)(axen_devs), sizeof (axen_devs) / sizeof ((axen_devs)[0]),
sizeof ((axen_devs)[0]), (uaa->vendor), (uaa->product)
))
!= NULL((void *)0) ?
593 UMATCH_VENDOR_PRODUCT_CONF_IFACE8 : UMATCH_NONE0);
594}
595
596void
597axen_attach(struct device *parent, struct device *self, void *aux)
598{
599 struct axen_softc *sc = (struct axen_softc *)self;
600 struct usb_attach_arg *uaa = aux;
601 usb_interface_descriptor_t *id;
602 usb_endpoint_descriptor_t *ed;
603 usb_device_descriptor_t *dd;
604 struct mii_data *mii;
605 u_char eaddr[ETHER_ADDR_LEN6];
606 char *devname = sc->axen_dev.dv_xname;
607 struct ifnet *ifp;
608 int i, s;
609
610 sc->axen_unit = self->dv_unit; /*device_get_unit(self);*/
611 sc->axen_udev = uaa->device;
612 sc->axen_iface = uaa->iface;
613 sc->axen_flags = axen_lookup(uaa->vendor, uaa->product)((struct axen_type *)usbd_match_device((const struct usb_devno
*)(axen_devs), sizeof (axen_devs) / sizeof ((axen_devs)[0]),
sizeof ((axen_devs)[0]), (uaa->vendor), (uaa->product)
))
->axen_flags;
614
615 usb_init_task(&sc->axen_tick_task, axen_tick_task, sc,((&sc->axen_tick_task)->fun = (axen_tick_task), (&
sc->axen_tick_task)->arg = (sc), (&sc->axen_tick_task
)->type = (0), (&sc->axen_tick_task)->state = 0x0
)
616 USB_TASK_TYPE_GENERIC)((&sc->axen_tick_task)->fun = (axen_tick_task), (&
sc->axen_tick_task)->arg = (sc), (&sc->axen_tick_task
)->type = (0), (&sc->axen_tick_task)->state = 0x0
)
;
617 rw_init(&sc->axen_mii_lock, "axenmii")_rw_init_flags(&sc->axen_mii_lock, "axenmii", 0, ((void
*)0))
;
618 usb_init_task(&sc->axen_stop_task, (void (*)(void *))axen_stop, sc,((&sc->axen_stop_task)->fun = ((void (*)(void *))axen_stop
), (&sc->axen_stop_task)->arg = (sc), (&sc->
axen_stop_task)->type = (0), (&sc->axen_stop_task)->
state = 0x0)
619 USB_TASK_TYPE_GENERIC)((&sc->axen_stop_task)->fun = ((void (*)(void *))axen_stop
), (&sc->axen_stop_task)->arg = (sc), (&sc->
axen_stop_task)->type = (0), (&sc->axen_stop_task)->
state = 0x0)
;
620
621 sc->axen_product = uaa->product;
622 sc->axen_vendor = uaa->vendor;
623
624 id = usbd_get_interface_descriptor(sc->axen_iface);
625
626 /* decide on what our bufsize will be */
627 switch (sc->axen_udev->speed) {
628 case USB_SPEED_FULL2:
629 sc->axen_bufsz = AXEN_BUFSZ_LS8 * 1024;
630 break;
631 case USB_SPEED_HIGH3:
632 sc->axen_bufsz = AXEN_BUFSZ_HS16 * 1024;
633 break;
634 case USB_SPEED_SUPER4:
635 sc->axen_bufsz = AXEN_BUFSZ_SS24 * 1024;
636 break;
637 default:
638 printf("%s: not supported usb bus type", sc->axen_dev.dv_xname);
639 return;
640 }
641
642 /* Find endpoints. */
643 for (i = 0; i < id->bNumEndpoints; i++) {
644 ed = usbd_interface2endpoint_descriptor(sc->axen_iface, i);
645 if (!ed) {
646 printf("%s: couldn't get ep %d\n",
647 sc->axen_dev.dv_xname, i);
648 return;
649 }
650 if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80 &&
651 UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02) {
652 sc->axen_ed[AXEN_ENDPT_RX0x0] = ed->bEndpointAddress;
653 } else if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_OUT0x00 &&
654 UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02) {
655 sc->axen_ed[AXEN_ENDPT_TX0x1] = ed->bEndpointAddress;
656 } else if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80 &&
657 UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_INTERRUPT0x03) {
658 sc->axen_ed[AXEN_ENDPT_INTR0x2] = ed->bEndpointAddress;
659 }
660 }
661
662 dd = usbd_get_device_descriptor(sc->axen_udev);
663 if (UGETW(dd->bcdDevice)(*(u_int16_t *)(dd->bcdDevice)) == 0x200)
664 sc->axen_flags = AX179A0x0004;
665
666 s = splnet()splraise(0x4);
667
668 sc->axen_phyno = AXEN_PHY_ID0x0003;
669 DPRINTF((" get_phyno %d\n", sc->axen_phyno));
670
671 /*
672 * Get station address.
673 */
674 /* use MAC command */
675 axen_lock_mii(sc);
676 axen_cmd(sc, AXEN_CMD_MAC_READ_ETHER0x6001, ETHER_ADDR_LEN6,
677 AXEN_CMD_MAC_NODE_ID0x10, &eaddr);
678 axen_unlock_mii(sc);
679
680 /*
681 * An ASIX chip was detected. Inform the world.
682 */
683 printf("%s:", sc->axen_dev.dv_xname);
684 if (sc->axen_flags & AX178A0x0001)
685 printf(" AX88178a");
686 else if (sc->axen_flags & AX1790x0002)
687 printf(" AX88179");
688 else
689 printf(" AX88179A");
690 printf(", address %s\n", ether_sprintf(eaddr));
691
692 bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN6);
693
694 axen_ax88179_init(sc);
695
696 /* Initialize interface info. */
697 ifp = &sc->arpcom.ac_if;
698 ifp->if_softc = sc;
699 strlcpy(ifp->if_xname, devname, IFNAMSIZ16);
700 ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
701 ifp->if_ioctl = axen_ioctl;
702 ifp->if_start = axen_start;
703 ifp->if_watchdog = axen_watchdog;
704
705 ifp->if_capabilitiesif_data.ifi_capabilities = IFCAP_VLAN_MTU0x00000010;
706#ifdef AXEN_TOE
707 ifp->if_capabilitiesif_data.ifi_capabilities |= IFCAP_CSUM_IPv40x00000001 | IFCAP_CSUM_TCPv40x00000002 |
708 IFCAP_CSUM_UDPv40x00000004 | IFCAP_CSUM_TCPv60x00000080 | IFCAP_CSUM_UDPv60x00000100;
709#endif
710
711 /* Initialize MII/media info. */
712 mii = &sc->axen_mii;
713 mii->mii_ifp = ifp;
714 mii->mii_readreg = axen_miibus_readreg;
715 mii->mii_writereg = axen_miibus_writereg;
716 mii->mii_statchg = axen_miibus_statchg;
717 mii->mii_flags = MIIF_AUTOTSLEEP0x0010;
718
719 ifmedia_init(&mii->mii_media, 0, axen_ifmedia_upd, axen_ifmedia_sts);
720 mii_attach(self, mii, 0xffffffff, MII_PHY_ANY-1, MII_OFFSET_ANY-1, 0);
721
722 if (LIST_FIRST(&mii->mii_phys)((&mii->mii_phys)->lh_first) == NULL((void *)0)) {
723 ifmedia_add(&mii->mii_media, IFM_ETHER0x0000000000000100ULL | IFM_NONE2ULL, 0, NULL((void *)0));
724 ifmedia_set(&mii->mii_media, IFM_ETHER0x0000000000000100ULL | IFM_NONE2ULL);
725 } else
726 ifmedia_set(&mii->mii_media, IFM_ETHER0x0000000000000100ULL | IFM_AUTO0ULL);
727
728 /* Attach the interface. */
729 if_attach(ifp);
730 ether_ifattach(ifp);
731
732 timeout_set(&sc->axen_stat_ch, axen_tick, sc);
733
734 splx(s)spllower(s);
735}
736
737int
738axen_detach(struct device *self, int flags)
739{
740 struct axen_softc *sc = (struct axen_softc *)self;
741 int s;
742 struct ifnet *ifp = GET_IFP(sc)(&(sc)->arpcom.ac_if);
743
744 DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
745
746 if (timeout_initialized(&sc->axen_stat_ch)((&sc->axen_stat_ch)->to_flags & 0x04))
747 timeout_del(&sc->axen_stat_ch);
748
749 if (sc->axen_ep[AXEN_ENDPT_TX0x1] != NULL((void *)0))
750 usbd_abort_pipe(sc->axen_ep[AXEN_ENDPT_TX0x1]);
751 if (sc->axen_ep[AXEN_ENDPT_RX0x0] != NULL((void *)0))
752 usbd_abort_pipe(sc->axen_ep[AXEN_ENDPT_RX0x0]);
753 if (sc->axen_ep[AXEN_ENDPT_INTR0x2] != NULL((void *)0))
754 usbd_abort_pipe(sc->axen_ep[AXEN_ENDPT_INTR0x2]);
755
756 /*
757 * Remove any pending tasks. They cannot be executing because they run
758 * in the same thread as detach.
759 */
760 usb_rem_task(sc->axen_udev, &sc->axen_tick_task);
761 usb_rem_task(sc->axen_udev, &sc->axen_stop_task);
762
763 s = splusb()splraise(0x2);
764
765 if (--sc->axen_refcnt >= 0) {
766 /* Wait for processes to go away */
767 usb_detach_wait(&sc->axen_dev);
768 }
769
770 if (ifp->if_flags & IFF_RUNNING0x40)
771 axen_stop(sc);
772
773 mii_detach(&sc->axen_mii, MII_PHY_ANY-1, MII_OFFSET_ANY-1);
774 ifmedia_delete_instance(&sc->axen_mii.mii_media, IFM_INST_ANY((uint64_t) -1));
775 if (ifp->if_softc != NULL((void *)0)) {
776 ether_ifdetach(ifp);
777 if_detach(ifp);
778 }
779
780#ifdef DIAGNOSTIC1
781 if (sc->axen_ep[AXEN_ENDPT_TX0x1] != NULL((void *)0) ||
782 sc->axen_ep[AXEN_ENDPT_RX0x0] != NULL((void *)0) ||
783 sc->axen_ep[AXEN_ENDPT_INTR0x2] != NULL((void *)0))
784 printf("%s: detach has active endpoints\n",
785 sc->axen_dev.dv_xname);
786#endif
787
788 splx(s)spllower(s);
789
790 return 0;
791}
792
793struct mbuf *
794axen_newbuf(void)
795{
796 struct mbuf *m;
797
798 MGETHDR(m, M_DONTWAIT, MT_DATA)m = m_gethdr((0x0002), (1));
799 if (m == NULL((void *)0))
800 return NULL((void *)0);
801
802 MCLGET(m, M_DONTWAIT)(void) m_clget((m), (0x0002), (1 << 11));
803 if (!(m->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
804 m_freem(m);
805 return NULL((void *)0);
806 }
807
808 m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = MCLBYTES(1 << 11);
809 m_adj(m, ETHER_ALIGN2);
810
811 return m;
812}
813
814int
815axen_rx_list_init(struct axen_softc *sc)
816{
817 struct axen_cdata *cd;
818 struct axen_chain *c;
819 int i;
820
821 DPRINTF(("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
822
823 cd = &sc->axen_cdata;
824 for (i = 0; i < AXEN_RX_LIST_CNT1; i++) {
825 c = &cd->axen_rx_chain[i];
826 c->axen_sc = sc;
827 c->axen_idx = i;
828 c->axen_mbuf = NULL((void *)0);
829 if (c->axen_xfer == NULL((void *)0)) {
830 c->axen_xfer = usbd_alloc_xfer(sc->axen_udev);
831 if (c->axen_xfer == NULL((void *)0))
832 return ENOBUFS55;
833 c->axen_buf = usbd_alloc_buffer(c->axen_xfer,
834 sc->axen_bufsz);
835 if (c->axen_buf == NULL((void *)0)) {
836 usbd_free_xfer(c->axen_xfer);
837 return ENOBUFS55;
838 }
839 }
840 }
841
842 return 0;
843}
844
845int
846axen_tx_list_init(struct axen_softc *sc)
847{
848 struct axen_cdata *cd;
849 struct axen_chain *c;
850 int i;
851
852 DPRINTF(("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__));
853
854 cd = &sc->axen_cdata;
855 for (i = 0; i < AXEN_TX_LIST_CNT1; i++) {
856 c = &cd->axen_tx_chain[i];
857 c->axen_sc = sc;
858 c->axen_idx = i;
859 c->axen_mbuf = NULL((void *)0);
860 if (c->axen_xfer == NULL((void *)0)) {
861 c->axen_xfer = usbd_alloc_xfer(sc->axen_udev);
862 if (c->axen_xfer == NULL((void *)0))
863 return ENOBUFS55;
864 c->axen_buf = usbd_alloc_buffer(c->axen_xfer,
865 sc->axen_bufsz);
866 if (c->axen_buf == NULL((void *)0)) {
867 usbd_free_xfer(c->axen_xfer);
868 return ENOBUFS55;
869 }
870 }
871 }
872
873 return 0;
874}
875
876/*
877 * A frame has been uploaded: pass the resulting mbuf chain up to
878 * the higher level protocols.
879 */
880void
881axen_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
882{
883 struct axen_chain *c = (struct axen_chain *)priv;
884 struct axen_softc *sc = c->axen_sc;
885 struct ifnet *ifp = GET_IFP(sc)(&(sc)->arpcom.ac_if);
886 u_char *buf = c->axen_buf;
887 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
888 struct mbuf *m;
889 u_int32_t total_len;
890 u_int32_t rx_hdr, pkt_hdr;
891 u_int32_t *hdr_p;
892 u_int16_t hdr_offset, pkt_count;
893 size_t pkt_len;
894 size_t temp;
895 int padlen, s;
896
897 DPRINTFN(10,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__));
898
899 if (usbd_is_dying(sc->axen_udev))
900 return;
901
902 if (!(ifp->if_flags & IFF_RUNNING0x40))
903 return;
904
905 if (status != USBD_NORMAL_COMPLETION) {
906 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
907 return;
908 if (usbd_ratecheck(&sc->axen_rx_notice)) {
909 printf("%s: usb errors on rx: %s\n",
910 sc->axen_dev.dv_xname, usbd_errstr(status));
911 }
912 if (status == USBD_STALLED)
913 usbd_clear_endpoint_stall_async(sc->axen_ep[AXEN_ENDPT_RX0x0]);
914 goto done;
915 }
916
917 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &total_len, NULL((void *)0));
918
919 if (total_len < sizeof(pkt_hdr)) {
920 ifp->if_ierrorsif_data.ifi_ierrors++;
921 goto done;
922 }
923
924 /*
925 * buffer map
926 *
927 * for ax88179
928 * [packet #0]...[packet #n][pkt hdr#0]..[pkt hdr#n][recv_hdr]
929 *
930 * for ax88179a
931 * [packet #0]...[packet #n][pkt hdr#0][dummy_hdr]..
932 * [pkt hdr#n][dummy_hdr][recv_hdr]
933 *
934 * each packet has 0xeeee as pseudo header..
935 */
936 hdr_p = (u_int32_t *)(buf + total_len - sizeof(u_int32_t));
937 rx_hdr = letoh32(*hdr_p)((__uint32_t)(*hdr_p));
938 hdr_offset = (u_int16_t)(rx_hdr >> 16);
939 pkt_count = (u_int16_t)(rx_hdr & 0xffff);
940
941 if (total_len > sc->axen_bufsz) {
942 printf("%s: rxeof: too large transfer\n",
943 sc->axen_dev.dv_xname);
944 goto done;
945 }
946
947 /* sanity check */
948 if (hdr_offset > total_len) {
949 ifp->if_ierrorsif_data.ifi_ierrors++;
950 goto done;
951 }
952
953 /* point first packet header */
954 hdr_p = (u_int32_t*)(buf + hdr_offset);
955
956 /*
957 * ax88179 will pack multiple ip packet to a USB transaction.
958 * process all of packets in the buffer
959 */
960
961#if 1 /* XXX: paranoiac check. need to remove later */
962#define AXEN_MAX_PACKED_PACKET200 200
963 if (pkt_count > AXEN_MAX_PACKED_PACKET200) {
964 DPRINTF(("Too many packets (%d) in a transaction, discard.\n",
965 pkt_count));
966 goto done;
967 }
968#endif
969
970 /* skip pseudo header (2byte) */
971 padlen = 2;
972 /* skip trailer padding (4Byte) for ax88179 */
973 if (!(sc->axen_flags & AX179A0x0004))
974 padlen += 4;
975
976 do {
977 pkt_hdr = letoh32(*hdr_p)((__uint32_t)(*hdr_p));
978 pkt_len = (pkt_hdr >> 16) & 0x1fff;
979
980 DPRINTFN(10,("rxeof: packet#%d, pkt_hdr 0x%08x, pkt_len %zu\n",
981 pkt_count, pkt_hdr, pkt_len));
982
983 /* skip dummy packet header */
984 if (pkt_len == 0)
985 goto nextpkt;
986
987 if ((buf[0] != 0xee) || (buf[1] != 0xee)){
988 printf("%s: invalid buffer(pkt#%d), continue\n",
989 sc->axen_dev.dv_xname, pkt_count);
990 ifp->if_ierrorsif_data.ifi_ierrors += pkt_count;
991 goto done;
992 }
993
994 if ((pkt_hdr & AXEN_RXHDR_CRC_ERR(1U << 29)) ||
995 (pkt_hdr & AXEN_RXHDR_DROP_ERR(1U << 31))) {
996 ifp->if_ierrorsif_data.ifi_ierrors++;
997 /* move to next pkt header */
998 DPRINTF(("crc err(pkt#%d)\n", pkt_count));
999 goto nextpkt;
1000 }
1001
1002 /* process each packet */
1003 /* allocate mbuf */
1004 m = axen_newbuf();
1005 if (m == NULL((void *)0)) {
1006 ifp->if_ierrorsif_data.ifi_ierrors++;
1007 goto nextpkt;
1008 }
1009
1010 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = pkt_len - padlen;
1011
1012#ifdef AXEN_TOE
1013 /* checksum err */
1014 if ((pkt_hdr & AXEN_RXHDR_L3CSUM_ERR(1U << 1)) ||
1015 (pkt_hdr & AXEN_RXHDR_L4CSUM_ERR(1U << 0))) {
1016 printf("%s: checksum err (pkt#%d)\n",
1017 sc->axen_dev.dv_xname, pkt_count);
1018 goto nextpkt;
1019 } else {
1020 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK0x0008;
1021 }
1022
1023 int l4_type;
1024 l4_type = (pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK0x0000001c) >>
1025 AXEN_RXHDR_L4_TYPE_OFFSET2;
1026
1027 if ((l4_type == AXEN_RXHDR_L4_TYPE_TCP0x4) ||
1028 (l4_type == AXEN_RXHDR_L4_TYPE_UDP0x1))
1029 m->m_pkthdrM_dat.MH.MH_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK0x0020 |
1030 M_UDP_CSUM_IN_OK0x0080;
1031#endif
1032
1033 memcpy(mtod(m, char *), buf + 2, pkt_len - padlen)__builtin_memcpy((((char *)((m)->m_hdr.mh_data))), (buf + 2
), (pkt_len - padlen))
;
1034
1035 ml_enqueue(&ml, m);
1036
1037nextpkt:
1038 /*
1039 * prepare next packet
1040 * as each packet will be aligned 8byte boundary,
1041 * need to fix up the start point of the buffer.
1042 */
1043 temp = ((pkt_len + 7) & 0xfff8);
1044 buf = buf + temp;
1045 hdr_p++;
1046 pkt_count--;
1047 } while( pkt_count > 0);
1048
1049done:
1050 /* push the packet up */
1051 s = splnet()splraise(0x4);
1052 if_input(ifp, &ml);
1053 splx(s)spllower(s);
1054
1055 /* clear buffer for next transaction */
1056 memset(c->axen_buf, 0, sc->axen_bufsz)__builtin_memset((c->axen_buf), (0), (sc->axen_bufsz));
1057
1058 /* Setup new transfer. */
1059 usbd_setup_xfer(xfer, sc->axen_ep[AXEN_ENDPT_RX0x0],
1060 c, c->axen_buf, sc->axen_bufsz,
1061 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
1062 USBD_NO_TIMEOUT0, axen_rxeof);
1063 usbd_transfer(xfer);
1064
1065 DPRINTFN(10,("%s: %s: start rx\n", sc->axen_dev.dv_xname, __func__));
1066}
1067
1068/*
1069 * A frame was downloaded to the chip. It's safe for us to clean up
1070 * the list buffers.
1071 */
1072void
1073axen_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1074{
1075 struct axen_softc *sc;
1076 struct axen_chain *c;
1077 struct ifnet *ifp;
1078 int s;
1079
1080 c = priv;
1081 sc = c->axen_sc;
1082 ifp = &sc->arpcom.ac_if;
1083
1084 if (usbd_is_dying(sc->axen_udev))
1085 return;
1086
1087 s = splnet()splraise(0x4);
1088
1089 if (status != USBD_NORMAL_COMPLETION) {
1090 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1091 splx(s)spllower(s);
1092 return;
1093 }
1094 ifp->if_oerrorsif_data.ifi_oerrors++;
1095 printf("axen%d: usb error on tx: %s\n", sc->axen_unit,
1096 usbd_errstr(status));
1097 if (status == USBD_STALLED)
1098 usbd_clear_endpoint_stall_async(sc->axen_ep[AXEN_ENDPT_TX0x1]);
1099 splx(s)spllower(s);
1100 return;
1101 }
1102
1103 ifp->if_timer = 0;
1104 ifq_clr_oactive(&ifp->if_snd);
1105
1106 m_freem(c->axen_mbuf);
1107 c->axen_mbuf = NULL((void *)0);
1108
1109 if (ifq_empty(&ifp->if_snd)(({ typeof((&ifp->if_snd)->ifq_len) __tmp = *(volatile
typeof((&ifp->if_snd)->ifq_len) *)&((&ifp->
if_snd)->ifq_len); membar_datadep_consumer(); __tmp; }) ==
0)
== 0)
1110 axen_start(ifp);
1111
1112 splx(s)spllower(s);
1113}
1114
1115void
1116axen_tick(void *xsc)
1117{
1118 struct axen_softc *sc = xsc;
1119
1120 if (sc == NULL((void *)0))
1121 return;
1122
1123 DPRINTFN(0xff, ("%s: %s: enter\n", sc->axen_dev.dv_xname,
1124 __func__));
1125
1126 if (usbd_is_dying(sc->axen_udev))
1127 return;
1128
1129 /* Perform periodic stuff in process context */
1130 usb_add_task(sc->axen_udev, &sc->axen_tick_task);
1131}
1132
1133void
1134axen_tick_task(void *xsc)
1135{
1136 int s;
1137 struct axen_softc *sc;
1138 struct mii_data *mii;
1139
1140 sc = xsc;
1141
1142 if (sc == NULL((void *)0))
1143 return;
1144
1145 if (usbd_is_dying(sc->axen_udev))
1146 return;
1147
1148 mii = GET_MII(sc)(&(sc)->axen_mii);
1149 if (mii == NULL((void *)0))
1150 return;
1151
1152 s = splnet()splraise(0x4);
1153
1154 mii_tick(mii);
1155 if (sc->axen_link == 0)
1156 axen_miibus_statchg(&sc->axen_dev);
1157 timeout_add_sec(&sc->axen_stat_ch, 1);
1158
1159 splx(s)spllower(s);
1160}
1161
1162int
1163axen_encap(struct axen_softc *sc, struct mbuf *m, int idx)
1164{
1165 struct axen_chain *c;
1166 usbd_status err;
1167 struct axen_sframe_hdr hdr;
1168 int length, boundary;
1169
1170 c = &sc->axen_cdata.axen_tx_chain[idx];
1171
1172 switch (sc->axen_udev->speed) {
1173 case USB_SPEED_FULL2:
1174 boundary = 64;
1175 break;
1176 case USB_SPEED_HIGH3:
1177 boundary = 512;
1178 break;
1179 case USB_SPEED_SUPER4:
1180 boundary = 4096; /* XXX */
1181 break;
1182 default:
1183 printf("%s: not supported usb bus type", sc->axen_dev.dv_xname);
1184 return EIO5;
1185 }
1186
1187 hdr.plen = htole32(m->m_pkthdr.len)((__uint32_t)(m->M_dat.MH.MH_pkthdr.len));
1188 hdr.gso = 0; /* disable segmentation offloading */
1189
1190 memcpy(c->axen_buf, &hdr, sizeof(hdr))__builtin_memcpy((c->axen_buf), (&hdr), (sizeof(hdr)));
1191 length = sizeof(hdr);
1192
1193 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, c->axen_buf + length);
1194 length += m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1195
1196 if ((length % boundary) == 0) {
1197 hdr.plen = 0x0;
1198 hdr.gso |= 0x80008000; /* enable padding */
1199 memcpy(c->axen_buf + length, &hdr, sizeof(hdr))__builtin_memcpy((c->axen_buf + length), (&hdr), (sizeof
(hdr)))
;
1200 length += sizeof(hdr);
1201 }
1202
1203 c->axen_mbuf = m;
1204
1205 usbd_setup_xfer(c->axen_xfer, sc->axen_ep[AXEN_ENDPT_TX0x1],
1206 c, c->axen_buf, length, USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01,
1207 10000, axen_txeof);
1208
1209 /* Transmit */
1210 err = usbd_transfer(c->axen_xfer);
1211 if (err != USBD_IN_PROGRESS) {
1212 c->axen_mbuf = NULL((void *)0);
1213 axen_stop(sc);
1214 return EIO5;
1215 }
1216
1217 sc->axen_cdata.axen_tx_cnt++;
1218
1219 return 0;
1220}
1221
1222void
1223axen_start(struct ifnet *ifp)
1224{
1225 struct axen_softc *sc;
1226 struct mbuf *m_head = NULL((void *)0);
1227
1228 sc = ifp->if_softc;
1229
1230 if (!sc->axen_link)
1231 return;
1232
1233 if (ifq_is_oactive(&ifp->if_snd))
1234 return;
1235
1236 m_head = ifq_dequeue(&ifp->if_snd);
1237 if (m_head == NULL((void *)0))
1238 return;
1239
1240 if (axen_encap(sc, m_head, 0)) {
1241 m_freem(m_head);
1242 ifq_set_oactive(&ifp->if_snd);
1243 return;
1244 }
1245
1246 /*
1247 * If there's a BPF listener, bounce a copy of this frame
1248 * to him.
1249 */
1250#if NBPFILTER1 > 0
1251 if (ifp->if_bpf)
1252 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT(1 << 1));
1253#endif
1254
1255 ifq_set_oactive(&ifp->if_snd);
1256
1257 /*
1258 * Set a timeout in case the chip goes out to lunch.
1259 */
1260 ifp->if_timer = 5;
1261}
1262
1263void
1264axen_init(void *xsc)
1265{
1266 struct axen_softc *sc = xsc;
1267 struct ifnet *ifp = &sc->arpcom.ac_if;
1268 struct axen_chain *c;
1269 usbd_status err;
1270 int i, s;
1271 uByte bval;
1272 uWord wval;
1273 uint16_t rxmode;
1274
1275 s = splnet()splraise(0x4);
1276
1277 /*
1278 * Cancel pending I/O and free all RX/TX buffers.
1279 */
1280 axen_reset(sc);
1281
1282 /* XXX: ? */
1283 bval = 0x01;
1284 axen_lock_mii(sc);
1285 axen_cmd(sc, AXEN_CMD_MAC_WRITE0x1101, 1, AXEN_UNK_280x28, &bval);
1286 axen_unlock_mii(sc);
1287
1288 /* Init RX ring. */
1289 if (axen_rx_list_init(sc) == ENOBUFS55) {
1290 printf("axen%d: rx list init failed\n", sc->axen_unit);
1291 splx(s)spllower(s);
1292 return;
1293 }
1294
1295 /* Init TX ring. */
1296 if (axen_tx_list_init(sc) == ENOBUFS55) {
1297 printf("axen%d: tx list init failed\n", sc->axen_unit);
1298 splx(s)spllower(s);
1299 return;
1300 }
1301
1302 /* Program promiscuous mode and multicast filters. */
1303 axen_iff(sc);
1304
1305 /* Enable receiver, set RX mode */
1306 axen_lock_mii(sc);
1307 axen_cmd(sc, AXEN_CMD_MAC_READ20x2001, 2, AXEN_MAC_RXCTL0x0b, &wval);
1308 rxmode = UGETW(wval)(*(u_int16_t *)(wval));
1309 rxmode |= AXEN_RXCTL_START0x0080;
1310 USETW(wval, rxmode)(*(u_int16_t *)(wval) = (rxmode));
1311 axen_cmd(sc, AXEN_CMD_MAC_WRITE20x2101, 2, AXEN_MAC_RXCTL0x0b, &wval);
1312 axen_unlock_mii(sc);
1313
1314 /* Open RX and TX pipes. */
1315 err = usbd_open_pipe(sc->axen_iface, sc->axen_ed[AXEN_ENDPT_RX0x0],
1316 USBD_EXCLUSIVE_USE0x01, &sc->axen_ep[AXEN_ENDPT_RX0x0]);
1317 if (err) {
1318 printf("axen%d: open rx pipe failed: %s\n",
1319 sc->axen_unit, usbd_errstr(err));
1320 splx(s)spllower(s);
1321 return;
1322 }
1323
1324 err = usbd_open_pipe(sc->axen_iface, sc->axen_ed[AXEN_ENDPT_TX0x1],
1325 USBD_EXCLUSIVE_USE0x01, &sc->axen_ep[AXEN_ENDPT_TX0x1]);
1326 if (err) {
1327 printf("axen%d: open tx pipe failed: %s\n",
1328 sc->axen_unit, usbd_errstr(err));
1329 splx(s)spllower(s);
1330 return;
1331 }
1332
1333 /* Start up the receive pipe. */
1334 for (i = 0; i < AXEN_RX_LIST_CNT1; i++) {
1335 c = &sc->axen_cdata.axen_rx_chain[i];
1336 usbd_setup_xfer(c->axen_xfer, sc->axen_ep[AXEN_ENDPT_RX0x0],
1337 c, c->axen_buf, sc->axen_bufsz,
1338 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
1339 USBD_NO_TIMEOUT0, axen_rxeof);
1340 usbd_transfer(c->axen_xfer);
1341 }
1342
1343 sc->axen_link = 0;
1344 ifp->if_flags |= IFF_RUNNING0x40;
1345 ifq_clr_oactive(&ifp->if_snd);
1346
1347 splx(s)spllower(s);
1348
1349 timeout_add_sec(&sc->axen_stat_ch, 1);
1350 return;
1351}
1352
1353int
1354axen_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1355{
1356 struct axen_softc *sc = ifp->if_softc;
1357 struct ifreq *ifr = (struct ifreq *)data;
1358 int s;
1359 int error = 0;
1360
1361 s = splnet()splraise(0x4);
1362
1363 switch(cmd) {
1
Control jumps to the 'default' case at line 1392
1364 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
1365 ifp->if_flags |= IFF_UP0x1;
1366 if (!(ifp->if_flags & IFF_RUNNING0x40))
1367 axen_init(sc);
1368 break;
1369
1370 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
1371 if (ifp->if_flags & IFF_UP0x1) {
1372 if (ifp->if_flags & IFF_RUNNING0x40)
1373 error = ENETRESET52;
1374 else
1375 axen_init(sc);
1376 } else {
1377 if (ifp->if_flags & IFF_RUNNING0x40)
1378 axen_stop(sc);
1379 }
1380 break;
1381
1382 case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
:
1383 case SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((55)))
:
1384 error = ifmedia_ioctl(ifp, ifr, &sc->axen_mii.mii_media, cmd);
1385 break;
1386
1387#if 0
1388 case SCIOCSIFMTU:
1389 /* XXX need to set AX_MEDIUM_JUMBO_EN here? */
1390 /* fall through */
1391#endif
1392 default:
1393 error = ether_ioctl(ifp, &sc->arpcom, cmd, data);
1394 }
1395
1396 if (error == ENETRESET52) {
2
Assuming 'error' is equal to ENETRESET
3
Taking true branch
1397 if (ifp->if_flags & IFF_RUNNING0x40)
4
Assuming the condition is true
5
Taking true branch
1398 axen_iff(sc);
6
Calling 'axen_iff'
1399 error = 0;
1400 }
1401
1402 splx(s)spllower(s);
1403
1404 return error;
1405}
1406
1407void
1408axen_watchdog(struct ifnet *ifp)
1409{
1410 struct axen_softc *sc;
1411 struct axen_chain *c;
1412 usbd_status stat;
1413 int s;
1414
1415 sc = ifp->if_softc;
1416
1417 ifp->if_oerrorsif_data.ifi_oerrors++;
1418 printf("axen%d: watchdog timeout\n", sc->axen_unit);
1419
1420 s = splusb()splraise(0x2);
1421 c = &sc->axen_cdata.axen_tx_chain[0];
1422 usbd_get_xfer_status(c->axen_xfer, NULL((void *)0), NULL((void *)0), NULL((void *)0), &stat);
1423 axen_txeof(c->axen_xfer, c, stat);
1424
1425 if (!ifq_empty(&ifp->if_snd)(({ typeof((&ifp->if_snd)->ifq_len) __tmp = *(volatile
typeof((&ifp->if_snd)->ifq_len) *)&((&ifp->
if_snd)->ifq_len); membar_datadep_consumer(); __tmp; }) ==
0)
)
1426 axen_start(ifp);
1427 splx(s)spllower(s);
1428}
1429
1430/*
1431 * Stop the adapter and free any mbufs allocated to the
1432 * RX and TX lists.
1433 */
1434void
1435axen_stop(struct axen_softc *sc)
1436{
1437 usbd_status err;
1438 struct ifnet *ifp;
1439 int i;
1440
1441 axen_reset(sc);
1442
1443 ifp = &sc->arpcom.ac_if;
1444 ifp->if_timer = 0;
1445 ifp->if_flags &= ~IFF_RUNNING0x40;
1446 ifq_clr_oactive(&ifp->if_snd);
1447
1448 timeout_del(&sc->axen_stat_ch);
1449
1450 /* Stop transfers. */
1451 if (sc->axen_ep[AXEN_ENDPT_RX0x0] != NULL((void *)0)) {
1452 err = usbd_close_pipe(sc->axen_ep[AXEN_ENDPT_RX0x0]);
1453 if (err) {
1454 printf("axen%d: close rx pipe failed: %s\n",
1455 sc->axen_unit, usbd_errstr(err));
1456 }
1457 sc->axen_ep[AXEN_ENDPT_RX0x0] = NULL((void *)0);
1458 }
1459
1460 if (sc->axen_ep[AXEN_ENDPT_TX0x1] != NULL((void *)0)) {
1461 err = usbd_close_pipe(sc->axen_ep[AXEN_ENDPT_TX0x1]);
1462 if (err) {
1463 printf("axen%d: close tx pipe failed: %s\n",
1464 sc->axen_unit, usbd_errstr(err));
1465 }
1466 sc->axen_ep[AXEN_ENDPT_TX0x1] = NULL((void *)0);
1467 }
1468
1469 if (sc->axen_ep[AXEN_ENDPT_INTR0x2] != NULL((void *)0)) {
1470 err = usbd_close_pipe(sc->axen_ep[AXEN_ENDPT_INTR0x2]);
1471 if (err) {
1472 printf("axen%d: close intr pipe failed: %s\n",
1473 sc->axen_unit, usbd_errstr(err));
1474 }
1475 sc->axen_ep[AXEN_ENDPT_INTR0x2] = NULL((void *)0);
1476 }
1477
1478 /* Free RX resources. */
1479 for (i = 0; i < AXEN_RX_LIST_CNT1; i++) {
1480 if (sc->axen_cdata.axen_rx_chain[i].axen_mbuf != NULL((void *)0)) {
1481 m_freem(sc->axen_cdata.axen_rx_chain[i].axen_mbuf);
1482 sc->axen_cdata.axen_rx_chain[i].axen_mbuf = NULL((void *)0);
1483 }
1484 if (sc->axen_cdata.axen_rx_chain[i].axen_xfer != NULL((void *)0)) {
1485 usbd_free_xfer(sc->axen_cdata.axen_rx_chain[i].axen_xfer);
1486 sc->axen_cdata.axen_rx_chain[i].axen_xfer = NULL((void *)0);
1487 }
1488 }
1489
1490 /* Free TX resources. */
1491 for (i = 0; i < AXEN_TX_LIST_CNT1; i++) {
1492
1493 if (sc->axen_cdata.axen_tx_chain[i].axen_mbuf != NULL((void *)0)) {
1494 m_freem(sc->axen_cdata.axen_tx_chain[i].axen_mbuf);
1495 sc->axen_cdata.axen_tx_chain[i].axen_mbuf = NULL((void *)0);
1496 }
1497 if (sc->axen_cdata.axen_tx_chain[i].axen_xfer != NULL((void *)0)) {
1498 usbd_free_xfer(sc->axen_cdata.axen_tx_chain[i].axen_xfer);
1499 sc->axen_cdata.axen_tx_chain[i].axen_xfer = NULL((void *)0);
1500 }
1501 }
1502
1503 sc->axen_link = 0;
1504}