Bug Summary

File:dev/usb/if_udav.c
Warning:line 1474, column 28
The left operand of '<<' is a garbage value

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_udav.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_udav.c
1/* $OpenBSD: if_udav.c,v 1.85 2021/08/09 07:21:48 jmatthew Exp $ */
2/* $NetBSD: if_udav.c,v 1.3 2004/04/23 17:25:25 itojun Exp $ */
3/* $nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $ */
4/*
5 * Copyright (c) 2003
6 * Shingo WATANABE <nabe@nabechan.org>. All rights reserved.
7 * Copyright (c) 2014
8 * Takayoshi SASANO <uaa@uaa.org.uk> (RD9700 support)
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 */
35
36/*
37 * DM9601(DAVICOM USB to Ethernet MAC Controller with Integrated 10/100 PHY)
38 * The spec can be found at the following url.
39 * http://www.meworks.net/userfile/24247/DM9601-DS-P03-102908.pdf
40 */
41
42/*
43 * TODO:
44 * Interrupt Endpoint support
45 * External PHYs
46 */
47
48#include "bpfilter.h"
49
50#include <sys/param.h>
51#include <sys/systm.h>
52#include <sys/rwlock.h>
53#include <sys/mbuf.h>
54#include <sys/kernel.h>
55#include <sys/socket.h>
56
57#include <sys/device.h>
58
59#include <net/if.h>
60#include <net/if_media.h>
61
62#if NBPFILTER1 > 0
63#include <net/bpf.h>
64#endif
65
66#include <netinet/in.h>
67#include <netinet/if_ether.h>
68
69#include <dev/mii/miivar.h>
70
71#include <dev/usb/usb.h>
72#include <dev/usb/usbdi.h>
73#include <dev/usb/usbdi_util.h>
74#include <dev/usb/usbdevs.h>
75
76#include <dev/usb/if_udavreg.h>
77
78int udav_match(struct device *, void *, void *);
79void udav_attach(struct device *, struct device *, void *);
80int udav_detach(struct device *, int);
81
82struct cfdriver udav_cd = {
83 NULL((void *)0), "udav", DV_IFNET
84};
85
86const struct cfattach udav_ca = {
87 sizeof(struct udav_softc), udav_match, udav_attach, udav_detach
88};
89
90int udav_openpipes(struct udav_softc *);
91int udav_rx_list_init(struct udav_softc *);
92int udav_tx_list_init(struct udav_softc *);
93int udav_newbuf(struct udav_softc *, struct udav_chain *, struct mbuf *);
94void udav_start(struct ifnet *);
95int udav_send(struct udav_softc *, struct mbuf *, int);
96void udav_txeof(struct usbd_xfer *, void *, usbd_status);
97void udav_rxeof(struct usbd_xfer *, void *, usbd_status);
98void udav_tick(void *);
99void udav_tick_task(void *);
100int udav_ioctl(struct ifnet *, u_long, caddr_t);
101void udav_stop_task(struct udav_softc *);
102void udav_stop(struct ifnet *, int);
103void udav_watchdog(struct ifnet *);
104int udav_ifmedia_change(struct ifnet *);
105void udav_ifmedia_status(struct ifnet *, struct ifmediareq *);
106void udav_lock_mii(struct udav_softc *);
107void udav_unlock_mii(struct udav_softc *);
108int udav_miibus_readreg(struct device *, int, int);
109void udav_miibus_writereg(struct device *, int, int, int);
110void udav_miibus_statchg(struct device *);
111int udav_init(struct ifnet *);
112void udav_iff(struct udav_softc *);
113void udav_reset(struct udav_softc *);
114
115int udav_csr_read(struct udav_softc *, int, void *, int);
116int udav_csr_write(struct udav_softc *, int, void *, int);
117int udav_csr_read1(struct udav_softc *, int);
118int udav_csr_write1(struct udav_softc *, int, unsigned char);
119
120#if 0
121int udav_mem_read(struct udav_softc *, int, void *, int);
122int udav_mem_write(struct udav_softc *, int, void *, int);
123int udav_mem_write1(struct udav_softc *, int, unsigned char);
124#endif
125
126/* Macros */
127#ifdef UDAV_DEBUG
128#define DPRINTF(x) do { if (udavdebug) printf x; } while(0)
129#define DPRINTFN(n,x) do { if (udavdebug >= (n)) printf x; } while(0)
130int udavdebug = 0;
131#else
132#define DPRINTF(x)
133#define DPRINTFN(n,x)
134#endif
135
136#define UDAV_SETBIT(sc, reg, x)udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) | (x)) \
137 udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) | (x))
138
139#define UDAV_CLRBIT(sc, reg, x)udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) & ~(x)) \
140 udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) & ~(x))
141
142static const struct udav_type {
143 struct usb_devno udav_dev;
144 u_int16_t udav_flags;
145#define UDAV_EXT_PHY0x0001 0x0001
146#define UDAV_RD97000x0002 0x0002
147} udav_devs [] = {
148 {{ USB_VENDOR_COREGA0x07aa, USB_PRODUCT_COREGA_FETHER_USB_TXC0x9601 }, 0 },
149 {{ USB_VENDOR_DAVICOM0x04a6, USB_PRODUCT_DAVICOM_DM96010x9601 }, 0 },
150 {{ USB_VENDOR_DAVICOM0x04a6, USB_PRODUCT_DAVICOM_WK6680x0668 }, 0 },
151 {{ USB_VENDOR_SHANTOU0x0a46, USB_PRODUCT_SHANTOU_DM96010x9601 }, 0 },
152 {{ USB_VENDOR_SHANTOU0x0a46, USB_PRODUCT_SHANTOU_ST2680x0268 }, 0 },
153 {{ USB_VENDOR_SHANTOU0x0a46, USB_PRODUCT_SHANTOU_ZT66880x6688 }, 0 },
154 {{ USB_VENDOR_SHANTOU0x0a46, USB_PRODUCT_SHANTOU_ADM85150x8515 }, 0 },
155 {{ USB_VENDOR_UNKNOWN40x0fe6, USB_PRODUCT_UNKNOWN4_DM96010x8101 }, 0 },
156 {{ USB_VENDOR_UNKNOWN60x01e1, USB_PRODUCT_UNKNOWN6_DM96010x9601 }, 0 },
157 {{ USB_VENDOR_UNKNOWN40x0fe6, USB_PRODUCT_UNKNOWN4_RD97000x9700 }, UDAV_RD97000x0002 },
158};
159#define udav_lookup(v, p)((struct udav_type *)usbd_match_device((const struct usb_devno
*)(udav_devs), sizeof (udav_devs) / sizeof ((udav_devs)[0]),
sizeof ((udav_devs)[0]), (v), (p)))
((struct udav_type *)usb_lookup(udav_devs, v, p)usbd_match_device((const struct usb_devno *)(udav_devs), sizeof
(udav_devs) / sizeof ((udav_devs)[0]), sizeof ((udav_devs)[0
]), (v), (p))
)
160
161
162/* Probe */
163int
164udav_match(struct device *parent, void *match, void *aux)
165{
166 struct usb_attach_arg *uaa = aux;
167
168 if (uaa->iface == NULL((void *)0) || uaa->configno != 1)
169 return (UMATCH_NONE0);
170
171 return (udav_lookup(uaa->vendor, uaa->product)((struct udav_type *)usbd_match_device((const struct usb_devno
*)(udav_devs), sizeof (udav_devs) / sizeof ((udav_devs)[0]),
sizeof ((udav_devs)[0]), (uaa->vendor), (uaa->product)
))
!= NULL((void *)0) ?
172 UMATCH_VENDOR_PRODUCT_CONF_IFACE8 : UMATCH_NONE0);
173}
174
175/* Attach */
176void
177udav_attach(struct device *parent, struct device *self, void *aux)
178{
179 struct udav_softc *sc = (struct udav_softc *)self;
180 struct usb_attach_arg *uaa = aux;
181 struct usbd_device *dev = uaa->device;
182 struct usbd_interface *iface = uaa->iface;
183 usbd_status err;
184 usb_interface_descriptor_t *id;
185 usb_endpoint_descriptor_t *ed;
186 char *devname = sc->sc_dev.dv_xname;
187 struct ifnet *ifp;
188 struct mii_data *mii;
189 u_char eaddr[ETHER_ADDR_LEN6];
190 int i, s;
191
192 printf("%s: ", devname);
193
194 sc->sc_udev = dev;
195
196 usb_init_task(&sc->sc_tick_task, udav_tick_task, sc,((&sc->sc_tick_task)->fun = (udav_tick_task), (&
sc->sc_tick_task)->arg = (sc), (&sc->sc_tick_task
)->type = (0), (&sc->sc_tick_task)->state = 0x0)
197 USB_TASK_TYPE_GENERIC)((&sc->sc_tick_task)->fun = (udav_tick_task), (&
sc->sc_tick_task)->arg = (sc), (&sc->sc_tick_task
)->type = (0), (&sc->sc_tick_task)->state = 0x0)
;
198 rw_init(&sc->sc_mii_lock, "udavmii")_rw_init_flags(&sc->sc_mii_lock, "udavmii", 0, ((void *
)0))
;
199 usb_init_task(&sc->sc_stop_task, (void (*)(void *)) udav_stop_task, sc,((&sc->sc_stop_task)->fun = ((void (*)(void *)) udav_stop_task
), (&sc->sc_stop_task)->arg = (sc), (&sc->sc_stop_task
)->type = (0), (&sc->sc_stop_task)->state = 0x0)
200 USB_TASK_TYPE_GENERIC)((&sc->sc_stop_task)->fun = ((void (*)(void *)) udav_stop_task
), (&sc->sc_stop_task)->arg = (sc), (&sc->sc_stop_task
)->type = (0), (&sc->sc_stop_task)->state = 0x0)
;
201
202 sc->sc_ctl_iface = iface;
203 sc->sc_flags = udav_lookup(uaa->vendor, uaa->product)((struct udav_type *)usbd_match_device((const struct usb_devno
*)(udav_devs), sizeof (udav_devs) / sizeof ((udav_devs)[0]),
sizeof ((udav_devs)[0]), (uaa->vendor), (uaa->product)
))
->udav_flags;
204
205 /* get interface descriptor */
206 id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
207
208 /* find endpoints */
209 sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1;
210 for (i = 0; i < id->bNumEndpoints; i++) {
211 ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i);
212 if (ed == NULL((void *)0)) {
213 printf("couldn't get endpoint %d\n", i);
214 goto bad;
215 }
216 if (UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02 &&
217 UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80)
218 sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */
219 else if (UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02 &&
220 UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_OUT0x00)
221 sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */
222 else if (UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_INTERRUPT0x03 &&
223 UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80)
224 sc->sc_intrin_no = ed->bEndpointAddress; /* Status */
225 }
226
227 if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 ||
228 sc->sc_intrin_no == -1) {
229 printf("missing endpoint\n");
230 goto bad;
231 }
232
233 s = splnet()splraise(0x7);
234
235 /* reset the adapter */
236 udav_reset(sc);
237
238 /* Get Ethernet Address */
239 err = udav_csr_read(sc, UDAV_PAR0x10, (void *)eaddr, ETHER_ADDR_LEN6);
240 if (err) {
241 printf("read MAC address failed\n");
242 splx(s)spllower(s);
243 goto bad;
244 }
245
246 /* Print Ethernet Address */
247 printf("address %s\n", ether_sprintf(eaddr));
248
249 bcopy(eaddr, (char *)&sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN6);
250
251 /* initialize interface information */
252 ifp = GET_IFP(sc)(&(sc)->sc_ac.ac_if);
253 ifp->if_softc = sc;
254 strlcpy(ifp->if_xname, devname, IFNAMSIZ16);
255 ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000;
256 ifp->if_start = udav_start;
257 ifp->if_ioctl = udav_ioctl;
258 ifp->if_watchdog = udav_watchdog;
259
260 /*
261 * Do ifmedia setup.
262 */
263 mii = &sc->sc_mii;
264 mii->mii_ifp = ifp;
265 mii->mii_readreg = udav_miibus_readreg;
266 mii->mii_writereg = udav_miibus_writereg;
267 mii->mii_statchg = udav_miibus_statchg;
268 mii->mii_flags = MIIF_AUTOTSLEEP0x0010;
269 ifmedia_init(&mii->mii_media, 0,
270 udav_ifmedia_change, udav_ifmedia_status);
271 if (sc->sc_flags & UDAV_RD97000x0002) {
272 /* no MII-PHY */
273 ifmedia_add(&mii->mii_media, IFM_ETHER0x0000000000000100ULL | IFM_NONE2ULL, 0, NULL((void *)0));
274 ifmedia_set(&mii->mii_media, IFM_ETHER0x0000000000000100ULL | IFM_NONE2ULL);
275 } else {
276 mii_attach(self, mii, 0xffffffff,
277 MII_PHY_ANY-1, MII_OFFSET_ANY-1, 0);
278 if (LIST_FIRST(&mii->mii_phys)((&mii->mii_phys)->lh_first) == NULL((void *)0)) {
279 ifmedia_add(&mii->mii_media, IFM_ETHER0x0000000000000100ULL | IFM_NONE2ULL,
280 0, NULL((void *)0));
281 ifmedia_set(&mii->mii_media, IFM_ETHER0x0000000000000100ULL | IFM_NONE2ULL);
282 } else
283 ifmedia_set(&mii->mii_media, IFM_ETHER0x0000000000000100ULL | IFM_AUTO0ULL);
284 }
285
286 /* attach the interface */
287 if_attach(ifp);
288 ether_ifattach(ifp);
289
290 timeout_set(&sc->sc_stat_ch, udav_tick, sc);
291
292 splx(s)spllower(s);
293
294 return;
295
296 bad:
297 usbd_deactivate(sc->sc_udev);
298}
299
300/* detach */
301int
302udav_detach(struct device *self, int flags)
303{
304 struct udav_softc *sc = (struct udav_softc *)self;
305 struct ifnet *ifp = GET_IFP(sc)(&(sc)->sc_ac.ac_if);
306 int s;
307
308 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
309
310
311 if (timeout_initialized(&sc->sc_stat_ch)((&sc->sc_stat_ch)->to_flags & 0x04))
312 timeout_del(&sc->sc_stat_ch);
313
314 /* Remove any pending tasks */
315 usb_rem_task(sc->sc_udev, &sc->sc_tick_task);
316 usb_rem_task(sc->sc_udev, &sc->sc_stop_task);
317
318 s = splusb()splraise(0x5);
319
320 if (--sc->sc_refcnt >= 0) {
321 /* Wait for processes to go away */
322 usb_detach_wait(&sc->sc_dev);
323 }
324 if (ifp->if_flags & IFF_RUNNING0x40)
325 udav_stop(GET_IFP(sc)(&(sc)->sc_ac.ac_if), 1);
326
327 if (!(sc->sc_flags & UDAV_RD97000x0002))
328 mii_detach(&sc->sc_mii, MII_PHY_ANY-1, MII_OFFSET_ANY-1);
329 ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY((uint64_t) -1));
330 if (ifp->if_softc != NULL((void *)0)) {
331 ether_ifdetach(ifp);
332 if_detach(ifp);
333 }
334
335#ifdef DIAGNOSTIC1
336 if (sc->sc_pipe_tx != NULL((void *)0))
337 printf("%s: detach has active tx endpoint.\n",
338 sc->sc_dev.dv_xname);
339 if (sc->sc_pipe_rx != NULL((void *)0))
340 printf("%s: detach has active rx endpoint.\n",
341 sc->sc_dev.dv_xname);
342 if (sc->sc_pipe_intr != NULL((void *)0))
343 printf("%s: detach has active intr endpoint.\n",
344 sc->sc_dev.dv_xname);
345#endif
346 splx(s)spllower(s);
347
348 return (0);
349}
350
351#if 0
352/* read memory */
353int
354udav_mem_read(struct udav_softc *sc, int offset, void *buf, int len)
355{
356 usb_device_request_t req;
357 usbd_status err;
358
359 if (sc == NULL((void *)0))
360 return (0);
361
362 DPRINTFN(0x200,
363 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
364
365 if (usbd_is_dying(sc->sc_udev))
366 return (0);
367
368 offset &= 0xffff;
369 len &= 0xff;
370
371 req.bmRequestType = UT_READ_VENDOR_DEVICE(0x80 | 0x40 | 0x00);
372 req.bRequest = UDAV_REQ_MEM_READ0x02;
373 USETW(req.wValue, 0x0000)(*(u_int16_t *)(req.wValue) = (0x0000));
374 USETW(req.wIndex, offset)(*(u_int16_t *)(req.wIndex) = (offset));
375 USETW(req.wLength, len)(*(u_int16_t *)(req.wLength) = (len));
376
377 sc->sc_refcnt++;
378 err = usbd_do_request(sc->sc_udev, &req, buf);
379 if (--sc->sc_refcnt < 0)
380 usb_detach_wakeup(&sc->sc_dev);
381 if (err) {
382 DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
383 sc->sc_dev.dv_xname, __func__, offset, err));
384 }
385
386 return (err);
387}
388
389/* write memory */
390int
391udav_mem_write(struct udav_softc *sc, int offset, void *buf, int len)
392{
393 usb_device_request_t req;
394 usbd_status err;
395
396 if (sc == NULL((void *)0))
397 return (0);
398
399 DPRINTFN(0x200,
400 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
401
402 if (usbd_is_dying(sc->sc_udev))
403 return (0);
404
405 offset &= 0xffff;
406 len &= 0xff;
407
408 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
409 req.bRequest = UDAV_REQ_MEM_WRITE0x05;
410 USETW(req.wValue, 0x0000)(*(u_int16_t *)(req.wValue) = (0x0000));
411 USETW(req.wIndex, offset)(*(u_int16_t *)(req.wIndex) = (offset));
412 USETW(req.wLength, len)(*(u_int16_t *)(req.wLength) = (len));
413
414 sc->sc_refcnt++;
415 err = usbd_do_request(sc->sc_udev, &req, buf);
416 if (--sc->sc_refcnt < 0)
417 usb_detach_wakeup(&sc->sc_dev);
418 if (err) {
419 DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
420 sc->sc_dev.dv_xname, __func__, offset, err));
421 }
422
423 return (err);
424}
425
426/* write memory */
427int
428udav_mem_write1(struct udav_softc *sc, int offset, unsigned char ch)
429{
430 usb_device_request_t req;
431 usbd_status err;
432
433 if (sc == NULL((void *)0))
434 return (0);
435
436 DPRINTFN(0x200,
437 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
438
439 if (usbd_is_dying(sc->sc_udev))
440 return (0);
441
442 offset &= 0xffff;
443
444 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
445 req.bRequest = UDAV_REQ_MEM_WRITE10x07;
446 USETW(req.wValue, ch)(*(u_int16_t *)(req.wValue) = (ch));
447 USETW(req.wIndex, offset)(*(u_int16_t *)(req.wIndex) = (offset));
448 USETW(req.wLength, 0x0000)(*(u_int16_t *)(req.wLength) = (0x0000));
449
450 sc->sc_refcnt++;
451 err = usbd_do_request(sc->sc_udev, &req, NULL((void *)0));
452 if (--sc->sc_refcnt < 0)
453 usb_detach_wakeup(&sc->sc_dev);
454 if (err) {
455 DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
456 sc->sc_dev.dv_xname, __func__, offset, err));
457 }
458
459 return (err);
460}
461#endif
462
463/* read register(s) */
464int
465udav_csr_read(struct udav_softc *sc, int offset, void *buf, int len)
466{
467 usb_device_request_t req;
468 usbd_status err;
469
470 if (sc
7.1
'sc' is not equal to NULL
== NULL((void *)0))
8
Taking false branch
471 return (0);
472
473 DPRINTFN(0x200,
474 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
475
476 if (usbd_is_dying(sc->sc_udev))
9
Assuming the condition is true
10
Taking true branch
477 return (0);
478
479 offset &= 0xff;
480 len &= 0xff;
481
482 req.bmRequestType = UT_READ_VENDOR_DEVICE(0x80 | 0x40 | 0x00);
483 req.bRequest = UDAV_REQ_REG_READ0x00;
484 USETW(req.wValue, 0x0000)(*(u_int16_t *)(req.wValue) = (0x0000));
485 USETW(req.wIndex, offset)(*(u_int16_t *)(req.wIndex) = (offset));
486 USETW(req.wLength, len)(*(u_int16_t *)(req.wLength) = (len));
487
488 sc->sc_refcnt++;
489 err = usbd_do_request(sc->sc_udev, &req, buf);
490 if (--sc->sc_refcnt < 0)
491 usb_detach_wakeup(&sc->sc_dev);
492 if (err) {
493 DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
494 sc->sc_dev.dv_xname, __func__, offset, err));
495 }
496
497 return (err);
498}
499
500/* write register(s) */
501int
502udav_csr_write(struct udav_softc *sc, int offset, void *buf, int len)
503{
504 usb_device_request_t req;
505 usbd_status err;
506
507 if (sc == NULL((void *)0))
508 return (0);
509
510 DPRINTFN(0x200,
511 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
512
513 if (usbd_is_dying(sc->sc_udev))
514 return (0);
515
516 offset &= 0xff;
517 len &= 0xff;
518
519 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
520 req.bRequest = UDAV_REQ_REG_WRITE0x01;
521 USETW(req.wValue, 0x0000)(*(u_int16_t *)(req.wValue) = (0x0000));
522 USETW(req.wIndex, offset)(*(u_int16_t *)(req.wIndex) = (offset));
523 USETW(req.wLength, len)(*(u_int16_t *)(req.wLength) = (len));
524
525 sc->sc_refcnt++;
526 err = usbd_do_request(sc->sc_udev, &req, buf);
527 if (--sc->sc_refcnt < 0)
528 usb_detach_wakeup(&sc->sc_dev);
529 if (err) {
530 DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
531 sc->sc_dev.dv_xname, __func__, offset, err));
532 }
533
534 return (err);
535}
536
537int
538udav_csr_read1(struct udav_softc *sc, int offset)
539{
540 u_int8_t val = 0;
541
542 if (sc == NULL((void *)0))
543 return (0);
544
545 DPRINTFN(0x200,
546 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
547
548 return (udav_csr_read(sc, offset, &val, 1) ? 0 : val);
549}
550
551/* write a register */
552int
553udav_csr_write1(struct udav_softc *sc, int offset, unsigned char ch)
554{
555 usb_device_request_t req;
556 usbd_status err;
557
558 if (sc == NULL((void *)0))
559 return (0);
560
561 DPRINTFN(0x200,
562 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
563
564 if (usbd_is_dying(sc->sc_udev))
565 return (0);
566
567 offset &= 0xff;
568
569 req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00);
570 req.bRequest = UDAV_REQ_REG_WRITE10x03;
571 USETW(req.wValue, ch)(*(u_int16_t *)(req.wValue) = (ch));
572 USETW(req.wIndex, offset)(*(u_int16_t *)(req.wIndex) = (offset));
573 USETW(req.wLength, 0x0000)(*(u_int16_t *)(req.wLength) = (0x0000));
574
575 sc->sc_refcnt++;
576 err = usbd_do_request(sc->sc_udev, &req, NULL((void *)0));
577 if (--sc->sc_refcnt < 0)
578 usb_detach_wakeup(&sc->sc_dev);
579 if (err) {
580 DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
581 sc->sc_dev.dv_xname, __func__, offset, err));
582 }
583
584 return (err);
585}
586
587int
588udav_init(struct ifnet *ifp)
589{
590 struct udav_softc *sc = ifp->if_softc;
591 struct mii_data *mii = GET_MII(sc)(&(sc)->sc_mii);
592 u_char *eaddr;
593 int s;
594
595 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
596
597 s = splnet()splraise(0x7);
598
599 /* Cancel pending I/O and free all TX/RX buffers */
600 udav_stop(ifp, 1);
601
602 eaddr = sc->sc_ac.ac_enaddr;
603 udav_csr_write(sc, UDAV_PAR0x10, eaddr, ETHER_ADDR_LEN6);
604
605 /* Initialize network control register */
606 /* Disable loopback */
607 UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_LBK0 | UDAV_NCR_LBK1)udav_csr_write1(sc, 0x00, udav_csr_read1(sc, 0x00) & ~((1
<<1) | (1<<2)))
;
608
609 /* Initialize RX control register */
610 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_DIS_LONG | UDAV_RCR_DIS_CRC)udav_csr_write1(sc, 0x05, udav_csr_read1(sc, 0x05) | ((1<<
5) | (1<<4)))
;
611
612 /* Initialize transmit ring */
613 if (udav_tx_list_init(sc) == ENOBUFS55) {
614 printf("%s: tx list init failed\n", sc->sc_dev.dv_xname);
615 splx(s)spllower(s);
616 return (EIO5);
617 }
618
619 /* Initialize receive ring */
620 if (udav_rx_list_init(sc) == ENOBUFS55) {
621 printf("%s: rx list init failed\n", sc->sc_dev.dv_xname);
622 splx(s)spllower(s);
623 return (EIO5);
624 }
625
626 /* Program promiscuous mode and multicast filters */
627 udav_iff(sc);
628
629 /* Enable RX */
630 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_RXEN)udav_csr_write1(sc, 0x05, udav_csr_read1(sc, 0x05) | ((1<<
0)))
;
631
632 /* clear POWER_DOWN state of internal PHY */
633 UDAV_SETBIT(sc, UDAV_GPCR, UDAV_GPCR_GEP_CNTL0)udav_csr_write1(sc, 0x1e, udav_csr_read1(sc, 0x1e) | ((1<<
0)))
;
634 UDAV_CLRBIT(sc, UDAV_GPR, UDAV_GPR_GEPIO0)udav_csr_write1(sc, 0x1f, udav_csr_read1(sc, 0x1f) & ~((1
<<0)))
;
635
636 if (!(sc->sc_flags & UDAV_RD97000x0002))
637 mii_mediachg(mii);
638
639 if (sc->sc_pipe_tx == NULL((void *)0) || sc->sc_pipe_rx == NULL((void *)0)) {
640 if (udav_openpipes(sc)) {
641 splx(s)spllower(s);
642 return (EIO5);
643 }
644 }
645
646 ifp->if_flags |= IFF_RUNNING0x40;
647 ifq_clr_oactive(&ifp->if_snd);
648
649 splx(s)spllower(s);
650
651 timeout_add_sec(&sc->sc_stat_ch, 1);
652
653 return (0);
654}
655
656void
657udav_reset(struct udav_softc *sc)
658{
659 int i;
660
661 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
662
663 if (usbd_is_dying(sc->sc_udev))
664 return;
665
666 /* Select PHY */
667#if 1
668 /*
669 * XXX: force select internal phy.
670 * external phy routines are not tested.
671 */
672 UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY)udav_csr_write1(sc, 0x00, udav_csr_read1(sc, 0x00) & ~((1
<<7)))
;
673#else
674 if (sc->sc_flags & UDAV_EXT_PHY0x0001) {
675 UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY)udav_csr_write1(sc, 0x00, udav_csr_read1(sc, 0x00) | ((1<<
7)))
;
676 } else {
677 UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY)udav_csr_write1(sc, 0x00, udav_csr_read1(sc, 0x00) & ~((1
<<7)))
;
678 }
679#endif
680
681 UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_RST)udav_csr_write1(sc, 0x00, udav_csr_read1(sc, 0x00) | ((1<<
0)))
;
682
683 for (i = 0; i < UDAV_TX_TIMEOUT1000; i++) {
684 if (!(udav_csr_read1(sc, UDAV_NCR0x00) & UDAV_NCR_RST(1<<0)))
685 break;
686 delay(10)(*delay_func)(10); /* XXX */
687 }
688 delay(10000)(*delay_func)(10000); /* XXX */
689}
690
691#define UDAV_BITS6 6
692
693void
694udav_iff(struct udav_softc *sc)
695{
696 struct ifnet *ifp = GET_IFP(sc)(&(sc)->sc_ac.ac_if);
697 struct arpcom *ac = &sc->sc_ac;
698 struct ether_multi *enm;
699 struct ether_multistep step;
700 u_int8_t hashes[8];
701 int h = 0;
702
703 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
704
705 if (usbd_is_dying(sc->sc_udev))
706 return;
707
708 UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC)udav_csr_write1(sc, 0x05, udav_csr_read1(sc, 0x05) & ~((1
<<3) | (1<<1)))
;
709 memset(hashes, 0x00, sizeof(hashes))__builtin_memset((hashes), (0x00), (sizeof(hashes)));
710 ifp->if_flags &= ~IFF_ALLMULTI0x200;
711
712 if (ifp->if_flags & IFF_PROMISC0x100 || ac->ac_multirangecnt > 0) {
713 ifp->if_flags |= IFF_ALLMULTI0x200;
714 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL)udav_csr_write1(sc, 0x05, udav_csr_read1(sc, 0x05) | ((1<<
3)))
;
715 if (ifp->if_flags & IFF_PROMISC0x100)
716 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_PRMSC)udav_csr_write1(sc, 0x05, udav_csr_read1(sc, 0x05) | ((1<<
1)))
;
717 } else {
718 hashes[7] |= 0x80; /* broadcast address */
719
720 /* now program new ones */
721 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)
;
722 while (enm != NULL((void *)0)) {
723 h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN6) &
724 ((1 << UDAV_BITS6) - 1);
725
726 hashes[h>>3] |= 1 << (h & 0x7);
727
728 ETHER_NEXT_MULTI(step, enm)do { if (((enm) = (step).e_enm) != ((void *)0)) (step).e_enm =
(((enm))->enm_list.le_next); } while ( 0)
;
729 }
730 }
731
732 udav_csr_write(sc, UDAV_MAR0x16, hashes, sizeof(hashes));
733}
734
735int
736udav_openpipes(struct udav_softc *sc)
737{
738 struct udav_chain *c;
739 usbd_status err;
740 int i;
741 int error = 0;
742
743 if (usbd_is_dying(sc->sc_udev))
744 return (EIO5);
745
746 sc->sc_refcnt++;
747
748 /* Open RX pipe */
749 err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no,
750 USBD_EXCLUSIVE_USE0x01, &sc->sc_pipe_rx);
751 if (err) {
752 printf("%s: open rx pipe failed: %s\n",
753 sc->sc_dev.dv_xname, usbd_errstr(err));
754 error = EIO5;
755 goto done;
756 }
757
758 /* Open TX pipe */
759 err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no,
760 USBD_EXCLUSIVE_USE0x01, &sc->sc_pipe_tx);
761 if (err) {
762 printf("%s: open tx pipe failed: %s\n",
763 sc->sc_dev.dv_xname, usbd_errstr(err));
764 error = EIO5;
765 goto done;
766 }
767
768#if 0
769 /* XXX: interrupt endpoint is not yet supported */
770 /* Open Interrupt pipe */
771 err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no,
772 0, &sc->sc_pipe_intr, sc,
773 &sc->sc_cdata.udav_ibuf, UDAV_INTR_PKGLEN,
774 udav_intr, UDAV_INTR_INTERVAL);
775 if (err) {
776 printf("%s: open intr pipe failed: %s\n",
777 sc->sc_dev.dv_xname, usbd_errstr(err));
778 error = EIO5;
779 goto done;
780 }
781#endif
782
783
784 /* Start up the receive pipe. */
785 for (i = 0; i < UDAV_RX_LIST_CNT1; i++) {
786 c = &sc->sc_cdata.udav_rx_chain[i];
787 usbd_setup_xfer(c->udav_xfer, sc->sc_pipe_rx,
788 c, c->udav_buf, UDAV_BUFSZ1522 + sizeof(struct udav_rx_hdr),
789 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
790 USBD_NO_TIMEOUT0, udav_rxeof);
791 (void)usbd_transfer(c->udav_xfer);
792 DPRINTF(("%s: %s: start read\n", sc->sc_dev.dv_xname,
793 __func__));
794 }
795
796 done:
797 if (--sc->sc_refcnt < 0)
798 usb_detach_wakeup(&sc->sc_dev);
799
800 return (error);
801}
802
803int
804udav_newbuf(struct udav_softc *sc, struct udav_chain *c, struct mbuf *m)
805{
806 struct mbuf *m_new = NULL((void *)0);
807
808 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
809
810 if (m == NULL((void *)0)) {
811 MGETHDR(m_new, M_DONTWAIT, MT_DATA)m_new = m_gethdr((0x0002), (1));
812 if (m_new == NULL((void *)0)) {
813 printf("%s: no memory for rx list "
814 "-- packet dropped!\n", sc->sc_dev.dv_xname);
815 return (ENOBUFS55);
816 }
817 MCLGET(m_new, M_DONTWAIT)(void) m_clget((m_new), (0x0002), (1 << 11));
818 if (!(m_new->m_flagsm_hdr.mh_flags & M_EXT0x0001)) {
819 printf("%s: no memory for rx list "
820 "-- packet dropped!\n", sc->sc_dev.dv_xname);
821 m_freem(m_new);
822 return (ENOBUFS55);
823 }
824 m_new->m_lenm_hdr.mh_len = m_new->m_pkthdrM_dat.MH.MH_pkthdr.len = MCLBYTES(1 << 11);
825 } else {
826 m_new = m;
827 m_new->m_lenm_hdr.mh_len = m_new->m_pkthdrM_dat.MH.MH_pkthdr.len = MCLBYTES(1 << 11);
828 m_new->m_datam_hdr.mh_data = m_new->m_extM_dat.MH.MH_dat.MH_ext.ext_buf;
829 }
830
831 m_adj(m_new, ETHER_ALIGN2);
832 c->udav_mbuf = m_new;
833
834 return (0);
835}
836
837
838int
839udav_rx_list_init(struct udav_softc *sc)
840{
841 struct udav_cdata *cd;
842 struct udav_chain *c;
843 int i;
844
845 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
846
847 cd = &sc->sc_cdata;
848 for (i = 0; i < UDAV_RX_LIST_CNT1; i++) {
849 c = &cd->udav_rx_chain[i];
850 c->udav_sc = sc;
851 c->udav_idx = i;
852 if (udav_newbuf(sc, c, NULL((void *)0)) == ENOBUFS55)
853 return (ENOBUFS55);
854 if (c->udav_xfer == NULL((void *)0)) {
855 c->udav_xfer = usbd_alloc_xfer(sc->sc_udev);
856 if (c->udav_xfer == NULL((void *)0))
857 return (ENOBUFS55);
858 c->udav_buf = usbd_alloc_buffer(c->udav_xfer, UDAV_BUFSZ1522 + sizeof(struct udav_rx_hdr));
859 if (c->udav_buf == NULL((void *)0)) {
860 usbd_free_xfer(c->udav_xfer);
861 return (ENOBUFS55);
862 }
863 }
864 }
865
866 return (0);
867}
868
869int
870udav_tx_list_init(struct udav_softc *sc)
871{
872 struct udav_cdata *cd;
873 struct udav_chain *c;
874 int i;
875
876 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
877
878 cd = &sc->sc_cdata;
879 for (i = 0; i < UDAV_TX_LIST_CNT1; i++) {
880 c = &cd->udav_tx_chain[i];
881 c->udav_sc = sc;
882 c->udav_idx = i;
883 c->udav_mbuf = NULL((void *)0);
884 if (c->udav_xfer == NULL((void *)0)) {
885 c->udav_xfer = usbd_alloc_xfer(sc->sc_udev);
886 if (c->udav_xfer == NULL((void *)0))
887 return (ENOBUFS55);
888 c->udav_buf = usbd_alloc_buffer(c->udav_xfer, UDAV_BUFSZ1522 + sizeof(struct udav_rx_hdr));
889 if (c->udav_buf == NULL((void *)0)) {
890 usbd_free_xfer(c->udav_xfer);
891 return (ENOBUFS55);
892 }
893 }
894 }
895
896 return (0);
897}
898
899void
900udav_start(struct ifnet *ifp)
901{
902 struct udav_softc *sc = ifp->if_softc;
903 struct mbuf *m_head = NULL((void *)0);
904
905 DPRINTF(("%s: %s: enter, link=%d\n", sc->sc_dev.dv_xname,
906 __func__, sc->sc_link));
907
908 if (usbd_is_dying(sc->sc_udev))
909 return;
910
911 if (!sc->sc_link)
912 return;
913
914 if (ifq_is_oactive(&ifp->if_snd))
915 return;
916
917 m_head = ifq_deq_begin(&ifp->if_snd);
918 if (m_head == NULL((void *)0))
919 return;
920
921 if (udav_send(sc, m_head, 0)) {
922 ifq_deq_rollback(&ifp->if_snd, m_head);
923 ifq_set_oactive(&ifp->if_snd);
924 return;
925 }
926
927 ifq_deq_commit(&ifp->if_snd, m_head);
928
929#if NBPFILTER1 > 0
930 if (ifp->if_bpf)
931 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT(1 << 1));
932#endif
933
934 ifq_set_oactive(&ifp->if_snd);
935
936 /* Set a timeout in case the chip goes out to lunch. */
937 ifp->if_timer = 5;
938}
939
940int
941udav_send(struct udav_softc *sc, struct mbuf *m, int idx)
942{
943 int total_len;
944 struct udav_chain *c;
945 usbd_status err;
946
947 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
948
949 c = &sc->sc_cdata.udav_tx_chain[idx];
950
951 /* Copy the mbuf data into a contiguous buffer */
952 /* first 2 bytes are packet length */
953 m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, c->udav_buf + 2);
954 c->udav_mbuf = m;
955 total_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
956 if (total_len < UDAV_MIN_FRAME_LEN60) {
957 memset(c->udav_buf + 2 + total_len, 0,__builtin_memset((c->udav_buf + 2 + total_len), (0), (60 -
total_len))
958 UDAV_MIN_FRAME_LEN - total_len)__builtin_memset((c->udav_buf + 2 + total_len), (0), (60 -
total_len))
;
959 total_len = UDAV_MIN_FRAME_LEN60;
960 }
961
962 /* Frame length is specified in the first 2bytes of the buffer */
963 c->udav_buf[0] = (u_int8_t)total_len;
964 c->udav_buf[1] = (u_int8_t)(total_len >> 8);
965 total_len += 2;
966
967 usbd_setup_xfer(c->udav_xfer, sc->sc_pipe_tx, c, c->udav_buf, total_len,
968 USBD_FORCE_SHORT_XFER0x08 | USBD_NO_COPY0x01,
969 UDAV_TX_TIMEOUT1000, udav_txeof);
970
971 /* Transmit */
972 sc->sc_refcnt++;
973 err = usbd_transfer(c->udav_xfer);
974 if (--sc->sc_refcnt < 0)
975 usb_detach_wakeup(&sc->sc_dev);
976 if (err != USBD_IN_PROGRESS) {
977 printf("%s: udav_send error=%s\n", sc->sc_dev.dv_xname,
978 usbd_errstr(err));
979 /* Stop the interface */
980 usb_add_task(sc->sc_udev, &sc->sc_stop_task);
981 return (EIO5);
982 }
983
984 DPRINTF(("%s: %s: send %d bytes\n", sc->sc_dev.dv_xname,
985 __func__, total_len));
986
987 sc->sc_cdata.udav_tx_cnt++;
988
989 return (0);
990}
991
992void
993udav_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
994{
995 struct udav_chain *c = priv;
996 struct udav_softc *sc = c->udav_sc;
997 struct ifnet *ifp = GET_IFP(sc)(&(sc)->sc_ac.ac_if);
998 int s;
999
1000 if (usbd_is_dying(sc->sc_udev))
1001 return;
1002
1003 s = splnet()splraise(0x7);
1004
1005 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1006
1007 ifp->if_timer = 0;
1008 ifq_clr_oactive(&ifp->if_snd);
1009
1010 if (status != USBD_NORMAL_COMPLETION) {
1011 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
1012 splx(s)spllower(s);
1013 return;
1014 }
1015 ifp->if_oerrorsif_data.ifi_oerrors++;
1016 printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname,
1017 usbd_errstr(status));
1018 if (status == USBD_STALLED) {
1019 sc->sc_refcnt++;
1020 usbd_clear_endpoint_stall_async(sc->sc_pipe_tx);
1021 if (--sc->sc_refcnt < 0)
1022 usb_detach_wakeup(&sc->sc_dev);
1023 }
1024 splx(s)spllower(s);
1025 return;
1026 }
1027
1028 m_freem(c->udav_mbuf);
1029 c->udav_mbuf = NULL((void *)0);
1030
1031 if (ifq_empty(&ifp->if_snd)(((&ifp->if_snd)->ifq_len) == 0) == 0)
1032 udav_start(ifp);
1033
1034 splx(s)spllower(s);
1035}
1036
1037void
1038udav_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
1039{
1040 struct udav_chain *c = priv;
1041 struct udav_softc *sc = c->udav_sc;
1042 struct ifnet *ifp = GET_IFP(sc)(&(sc)->sc_ac.ac_if);
1043 struct udav_rx_hdr *h;
1044 struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 };
1045 struct mbuf *m;
1046 u_int32_t total_len;
1047 int s;
1048
1049 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
1050
1051 if (usbd_is_dying(sc->sc_udev))
1052 return;
1053
1054 if (status != USBD_NORMAL_COMPLETION) {
1055 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
1056 return;
1057 sc->sc_rx_errs++;
1058 if (usbd_ratecheck(&sc->sc_rx_notice)) {
1059 printf("%s: %u usb errors on rx: %s\n",
1060 sc->sc_dev.dv_xname, sc->sc_rx_errs,
1061 usbd_errstr(status));
1062 sc->sc_rx_errs = 0;
1063 }
1064 if (status == USBD_STALLED) {
1065 sc->sc_refcnt++;
1066 usbd_clear_endpoint_stall_async(sc->sc_pipe_rx);
1067 if (--sc->sc_refcnt < 0)
1068 usb_detach_wakeup(&sc->sc_dev);
1069 }
1070 goto done;
1071 }
1072
1073 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &total_len, NULL((void *)0));
1074
1075 if (total_len < UDAV_RX_HDRLENsizeof(struct udav_rx_hdr)) {
1076 ifp->if_ierrorsif_data.ifi_ierrors++;
1077 goto done;
1078 }
1079
1080 h = (struct udav_rx_hdr *)c->udav_buf;
1081 total_len = UGETW(h->length)(*(u_int16_t *)(h->length)) - ETHER_CRC_LEN4;
1082
1083 DPRINTF(("%s: RX Status: 0x%02x\n", sc->sc_dev.dv_xname, h->pktstat));
1084
1085 if (h->pktstat & UDAV_RSR_LCS(1<<5)) {
1086 ifp->if_collisionsif_data.ifi_collisions++;
1087 goto done;
1088 }
1089
1090 /* RX status may still be correct but total_len is bogus */
1091 if (total_len < sizeof(struct ether_header) ||
1092 h->pktstat & UDAV_RSR_ERR((1<<7) | (1<<5) | (1<<4) | (1<<3) | (
1<<2) | (1<<1) | (1<<0))
||
1093 total_len > UDAV_BUFSZ1522 + sizeof(struct udav_rx_hdr) ) {
1094 ifp->if_ierrorsif_data.ifi_ierrors++;
1095 goto done;
1096 }
1097
1098 /* copy data to mbuf */
1099 m = c->udav_mbuf;
1100 memcpy(mtod(m, char *), c->udav_buf + UDAV_RX_HDRLEN, total_len)__builtin_memcpy((((char *)((m)->m_hdr.mh_data))), (c->
udav_buf + sizeof(struct udav_rx_hdr)), (total_len))
;
1101
1102 m->m_pkthdrM_dat.MH.MH_pkthdr.len = m->m_lenm_hdr.mh_len = total_len;
1103 ml_enqueue(&ml, m);
1104
1105 if (udav_newbuf(sc, c, NULL((void *)0)) == ENOBUFS55) {
1106 ifp->if_ierrorsif_data.ifi_ierrors++;
1107 goto done;
1108 }
1109
1110 s = splnet()splraise(0x7);
1111 if_input(ifp, &ml);
1112 splx(s)spllower(s);
1113
1114 done:
1115 /* Setup new transfer */
1116 usbd_setup_xfer(xfer, sc->sc_pipe_rx, c, c->udav_buf, UDAV_BUFSZ1522 + sizeof(struct udav_rx_hdr),
1117 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01,
1118 USBD_NO_TIMEOUT0, udav_rxeof);
1119 sc->sc_refcnt++;
1120 usbd_transfer(xfer);
1121 if (--sc->sc_refcnt < 0)
1122 usb_detach_wakeup(&sc->sc_dev);
1123
1124 DPRINTF(("%s: %s: start rx\n", sc->sc_dev.dv_xname, __func__));
1125}
1126
1127int
1128udav_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1129{
1130 struct udav_softc *sc = ifp->if_softc;
1131 struct ifreq *ifr = (struct ifreq *)data;
1132 int s, error = 0;
1133
1134 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1135
1136 if (usbd_is_dying(sc->sc_udev))
1137 return ENXIO6;
1138
1139 s = splnet()splraise(0x7);
1140
1141 switch (cmd) {
1142 case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((12)))
:
1143 ifp->if_flags |= IFF_UP0x1;
1144 if (!(ifp->if_flags & IFF_RUNNING0x40))
1145 udav_init(ifp);
1146 break;
1147
1148 case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff
) << 16) | ((('i')) << 8) | ((16)))
:
1149 if (ifp->if_flags & IFF_UP0x1) {
1150 if (ifp->if_flags & IFF_RUNNING0x40)
1151 error = ENETRESET52;
1152 else
1153 udav_init(ifp);
1154 } else {
1155 if (ifp->if_flags & IFF_RUNNING0x40)
1156 udav_stop(ifp, 1);
1157 }
1158 break;
1159
1160 case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifmediareq) & 0x1fff) << 16) | ((('i')) <<
8) | ((56)))
:
1161 case SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof
(struct ifreq) & 0x1fff) << 16) | ((('i')) <<
8) | ((55)))
:
1162 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
1163 break;
1164
1165 default:
1166 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
1167 }
1168
1169 if (error == ENETRESET52) {
1170 if (ifp->if_flags & IFF_RUNNING0x40)
1171 udav_iff(sc);
1172 error = 0;
1173 }
1174
1175 splx(s)spllower(s);
1176 return (error);
1177}
1178
1179void
1180udav_watchdog(struct ifnet *ifp)
1181{
1182 struct udav_softc *sc = ifp->if_softc;
1183 struct udav_chain *c;
1184 usbd_status stat;
1185 int s;
1186
1187 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1188
1189 ifp->if_oerrorsif_data.ifi_oerrors++;
1190 printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
1191
1192 s = splusb()splraise(0x5);
1193 c = &sc->sc_cdata.udav_tx_chain[0];
1194 usbd_get_xfer_status(c->udav_xfer, NULL((void *)0), NULL((void *)0), NULL((void *)0), &stat);
1195 udav_txeof(c->udav_xfer, c, stat);
1196
1197 if (ifq_empty(&ifp->if_snd)(((&ifp->if_snd)->ifq_len) == 0) == 0)
1198 udav_start(ifp);
1199 splx(s)spllower(s);
1200}
1201
1202void
1203udav_stop_task(struct udav_softc *sc)
1204{
1205 udav_stop(GET_IFP(sc)(&(sc)->sc_ac.ac_if), 1);
1206}
1207
1208/* Stop the adapter and free any mbufs allocated to the RX and TX lists. */
1209void
1210udav_stop(struct ifnet *ifp, int disable)
1211{
1212 struct udav_softc *sc = ifp->if_softc;
1213 usbd_status err;
1214 int i;
1215
1216 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1217
1218 ifp->if_timer = 0;
1219 ifp->if_flags &= ~IFF_RUNNING0x40;
1220 ifq_clr_oactive(&ifp->if_snd);
1221
1222 udav_reset(sc);
1223
1224 timeout_del(&sc->sc_stat_ch);
1225
1226 /* Stop transfers */
1227 /* RX endpoint */
1228 if (sc->sc_pipe_rx != NULL((void *)0)) {
1229 err = usbd_close_pipe(sc->sc_pipe_rx);
1230 if (err)
1231 printf("%s: close rx pipe failed: %s\n",
1232 sc->sc_dev.dv_xname, usbd_errstr(err));
1233 sc->sc_pipe_rx = NULL((void *)0);
1234 }
1235
1236 /* TX endpoint */
1237 if (sc->sc_pipe_tx != NULL((void *)0)) {
1238 err = usbd_close_pipe(sc->sc_pipe_tx);
1239 if (err)
1240 printf("%s: close tx pipe failed: %s\n",
1241 sc->sc_dev.dv_xname, usbd_errstr(err));
1242 sc->sc_pipe_tx = NULL((void *)0);
1243 }
1244
1245#if 0
1246 /* XXX: Interrupt endpoint is not yet supported!! */
1247 /* Interrupt endpoint */
1248 if (sc->sc_pipe_intr != NULL((void *)0)) {
1249 err = usbd_close_pipe(sc->sc_pipe_intr);
1250 if (err)
1251 printf("%s: close intr pipe failed: %s\n",
1252 sc->sc_dev.dv_xname, usbd_errstr(err));
1253 sc->sc_pipe_intr = NULL((void *)0);
1254 }
1255#endif
1256
1257 /* Free RX resources. */
1258 for (i = 0; i < UDAV_RX_LIST_CNT1; i++) {
1259 if (sc->sc_cdata.udav_rx_chain[i].udav_mbuf != NULL((void *)0)) {
1260 m_freem(sc->sc_cdata.udav_rx_chain[i].udav_mbuf);
1261 sc->sc_cdata.udav_rx_chain[i].udav_mbuf = NULL((void *)0);
1262 }
1263 if (sc->sc_cdata.udav_rx_chain[i].udav_xfer != NULL((void *)0)) {
1264 usbd_free_xfer(sc->sc_cdata.udav_rx_chain[i].udav_xfer);
1265 sc->sc_cdata.udav_rx_chain[i].udav_xfer = NULL((void *)0);
1266 }
1267 }
1268
1269 /* Free TX resources. */
1270 for (i = 0; i < UDAV_TX_LIST_CNT1; i++) {
1271 if (sc->sc_cdata.udav_tx_chain[i].udav_mbuf != NULL((void *)0)) {
1272 m_freem(sc->sc_cdata.udav_tx_chain[i].udav_mbuf);
1273 sc->sc_cdata.udav_tx_chain[i].udav_mbuf = NULL((void *)0);
1274 }
1275 if (sc->sc_cdata.udav_tx_chain[i].udav_xfer != NULL((void *)0)) {
1276 usbd_free_xfer(sc->sc_cdata.udav_tx_chain[i].udav_xfer);
1277 sc->sc_cdata.udav_tx_chain[i].udav_xfer = NULL((void *)0);
1278 }
1279 }
1280
1281 sc->sc_link = 0;
1282}
1283
1284/* Set media options */
1285int
1286udav_ifmedia_change(struct ifnet *ifp)
1287{
1288 struct udav_softc *sc = ifp->if_softc;
1289 struct mii_data *mii = GET_MII(sc)(&(sc)->sc_mii);
1290
1291 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1292
1293 if (usbd_is_dying(sc->sc_udev))
1294 return (0);
1295
1296 sc->sc_link = 0;
1297
1298 if (sc->sc_flags & UDAV_RD97000x0002)
1299 return (0);
1300
1301 if (mii->mii_instance) {
1302 struct mii_softc *miisc;
1303 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)for((miisc) = ((&mii->mii_phys)->lh_first); (miisc)
!= ((void *)0); (miisc) = ((miisc)->mii_list.le_next))
1304 mii_phy_reset(miisc);
1305 }
1306
1307 return (mii_mediachg(mii));
1308}
1309
1310/* Report current media status. */
1311void
1312udav_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr)
1313{
1314 struct udav_softc *sc = ifp->if_softc;
1315 struct mii_data *mii = GET_MII(sc)(&(sc)->sc_mii);
1316
1317 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1318
1319 if (usbd_is_dying(sc->sc_udev))
1320 return;
1321
1322 if ((ifp->if_flags & IFF_RUNNING0x40) == 0) {
1323 ifmr->ifm_active = IFM_ETHER0x0000000000000100ULL | IFM_NONE2ULL;
1324 ifmr->ifm_status = 0;
1325 return;
1326 }
1327
1328 if (sc->sc_flags & UDAV_RD97000x0002) {
1329 ifmr->ifm_active = IFM_ETHER0x0000000000000100ULL | IFM_10_T3;
1330 ifmr->ifm_status = IFM_AVALID0x0000000000000001ULL;
1331 if (sc->sc_link) ifmr->ifm_status |= IFM_ACTIVE0x0000000000000002ULL;
1332 return;
1333 }
1334
1335 mii_pollstat(mii);
1336 ifmr->ifm_active = mii->mii_media_active;
1337 ifmr->ifm_status = mii->mii_media_status;
1338}
1339
1340void
1341udav_tick(void *xsc)
1342{
1343 struct udav_softc *sc = xsc;
1344
1345 if (sc == NULL((void *)0))
1346 return;
1347
1348 DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
1349 __func__));
1350
1351 /* Perform periodic stuff in process context */
1352 usb_add_task(sc->sc_udev, &sc->sc_tick_task);
1353}
1354
1355void
1356udav_tick_task(void *xsc)
1357{
1358 struct udav_softc *sc = xsc;
1359 struct ifnet *ifp;
1360 struct mii_data *mii;
1361 int s, sts;
1362
1363 if (sc == NULL((void *)0))
1364 return;
1365
1366 DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
1367 __func__));
1368
1369 if (usbd_is_dying(sc->sc_udev))
1370 return;
1371
1372 ifp = GET_IFP(sc)(&(sc)->sc_ac.ac_if);
1373 mii = GET_MII(sc)(&(sc)->sc_mii);
1374
1375 if (mii == NULL((void *)0))
1376 return;
1377
1378 s = splnet()splraise(0x7);
1379
1380 if (sc->sc_flags & UDAV_RD97000x0002) {
1381 sts = udav_csr_read1(sc, UDAV_NSR0x01) & UDAV_NSR_LINKST(1<<6);
1382 if (!sts)
1383 sc->sc_link = 0;
1384 } else {
1385 mii_tick(mii);
1386 sts = (mii->mii_media_status & IFM_ACTIVE0x0000000000000002ULL &&
1387 IFM_SUBTYPE(mii->mii_media_active)((mii->mii_media_active) & 0x00000000000000ffULL) != IFM_NONE2ULL) ? 1 : 0;
1388 }
1389
1390 if (!sc->sc_link && sts) {
1391 DPRINTF(("%s: %s: got link\n",
1392 sc->sc_dev.dv_xname, __func__));
1393 sc->sc_link++;
1394 if (ifq_empty(&ifp->if_snd)(((&ifp->if_snd)->ifq_len) == 0) == 0)
1395 udav_start(ifp);
1396 }
1397
1398 timeout_add_sec(&sc->sc_stat_ch, 1);
1399
1400 splx(s)spllower(s);
1401}
1402
1403/* Get exclusive access to the MII registers */
1404void
1405udav_lock_mii(struct udav_softc *sc)
1406{
1407 DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
1408 __func__));
1409
1410 sc->sc_refcnt++;
1411 rw_enter_write(&sc->sc_mii_lock);
1412}
1413
1414void
1415udav_unlock_mii(struct udav_softc *sc)
1416{
1417 DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
1418 __func__));
1419
1420 rw_exit_write(&sc->sc_mii_lock);
1421 if (--sc->sc_refcnt < 0)
1422 usb_detach_wakeup(&sc->sc_dev);
1423}
1424
1425int
1426udav_miibus_readreg(struct device *dev, int phy, int reg)
1427{
1428 struct udav_softc *sc;
1429 u_int8_t val[2];
1430 u_int16_t data16;
1431
1432 if (dev == NULL((void *)0))
1
Assuming 'dev' is not equal to NULL
2
Taking false branch
1433 return (0);
1434
1435 sc = (void *)dev;
1436
1437 DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n",
1438 sc->sc_dev.dv_xname, __func__, phy, reg));
1439
1440 if (usbd_is_dying(sc->sc_udev)) {
3
Assuming the condition is false
4
Taking false branch
1441#ifdef DIAGNOSTIC1
1442 printf("%s: %s: dying\n", sc->sc_dev.dv_xname,
1443 __func__);
1444#endif
1445 return (0);
1446 }
1447
1448 /* XXX: one PHY only for the internal PHY */
1449 if (phy != 0) {
5
Assuming 'phy' is equal to 0
6
Taking false branch
1450 DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
1451 sc->sc_dev.dv_xname, __func__, phy));
1452 return (0);
1453 }
1454
1455 udav_lock_mii(sc);
1456
1457 /* select internal PHY and set PHY register address */
1458 udav_csr_write1(sc, UDAV_EPAR0x0c,
1459 UDAV_EPAR_PHY_ADR0(1<<6) | (reg & UDAV_EPAR_EROA_MASK(0x1f)));
1460
1461 /* select PHY operation and start read command */
1462 udav_csr_write1(sc, UDAV_EPCR0x0b, UDAV_EPCR_EPOS(1<<3) | UDAV_EPCR_ERPRR(1<<2));
1463
1464 /* XXX: should be wait? */
1465
1466 /* end read command */
1467 UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRR)udav_csr_write1(sc, 0x0b, udav_csr_read1(sc, 0x0b) & ~((1
<<2)))
;
1468
1469 /* retrieve the result from data registers */
1470 udav_csr_read(sc, UDAV_EPDRL0x0d, val, 2);
7
Calling 'udav_csr_read'
11
Returning from 'udav_csr_read'
1471
1472 udav_unlock_mii(sc);
1473
1474 data16 = val[0] | (val[1] << 8);
12
The left operand of '<<' is a garbage value
1475
1476 DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04x\n",
1477 sc->sc_dev.dv_xname, __func__, phy, reg, data16));
1478
1479 return (data16);
1480}
1481
1482void
1483udav_miibus_writereg(struct device *dev, int phy, int reg, int data)
1484{
1485 struct udav_softc *sc;
1486 u_int8_t val[2];
1487
1488 if (dev == NULL((void *)0))
1489 return;
1490
1491 sc = (void *)dev;
1492
1493 DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n",
1494 sc->sc_dev.dv_xname, __func__, phy, reg, data));
1495
1496 if (usbd_is_dying(sc->sc_udev)) {
1497#ifdef DIAGNOSTIC1
1498 printf("%s: %s: dying\n", sc->sc_dev.dv_xname,
1499 __func__);
1500#endif
1501 return;
1502 }
1503
1504 /* XXX: one PHY only for the internal PHY */
1505 if (phy != 0) {
1506 DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
1507 sc->sc_dev.dv_xname, __func__, phy));
1508 return;
1509 }
1510
1511 udav_lock_mii(sc);
1512
1513 /* select internal PHY and set PHY register address */
1514 udav_csr_write1(sc, UDAV_EPAR0x0c,
1515 UDAV_EPAR_PHY_ADR0(1<<6) | (reg & UDAV_EPAR_EROA_MASK(0x1f)));
1516
1517 /* put the value to the data registers */
1518 val[0] = data & 0xff;
1519 val[1] = (data >> 8) & 0xff;
1520 udav_csr_write(sc, UDAV_EPDRL0x0d, val, 2);
1521
1522 /* select PHY operation and start write command */
1523 udav_csr_write1(sc, UDAV_EPCR0x0b, UDAV_EPCR_EPOS(1<<3) | UDAV_EPCR_ERPRW(1<<1));
1524
1525 /* XXX: should be wait? */
1526
1527 /* end write command */
1528 UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRW)udav_csr_write1(sc, 0x0b, udav_csr_read1(sc, 0x0b) & ~((1
<<1)))
;
1529
1530 udav_unlock_mii(sc);
1531
1532 return;
1533}
1534
1535void
1536udav_miibus_statchg(struct device *dev)
1537{
1538#ifdef UDAV_DEBUG
1539 struct udav_softc *sc;
1540
1541 if (dev == NULL((void *)0))
1542 return;
1543
1544 sc = (void *)dev;
1545 DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
1546#endif
1547 /* Nothing to do */
1548}