[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/if_udav.c

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD70  -  FREEBSD6  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  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