FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/if_udav.c
1 /* $NetBSD: if_udav.c,v 1.2 2003/09/04 15:17:38 tsutsui Exp $ */
2 /* $nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $ */
3 /* $FreeBSD: src/sys/dev/usb/if_udav.c,v 1.36 2008/04/26 05:46:28 imp Exp $ */
4 /*-
5 * Copyright (c) 2003
6 * Shingo WATANABE <nabe@nabechan.org>. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 */
33
34 /*
35 * DM9601(DAVICOM USB to Ethernet MAC Controller with Integrated 10/100 PHY)
36 * The spec can be found at the following url.
37 * http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf
38 */
39
40 /*
41 * TODO:
42 * Interrupt Endpoint support
43 * External PHYs
44 * powerhook() support?
45 */
46
47 #include <sys/cdefs.h>
48 __FBSDID("$FreeBSD: src/sys/dev/usb/if_udav.c,v 1.36 2008/04/26 05:46:28 imp Exp $");
49
50 #include "opt_inet.h"
51 #if defined(__NetBSD__)
52 #include "opt_ns.h"
53 #endif
54 #if defined(__NetBSD__)
55 #include "bpfilter.h"
56 #endif
57 #if defined(__FreeBSD__)
58 #define NBPFILTER 1
59 #endif
60 #if defined(__NetBSD__)
61 #include "rnd.h"
62 #endif
63
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/lock.h>
67 #include <sys/mbuf.h>
68 #include <sys/kernel.h>
69 #include <sys/module.h>
70 #include <sys/socket.h>
71 #if defined(__FreeBSD__)
72 #include <sys/types.h>
73 #include <sys/lockmgr.h>
74 #include <sys/sockio.h>
75 #endif
76
77 #if defined(__NetBSD__)
78 #include <sys/device.h>
79 #endif
80
81 #if defined(NRND) && NRND > 0
82 #include <sys/rnd.h>
83 #endif
84
85 #include <net/if.h>
86 #include <net/if_arp.h>
87 #include <net/if_dl.h>
88 #include <net/if_media.h>
89 #include <net/ethernet.h>
90 #include <net/if_types.h>
91
92 #if NBPFILTER > 0
93 #include <net/bpf.h>
94 #endif
95 #if defined(__NetBSD__)
96 #ifndef BPF_MTAP
97 #define BPF_MTAP(_ifp, _m) do { \
98 if ((_ifp)->if_bpf)) { \
99 bpf_mtap((_ifp)->if_bpf, (_m)) ; \
100 } \
101 } while (0)
102 #endif
103 #endif
104
105 #if defined(__NetBSD__)
106 #include <net/if_ether.h>
107 #ifdef INET
108 #include <netinet/in.h>
109 #include <netinet/if_inarp.h>
110 #endif /* INET */
111 #elif defined(__FreeBSD__) /* defined(__NetBSD__) */
112 #include <netinet/in.h>
113 #include <netinet/if_ether.h>
114 #endif /* defined(__FreeBSD__) */
115
116 #if defined(__NetBSD__)
117 #ifdef NS
118 #include <netns/ns.h>
119 #include <netns/ns_if.h>
120 #endif
121 #endif /* defined (__NetBSD__) */
122
123 #include <sys/bus.h>
124 #include <machine/bus.h>
125
126 #include <dev/mii/mii.h>
127 #include <dev/mii/miivar.h>
128
129 #include <dev/usb/usb_port.h>
130 #include <dev/usb/usb.h>
131 #include <dev/usb/usbdi.h>
132 #include <dev/usb/usbdi_util.h>
133 #include "usbdevs.h"
134 #include <dev/usb/usbdivar.h>
135 #include <dev/usb/usb_ethersubr.h>
136
137 #include <dev/usb/if_udavreg.h>
138
139 #if defined(__FreeBSD__)
140 MODULE_DEPEND(udav, usb, 1, 1, 1);
141 MODULE_DEPEND(udav, ether, 1, 1, 1);
142 MODULE_DEPEND(udav, miibus, 1, 1, 1);
143 #endif
144
145 /* "device miibus" required. See GENERIC if you get errors here. */
146 #include "miibus_if.h"
147
148 #if !defined(__FreeBSD__)
149 /* Function declarations */
150 USB_DECLARE_DRIVER(udav);
151 #endif
152
153 #if defined(__FreeBSD__)
154 static device_probe_t udav_match;
155 static device_attach_t udav_attach;
156 static device_detach_t udav_detach;
157 static device_shutdown_t udav_shutdown;
158 static miibus_readreg_t udav_miibus_readreg;
159 static miibus_writereg_t udav_miibus_writereg;
160 static miibus_statchg_t udav_miibus_statchg;
161 #endif
162
163 static int udav_openpipes(struct udav_softc *);
164 static void udav_start(struct ifnet *);
165 static int udav_send(struct udav_softc *, struct mbuf *, int);
166 static void udav_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
167 #if defined(__FreeBSD__)
168 static void udav_rxstart(struct ifnet *ifp);
169 #endif
170 static void udav_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
171 static void udav_tick(void *);
172 static void udav_tick_task(void *);
173 static int udav_ioctl(struct ifnet *, u_long, caddr_t);
174 static void udav_stop_task(struct udav_softc *);
175 static void udav_stop(struct ifnet *, int);
176 static void udav_watchdog(struct ifnet *);
177 static int udav_ifmedia_change(struct ifnet *);
178 static void udav_ifmedia_status(struct ifnet *, struct ifmediareq *);
179 static void udav_lock_mii(struct udav_softc *);
180 static void udav_unlock_mii(struct udav_softc *);
181 #if defined(__NetBSD__)
182 static int udav_miibus_readreg(device_t, int, int);
183 static void udav_miibus_writereg(device_t, int, int, int);
184 static void udav_miibus_statchg(device_t);
185 static int udav_init(struct ifnet *);
186 #elif defined(__FreeBSD__)
187 static void udav_init(void *);
188 #endif
189 static void udav_setmulti(struct udav_softc *);
190 static void udav_reset(struct udav_softc *);
191
192 static int udav_csr_read(struct udav_softc *, int, void *, int);
193 static int udav_csr_write(struct udav_softc *, int, void *, int);
194 static int udav_csr_read1(struct udav_softc *, int);
195 static int udav_csr_write1(struct udav_softc *, int, unsigned char);
196
197 #if 0
198 static int udav_mem_read(struct udav_softc *, int, void *, int);
199 static int udav_mem_write(struct udav_softc *, int, void *, int);
200 static int udav_mem_write1(struct udav_softc *, int, unsigned char);
201 #endif
202
203 #if defined(__FreeBSD__)
204 static device_method_t udav_methods[] = {
205 /* Device interface */
206 DEVMETHOD(device_probe, udav_match),
207 DEVMETHOD(device_attach, udav_attach),
208 DEVMETHOD(device_detach, udav_detach),
209 DEVMETHOD(device_shutdown, udav_shutdown),
210
211 /* bus interface */
212 DEVMETHOD(bus_print_child, bus_generic_print_child),
213 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
214
215 /* MII interface */
216 DEVMETHOD(miibus_readreg, udav_miibus_readreg),
217 DEVMETHOD(miibus_writereg, udav_miibus_writereg),
218 DEVMETHOD(miibus_statchg, udav_miibus_statchg),
219
220 { 0, 0 }
221 };
222
223 static driver_t udav_driver = {
224 "udav",
225 udav_methods,
226 sizeof(struct udav_softc)
227 };
228
229 static devclass_t udav_devclass;
230
231 DRIVER_MODULE(udav, uhub, udav_driver, udav_devclass, usbd_driver_load, 0);
232 DRIVER_MODULE(miibus, udav, miibus_driver, miibus_devclass, 0, 0);
233
234 #endif /* defined(__FreeBSD__) */
235
236 /* Macros */
237 #ifdef UDAV_DEBUG
238 #define DPRINTF(x) if (udavdebug) printf x
239 #define DPRINTFN(n,x) if (udavdebug >= (n)) printf x
240 int udavdebug = 0;
241 #else
242 #define DPRINTF(x)
243 #define DPRINTFN(n,x)
244 #endif
245
246 #define delay(d) DELAY(d)
247
248 #define UDAV_SETBIT(sc, reg, x) \
249 udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) | (x))
250
251 #define UDAV_CLRBIT(sc, reg, x) \
252 udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) & ~(x))
253
254 static const struct udav_type {
255 struct usb_devno udav_dev;
256 u_int16_t udav_flags;
257 #define UDAV_EXT_PHY 0x0001
258 } udav_devs [] = {
259 /* Corega USB-TXC */
260 {{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXC }, 0},
261 /* ShanTou ST268 USB NIC */
262 {{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ST268 }, 0},
263 /* ShanTou DM9601 USB NIC */
264 {{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_DM9601}, 0},
265 };
266 #define udav_lookup(v, p) ((const struct udav_type *)usb_lookup(udav_devs, v, p))
267
268
269 /* Probe */
270 static int
271 udav_match(device_t self)
272 {
273 struct usb_attach_arg *uaa = device_get_ivars(self);
274
275 if (uaa->iface != NULL)
276 return (UMATCH_NONE);
277
278 return (udav_lookup(uaa->vendor, uaa->product) != NULL ?
279 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
280 }
281
282 /* Attach */
283 static int
284 udav_attach(device_t self)
285 {
286 USB_ATTACH_START(udav, sc, uaa);
287 usbd_device_handle dev = uaa->device;
288 usbd_interface_handle iface;
289 usbd_status err;
290 usb_interface_descriptor_t *id;
291 usb_endpoint_descriptor_t *ed;
292 const char *devname ;
293 struct ifnet *ifp;
294 #if defined(__NetBSD__)
295 struct mii_data *mii;
296 #endif
297 u_char eaddr[ETHER_ADDR_LEN];
298 int i;
299 #if defined(__NetBSD__)
300 int s;
301 #endif
302
303 sc->sc_dev = self;
304 devname = device_get_nameunit(self);
305 /* Move the device into the configured state. */
306 err = usbd_set_config_no(dev, UDAV_CONFIG_NO, 1);
307 if (err) {
308 printf("%s: setting config no failed\n", devname);
309 goto bad;
310 }
311
312 usb_init_task(&sc->sc_tick_task, udav_tick_task, sc);
313 lockinit(&sc->sc_mii_lock, PZERO, "udavmii", 0, 0);
314 usb_init_task(&sc->sc_stop_task, (void (*)(void *)) udav_stop_task, sc);
315
316 /* get control interface */
317 err = usbd_device2interface_handle(dev, UDAV_IFACE_INDEX, &iface);
318 if (err) {
319 printf("%s: failed to get interface, err=%s\n", devname,
320 usbd_errstr(err));
321 goto bad;
322 }
323
324 sc->sc_udev = dev;
325 sc->sc_ctl_iface = iface;
326 sc->sc_flags = udav_lookup(uaa->vendor, uaa->product)->udav_flags;
327
328 /* get interface descriptor */
329 id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
330
331 /* find endpoints */
332 sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1;
333 for (i = 0; i < id->bNumEndpoints; i++) {
334 ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i);
335 if (ed == NULL) {
336 printf("%s: couldn't get endpoint %d\n", devname, i);
337 goto bad;
338 }
339 if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
340 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
341 sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */
342 else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
343 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
344 sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */
345 else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT &&
346 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
347 sc->sc_intrin_no = ed->bEndpointAddress; /* Status */
348 }
349
350 if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 ||
351 sc->sc_intrin_no == -1) {
352 printf("%s: missing endpoint\n", devname);
353 goto bad;
354 }
355
356 #if defined(__FreeBSD__)
357 mtx_init(&sc->sc_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK,
358 MTX_DEF | MTX_RECURSE);
359 #endif
360 #if defined(__NetBSD__)
361 s = splnet();
362 #elif defined(__FreeBSD__)
363 UDAV_LOCK(sc);
364 #endif
365
366 /* reset the adapter */
367 udav_reset(sc);
368
369 /* Get Ethernet Address */
370 err = udav_csr_read(sc, UDAV_PAR, (void *)eaddr, ETHER_ADDR_LEN);
371 if (err) {
372 printf("%s: read MAC address failed\n", devname);
373 #if defined(__NetBSD__)
374 splx(s);
375 #elif defined(__FreeBSD__)
376 UDAV_UNLOCK(sc);
377 mtx_destroy(&sc->sc_mtx);
378 #endif
379 goto bad;
380 }
381
382 /* Print Ethernet Address */
383 printf("%s: Ethernet address %s\n", devname, ether_sprintf(eaddr));
384
385 /* initialize interface infomation */
386 #if defined(__FreeBSD__)
387 ifp = GET_IFP(sc) = if_alloc(IFT_ETHER);
388 if (ifp == NULL) {
389 printf("%s: can not if_alloc\n", devname);
390 UDAV_UNLOCK(sc);
391 mtx_destroy(&sc->sc_mtx);
392 goto bad;
393 }
394 #else
395 ifp = GET_IFP(sc);
396 #endif
397 ifp->if_softc = sc;
398 ifp->if_mtu = ETHERMTU;
399 #if defined(__NetBSD__)
400 strncpy(ifp->if_xname, devname, IFNAMSIZ);
401 #elif defined(__FreeBSD__)
402 if_initname(ifp, "udav", device_get_unit(self));
403 #endif
404 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
405 IFF_NEEDSGIANT;
406 ifp->if_start = udav_start;
407 ifp->if_ioctl = udav_ioctl;
408 ifp->if_watchdog = udav_watchdog;
409 ifp->if_init = udav_init;
410 #if defined(__NetBSD__)
411 ifp->if_stop = udav_stop;
412 #endif
413 #if defined(__FreeBSD__)
414 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
415 #endif
416 #if defined(__NetBSD__)
417 IFQ_SET_READY(&ifp->if_snd);
418 #endif
419
420
421 #if defined(__NetBSD__)
422 /*
423 * Do ifmedia setup.
424 */
425 mii = &sc->sc_mii;
426 mii->mii_ifp = ifp;
427 mii->mii_readreg = udav_miibus_readreg;
428 mii->mii_writereg = udav_miibus_writereg;
429 mii->mii_statchg = udav_miibus_statchg;
430 mii->mii_flags = MIIF_AUTOTSLEEP;
431 ifmedia_init(&mii->mii_media, 0,
432 udav_ifmedia_change, udav_ifmedia_status);
433 mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
434 if (LIST_FIRST(&mii->mii_phys) == NULL) {
435 ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
436 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
437 } else
438 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
439
440 /* attach the interface */
441 if_attach(ifp);
442 Ether_ifattach(ifp, eaddr);
443 #elif defined(__FreeBSD__)
444 if (mii_phy_probe(self, &sc->sc_miibus,
445 udav_ifmedia_change, udav_ifmedia_status)) {
446 printf("%s: MII without any PHY!\n", device_get_nameunit(sc->sc_dev));
447 if_free(ifp);
448 UDAV_UNLOCK(sc);
449 mtx_destroy(&sc->sc_mtx);
450 return ENXIO;
451 }
452
453 sc->sc_qdat.ifp = ifp;
454 sc->sc_qdat.if_rxstart = udav_rxstart;
455
456 /*
457 * Call MI attach routine.
458 */
459
460 ether_ifattach(ifp, eaddr);
461 #endif
462
463 #if defined(NRND) && NRND > 0
464 rnd_attach_source(&sc->rnd_source, devname, RND_TYPE_NET, 0);
465 #endif
466
467 usb_callout_init(sc->sc_stat_ch);
468 #if defined(__FreeBSD__)
469 usb_register_netisr();
470 #endif
471 sc->sc_attached = 1;
472 #if defined(__NetBSD__)
473 splx(s);
474 #elif defined(__FreeBSD__)
475 UDAV_UNLOCK(sc);
476 #endif
477
478 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, sc->sc_dev);
479
480 return 0;
481
482 bad:
483 sc->sc_dying = 1;
484 return ENXIO;
485 }
486
487 /* detach */
488 static int
489 udav_detach(device_t self)
490 {
491 USB_DETACH_START(udav, sc);
492 struct ifnet *ifp = GET_IFP(sc);
493 #if defined(__NetBSD__)
494 int s;
495 #endif
496
497 DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__));
498
499 /* Detached before attached finished */
500 if (!sc->sc_attached)
501 return (0);
502
503 UDAV_LOCK(sc);
504
505 usb_uncallout(sc->sc_stat_ch, udav_tick, sc);
506
507 /* Remove any pending tasks */
508 usb_rem_task(sc->sc_udev, &sc->sc_tick_task);
509 usb_rem_task(sc->sc_udev, &sc->sc_stop_task);
510
511 #if defined(__NetBSD__)
512 s = splusb();
513 #elif defined(__FreeBSD__)
514 UDAV_LOCK(sc);
515 #endif
516
517 if (--sc->sc_refcnt >= 0) {
518 /* Wait for processes to go away */
519 usb_detach_wait(sc->sc_dev);
520 }
521 #if defined(__FreeBSD__)
522 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
523 #else
524 if (ifp->if_flags & IFF_RUNNING)
525 #endif
526 udav_stop(GET_IFP(sc), 1);
527
528 #if defined(NRND) && NRND > 0
529 rnd_detach_source(&sc->rnd_source);
530 #endif
531 #if defined(__NetBSD__)
532 mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
533 ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
534 #endif
535 ether_ifdetach(ifp);
536 #if defined(__NetBSD__)
537 if_detach(ifp);
538 #endif
539 #if defined(__FreeBSD__)
540 if_free(ifp);
541 #endif
542
543 #ifdef DIAGNOSTIC
544 if (sc->sc_pipe_tx != NULL)
545 printf("%s: detach has active tx endpoint.\n",
546 device_get_nameunit(sc->sc_dev));
547 if (sc->sc_pipe_rx != NULL)
548 printf("%s: detach has active rx endpoint.\n",
549 device_get_nameunit(sc->sc_dev));
550 if (sc->sc_pipe_intr != NULL)
551 printf("%s: detach has active intr endpoint.\n",
552 device_get_nameunit(sc->sc_dev));
553 #endif
554 sc->sc_attached = 0;
555
556 #if defined(__NetBSD__)
557 splx(s);
558 #elif defined(__FreeBSD__)
559 UDAV_UNLOCK(sc);
560 #endif
561
562 #if defined(__FreeBSD__)
563 mtx_destroy(&sc->sc_mtx);
564 #endif
565
566 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
567 return (0);
568 }
569
570 #if 0
571 /* read memory */
572 static int
573 udav_mem_read(struct udav_softc *sc, int offset, void *buf, int len)
574 {
575 usb_device_request_t req;
576 usbd_status err;
577
578 if (sc == NULL)
579 return (0);
580
581 DPRINTFN(0x200,
582 ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__));
583
584 if (sc->sc_dying)
585 return (0);
586
587 offset &= 0xffff;
588 len &= 0xff;
589
590 req.bmRequestType = UT_READ_VENDOR_DEVICE;
591 req.bRequest = UDAV_REQ_MEM_READ;
592 USETW(req.wValue, 0x0000);
593 USETW(req.wIndex, offset);
594 USETW(req.wLength, len);
595
596 sc->sc_refcnt++;
597 err = usbd_do_request(sc->sc_udev, &req, buf);
598 if (--sc->sc_refcnt < 0)
599 usb_detach_wakeup(sc->sc_dev);
600 if (err) {
601 DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
602 device_get_nameunit(sc->sc_dev), __func__, offset, err));
603 }
604
605 return (err);
606 }
607
608 /* write memory */
609 static int
610 udav_mem_write(struct udav_softc *sc, int offset, void *buf, int len)
611 {
612 usb_device_request_t req;
613 usbd_status err;
614
615 if (sc == NULL)
616 return (0);
617
618 DPRINTFN(0x200,
619 ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__));
620
621 if (sc->sc_dying)
622 return (0);
623
624 offset &= 0xffff;
625 len &= 0xff;
626
627 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
628 req.bRequest = UDAV_REQ_MEM_WRITE;
629 USETW(req.wValue, 0x0000);
630 USETW(req.wIndex, offset);
631 USETW(req.wLength, len);
632
633 sc->sc_refcnt++;
634 err = usbd_do_request(sc->sc_udev, &req, buf);
635 if (--sc->sc_refcnt < 0)
636 usb_detach_wakeup(sc->sc_dev);
637 if (err) {
638 DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
639 device_get_nameunit(sc->sc_dev), __func__, offset, err));
640 }
641
642 return (err);
643 }
644
645 /* write memory */
646 static int
647 udav_mem_write1(struct udav_softc *sc, int offset, unsigned char ch)
648 {
649 usb_device_request_t req;
650 usbd_status err;
651
652 if (sc == NULL)
653 return (0);
654
655 DPRINTFN(0x200,
656 ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__));
657
658 if (sc->sc_dying)
659 return (0);
660
661 offset &= 0xffff;
662
663 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
664 req.bRequest = UDAV_REQ_MEM_WRITE1;
665 USETW(req.wValue, ch);
666 USETW(req.wIndex, offset);
667 USETW(req.wLength, 0x0000);
668
669 sc->sc_refcnt++;
670 err = usbd_do_request(sc->sc_udev, &req, NULL);
671 if (--sc->sc_refcnt < 0)
672 usb_detach_wakeup(sc->sc_dev);
673 if (err) {
674 DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
675 device_get_nameunit(sc->sc_dev), __func__, offset, err));
676 }
677
678 return (err);
679 }
680 #endif
681
682 /* read register(s) */
683 static int
684 udav_csr_read(struct udav_softc *sc, int offset, void *buf, int len)
685 {
686 usb_device_request_t req;
687 usbd_status err;
688
689 if (sc == NULL)
690 return (0);
691
692 DPRINTFN(0x200,
693 ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__));
694
695 if (sc->sc_dying)
696 return (0);
697
698 offset &= 0xff;
699 len &= 0xff;
700
701 req.bmRequestType = UT_READ_VENDOR_DEVICE;
702 req.bRequest = UDAV_REQ_REG_READ;
703 USETW(req.wValue, 0x0000);
704 USETW(req.wIndex, offset);
705 USETW(req.wLength, len);
706
707 sc->sc_refcnt++;
708 err = usbd_do_request(sc->sc_udev, &req, buf);
709 if (--sc->sc_refcnt < 0)
710 usb_detach_wakeup(sc->sc_dev);
711 if (err) {
712 DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
713 device_get_nameunit(sc->sc_dev), __func__, offset, err));
714 }
715
716 return (err);
717 }
718
719 /* write register(s) */
720 static int
721 udav_csr_write(struct udav_softc *sc, int offset, void *buf, int len)
722 {
723 usb_device_request_t req;
724 usbd_status err;
725
726 if (sc == NULL)
727 return (0);
728
729 DPRINTFN(0x200,
730 ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__));
731
732 if (sc->sc_dying)
733 return (0);
734
735 offset &= 0xff;
736 len &= 0xff;
737
738 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
739 req.bRequest = UDAV_REQ_REG_WRITE;
740 USETW(req.wValue, 0x0000);
741 USETW(req.wIndex, offset);
742 USETW(req.wLength, len);
743
744 sc->sc_refcnt++;
745 err = usbd_do_request(sc->sc_udev, &req, buf);
746 if (--sc->sc_refcnt < 0)
747 usb_detach_wakeup(sc->sc_dev);
748 if (err) {
749 DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
750 device_get_nameunit(sc->sc_dev), __func__, offset, err));
751 }
752
753 return (err);
754 }
755
756 static int
757 udav_csr_read1(struct udav_softc *sc, int offset)
758 {
759 u_int8_t val = 0;
760
761 if (sc == NULL)
762 return (0);
763
764 DPRINTFN(0x200,
765 ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__));
766
767 if (sc->sc_dying)
768 return (0);
769
770 return (udav_csr_read(sc, offset, &val, 1) ? 0 : val);
771 }
772
773 /* write a register */
774 static int
775 udav_csr_write1(struct udav_softc *sc, int offset, unsigned char ch)
776 {
777 usb_device_request_t req;
778 usbd_status err;
779
780 if (sc == NULL)
781 return (0);
782
783 DPRINTFN(0x200,
784 ("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__));
785
786 if (sc->sc_dying)
787 return (0);
788
789 offset &= 0xff;
790
791 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
792 req.bRequest = UDAV_REQ_REG_WRITE1;
793 USETW(req.wValue, ch);
794 USETW(req.wIndex, offset);
795 USETW(req.wLength, 0x0000);
796
797 sc->sc_refcnt++;
798 err = usbd_do_request(sc->sc_udev, &req, NULL);
799 if (--sc->sc_refcnt < 0)
800 usb_detach_wakeup(sc->sc_dev);
801 if (err) {
802 DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
803 device_get_nameunit(sc->sc_dev), __func__, offset, err));
804 }
805
806 return (err);
807 }
808
809 #if defined(__NetBSD__)
810 static int
811 udav_init(struct ifnet *ifp)
812 #elif defined(__FreeBSD__)
813 static void
814 udav_init(void *xsc)
815 #endif
816 {
817 #if defined(__NetBSD__)
818 struct udav_softc *sc = ifp->if_softc;
819 #elif defined(__FreeBSD__)
820 struct udav_softc *sc = (struct udav_softc *)xsc;
821 struct ifnet *ifp = GET_IFP(sc);
822 #endif
823 struct mii_data *mii = GET_MII(sc);
824 u_char *eaddr;
825 #if defined(__NetBSD__)
826 int s;
827 #endif
828
829 DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__));
830
831 if (sc->sc_dying)
832 #if defined(__NetBSD__)
833 return (EIO);
834 #elif defined(__FreeBSD__)
835 return ;
836 #endif
837
838 #if defined(__NetBSD__)
839 s = splnet();
840 #elif defined(__FreeBSD__)
841 UDAV_LOCK(sc);
842 #endif
843
844 /* Cancel pending I/O and free all TX/RX buffers */
845 udav_stop(ifp, 1);
846
847 #if defined(__NetBSD__)
848 eaddr = LLADDR(ifp->if_sadl);
849 #elif defined(__FreeBSD__)
850 eaddr = IF_LLADDR(ifp);
851 #endif
852 udav_csr_write(sc, UDAV_PAR, eaddr, ETHER_ADDR_LEN);
853
854 /* Initialize network control register */
855 /* Disable loopback */
856 UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_LBK0 | UDAV_NCR_LBK1);
857
858 /* Initialize RX control register */
859 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_DIS_LONG | UDAV_RCR_DIS_CRC);
860
861 /* If we want promiscuous mode, accept all physical frames. */
862 if (ifp->if_flags & IFF_PROMISC)
863 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
864 else
865 UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
866
867 /* Initialize transmit ring */
868 if (usb_ether_tx_list_init(sc, &sc->sc_cdata,
869 sc->sc_udev) == ENOBUFS) {
870 printf("%s: tx list init failed\n", device_get_nameunit(sc->sc_dev));
871 #if defined(__NetBSD__)
872 splx(s);
873 return (EIO);
874 #elif defined(__FreeBSD__)
875 UDAV_UNLOCK(sc);
876 return ;
877 #endif
878
879 }
880
881 /* Initialize receive ring */
882 if (usb_ether_rx_list_init(sc, &sc->sc_cdata,
883 sc->sc_udev) == ENOBUFS) {
884 printf("%s: rx list init failed\n", device_get_nameunit(sc->sc_dev));
885 #if defined(__NetBSD__)
886 splx(s);
887 return (EIO);
888 #elif defined(__FreeBSD__)
889 UDAV_UNLOCK(sc);
890 return ;
891 #endif
892 }
893
894 /* Load the multicast filter */
895 udav_setmulti(sc);
896
897 /* Enable RX */
898 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_RXEN);
899
900 /* clear POWER_DOWN state of internal PHY */
901 UDAV_SETBIT(sc, UDAV_GPCR, UDAV_GPCR_GEP_CNTL0);
902 UDAV_CLRBIT(sc, UDAV_GPR, UDAV_GPR_GEPIO0);
903
904 mii_mediachg(mii);
905
906 if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) {
907 if (udav_openpipes(sc)) {
908 #if defined(__NetBSD__)
909 splx(s);
910 return (EIO);
911 #elif defined(__FreeBSD__)
912 UDAV_UNLOCK(sc);
913 return ;
914 #endif
915 }
916 }
917
918 #if defined(__FreeBSD__)
919 ifp->if_drv_flags |= IFF_DRV_RUNNING;
920 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
921 #else
922 ifp->if_flags |= IFF_RUNNING;
923 ifp->if_flags &= ~IFF_OACTIVE;
924 #endif
925
926 #if defined(__NetBSD__)
927 splx(s);
928 #elif defined(__FreeBSD__)
929 UDAV_UNLOCK(sc);
930 #endif
931
932 usb_callout(sc->sc_stat_ch, hz, udav_tick, sc);
933
934 #if defined(__NetBSD__)
935 return (0);
936 #elif defined(__FreeBSD__)
937 return ;
938 #endif
939 }
940
941 static void
942 udav_reset(struct udav_softc *sc)
943 {
944 int i;
945
946 DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__));
947
948 if (sc->sc_dying)
949 return;
950
951 /* Select PHY */
952 #if 1
953 /*
954 * XXX: force select internal phy.
955 * external phy routines are not tested.
956 */
957 UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
958 #else
959 if (sc->sc_flags & UDAV_EXT_PHY) {
960 UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
961 } else {
962 UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
963 }
964 #endif
965
966 UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_RST);
967
968 for (i = 0; i < UDAV_TX_TIMEOUT; i++) {
969 if (!(udav_csr_read1(sc, UDAV_NCR) & UDAV_NCR_RST))
970 break;
971 delay(10); /* XXX */
972 }
973 delay(10000); /* XXX */
974 }
975
976 #if defined(__NetBSD__) || defined(__OpenBSD__)
977 int
978 udav_activate(device_t self, enum devact act)
979 {
980 struct udav_softc *sc = (struct udav_softc *)self;
981
982 DPRINTF(("%s: %s: enter, act=%d\n", device_get_nameunit(sc->sc_dev),
983 __func__, act));
984 switch (act) {
985 case DVACT_ACTIVATE:
986 return (EOPNOTSUPP);
987 break;
988
989 case DVACT_DEACTIVATE:
990 if_deactivate(&sc->sc_ec.ec_if);
991 sc->sc_dying = 1;
992 break;
993 }
994 return (0);
995 }
996 #endif
997
998 #define UDAV_BITS 6
999
1000 #define UDAV_CALCHASH(addr) \
1001 (ether_crc32_le((addr), ETHER_ADDR_LEN) & ((1 << UDAV_BITS) - 1))
1002
1003 static void
1004 udav_setmulti(struct udav_softc *sc)
1005 {
1006 struct ifnet *ifp;
1007 #if defined(__NetBSD__)
1008 struct ether_multi *enm;
1009 struct ether_multistep step;
1010 #elif defined(__FreeBSD__)
1011 struct ifmultiaddr *ifma;
1012 #endif
1013 u_int8_t hashes[8];
1014 int h = 0;
1015
1016 DPRINTF(("%s: %s: enter\n", device_get_nameunit(sc->sc_dev), __func__));
1017
1018 if (sc->sc_dying)
1019 return;
1020
1021 ifp = GET_IFP(sc);
1022
1023 if (ifp->if_flags & IFF_PROMISC) {
1024 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
1025 return;
1026 } else if (ifp->if_flags & IFF_ALLMULTI) {
1027 #if defined(__NetBSD__)
1028 allmulti:
1029 #endif
1030 ifp->if_flags |= IFF_ALLMULTI;
1031 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
1032 UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_PRMSC);
1033 return;
1034 }
1035
|