LCOV - code coverage report
Current view: top level - dev/usb - if_udav.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 646 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 31 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: if_udav.c,v 1.80 2018/07/03 14:33:43 kevlo 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 NBPFILTER > 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             : 
      78             : int udav_match(struct device *, void *, void *);
      79             : void udav_attach(struct device *, struct device *, void *);
      80             : int udav_detach(struct device *, int);
      81             : 
      82             : struct cfdriver udav_cd = {
      83             :         NULL, "udav", DV_IFNET
      84             : };
      85             : 
      86             : const struct cfattach udav_ca = {
      87             :         sizeof(struct udav_softc), udav_match, udav_attach, udav_detach
      88             : };
      89             : 
      90             : int udav_openpipes(struct udav_softc *);
      91             : int udav_rx_list_init(struct udav_softc *);
      92             : int udav_tx_list_init(struct udav_softc *);
      93             : int udav_newbuf(struct udav_softc *, struct udav_chain *, struct mbuf *);
      94             : void udav_start(struct ifnet *);
      95             : int udav_send(struct udav_softc *, struct mbuf *, int);
      96             : void udav_txeof(struct usbd_xfer *, void *, usbd_status);
      97             : void udav_rxeof(struct usbd_xfer *, void *, usbd_status);
      98             : void udav_tick(void *);
      99             : void udav_tick_task(void *);
     100             : int udav_ioctl(struct ifnet *, u_long, caddr_t);
     101             : void udav_stop_task(struct udav_softc *);
     102             : void udav_stop(struct ifnet *, int);
     103             : void udav_watchdog(struct ifnet *);
     104             : int udav_ifmedia_change(struct ifnet *);
     105             : void udav_ifmedia_status(struct ifnet *, struct ifmediareq *);
     106             : void udav_lock_mii(struct udav_softc *);
     107             : void udav_unlock_mii(struct udav_softc *);
     108             : int udav_miibus_readreg(struct device *, int, int);
     109             : void udav_miibus_writereg(struct device *, int, int, int);
     110             : void udav_miibus_statchg(struct device *);
     111             : int udav_init(struct ifnet *);
     112             : void udav_iff(struct udav_softc *);
     113             : void udav_reset(struct udav_softc *);
     114             : 
     115             : int udav_csr_read(struct udav_softc *, int, void *, int);
     116             : int udav_csr_write(struct udav_softc *, int, void *, int);
     117             : int udav_csr_read1(struct udav_softc *, int);
     118             : int udav_csr_write1(struct udav_softc *, int, unsigned char);
     119             : 
     120             : #if 0
     121             : int udav_mem_read(struct udav_softc *, int, void *, int);
     122             : int udav_mem_write(struct udav_softc *, int, void *, int);
     123             : int 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)
     130             : int udavdebug = 0;
     131             : #else
     132             : #define DPRINTF(x)
     133             : #define DPRINTFN(n,x)
     134             : #endif
     135             : 
     136             : #define UDAV_SETBIT(sc, reg, x) \
     137             :         udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) | (x))
     138             : 
     139             : #define UDAV_CLRBIT(sc, reg, x) \
     140             :         udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) & ~(x))
     141             : 
     142             : static const struct udav_type {
     143             :         struct usb_devno udav_dev;
     144             :         u_int16_t udav_flags;
     145             : #define UDAV_EXT_PHY    0x0001
     146             : #define UDAV_RD9700     0x0002
     147             : } udav_devs [] = {
     148             :         {{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXC }, 0 },
     149             :         {{ USB_VENDOR_DAVICOM, USB_PRODUCT_DAVICOM_DM9601 }, 0 },
     150             :         {{ USB_VENDOR_DAVICOM, USB_PRODUCT_DAVICOM_WK668 }, 0 },
     151             :         {{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_DM9601 }, 0 },
     152             :         {{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ST268 }, 0 },
     153             :         {{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ZT6688 }, 0 },
     154             :         {{ USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ADM8515 }, 0 },
     155             :         {{ USB_VENDOR_UNKNOWN4, USB_PRODUCT_UNKNOWN4_DM9601 }, 0 },
     156             :         {{ USB_VENDOR_UNKNOWN6, USB_PRODUCT_UNKNOWN6_DM9601 }, 0 },
     157             :         {{ USB_VENDOR_UNKNOWN4, USB_PRODUCT_UNKNOWN4_RD9700 }, UDAV_RD9700 },
     158             : };
     159             : #define udav_lookup(v, p) ((struct udav_type *)usb_lookup(udav_devs, v, p))
     160             : 
     161             : 
     162             : /* Probe */
     163             : int
     164           0 : udav_match(struct device *parent, void *match, void *aux)
     165             : {
     166           0 :         struct usb_attach_arg *uaa = aux;
     167             : 
     168           0 :         if (uaa->iface == NULL || uaa->configno != 1)
     169           0 :                 return (UMATCH_NONE);
     170             : 
     171           0 :         return (udav_lookup(uaa->vendor, uaa->product) != NULL ?
     172             :                 UMATCH_VENDOR_PRODUCT_CONF_IFACE : UMATCH_NONE);
     173           0 : }
     174             : 
     175             : /* Attach */
     176             : void
     177           0 : udav_attach(struct device *parent, struct device *self, void *aux)
     178             : {
     179           0 :         struct udav_softc *sc = (struct udav_softc *)self;
     180           0 :         struct usb_attach_arg *uaa = aux;
     181           0 :         struct usbd_device *dev = uaa->device;
     182           0 :         struct usbd_interface *iface = uaa->iface;
     183             :         usbd_status err;
     184             :         usb_interface_descriptor_t *id;
     185             :         usb_endpoint_descriptor_t *ed;
     186           0 :         char *devname = sc->sc_dev.dv_xname;
     187             :         struct ifnet *ifp;
     188             :         struct mii_data *mii;
     189           0 :         u_char eaddr[ETHER_ADDR_LEN];
     190             :         int i, s;
     191             : 
     192           0 :         printf("%s: ", devname);
     193             : 
     194           0 :         sc->sc_udev = dev;
     195             : 
     196           0 :         usb_init_task(&sc->sc_tick_task, udav_tick_task, sc,
     197             :             USB_TASK_TYPE_GENERIC);
     198           0 :         rw_init(&sc->sc_mii_lock, "udavmii");
     199           0 :         usb_init_task(&sc->sc_stop_task, (void (*)(void *)) udav_stop_task, sc,
     200             :             USB_TASK_TYPE_GENERIC);
     201             : 
     202           0 :         sc->sc_ctl_iface = iface;
     203           0 :         sc->sc_flags = udav_lookup(uaa->vendor, uaa->product)->udav_flags;
     204             : 
     205             :         /* get interface descriptor */
     206           0 :         id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
     207             : 
     208             :         /* find endpoints */
     209           0 :         sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1;
     210           0 :         for (i = 0; i < id->bNumEndpoints; i++) {
     211           0 :                 ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i);
     212           0 :                 if (ed == NULL) {
     213           0 :                         printf("couldn't get endpoint %d\n", i);
     214           0 :                         goto bad;
     215             :                 }
     216           0 :                 if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
     217           0 :                     UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
     218           0 :                         sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */
     219           0 :                 else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
     220           0 :                          UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
     221           0 :                         sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */
     222           0 :                 else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT &&
     223           0 :                          UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
     224           0 :                         sc->sc_intrin_no = ed->bEndpointAddress; /* Status */
     225             :         }
     226             : 
     227           0 :         if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 ||
     228           0 :             sc->sc_intrin_no == -1) {
     229           0 :                 printf("missing endpoint\n");
     230           0 :                 goto bad;
     231             :         }
     232             : 
     233           0 :         s = splnet();
     234             : 
     235             :         /* reset the adapter */
     236           0 :         udav_reset(sc);
     237             : 
     238             :         /* Get Ethernet Address */
     239           0 :         err = udav_csr_read(sc, UDAV_PAR, (void *)eaddr, ETHER_ADDR_LEN);
     240           0 :         if (err) {
     241           0 :                 printf("read MAC address failed\n");
     242           0 :                 splx(s);
     243           0 :                 goto bad;
     244             :         }
     245             : 
     246             :         /* Print Ethernet Address */
     247           0 :         printf("address %s\n", ether_sprintf(eaddr));
     248             : 
     249           0 :         bcopy(eaddr, (char *)&sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
     250             : 
     251             :         /* initialize interface information */
     252           0 :         ifp = GET_IFP(sc);
     253           0 :         ifp->if_softc = sc;
     254           0 :         strlcpy(ifp->if_xname, devname, IFNAMSIZ);
     255           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     256           0 :         ifp->if_start = udav_start;
     257           0 :         ifp->if_ioctl = udav_ioctl;
     258           0 :         ifp->if_watchdog = udav_watchdog;
     259             : 
     260             :         /*
     261             :          * Do ifmedia setup.
     262             :          */
     263           0 :         mii = &sc->sc_mii;
     264           0 :         mii->mii_ifp = ifp;
     265           0 :         mii->mii_readreg = udav_miibus_readreg;
     266           0 :         mii->mii_writereg = udav_miibus_writereg;
     267           0 :         mii->mii_statchg = udav_miibus_statchg;
     268           0 :         mii->mii_flags = MIIF_AUTOTSLEEP;
     269           0 :         ifmedia_init(&mii->mii_media, 0,
     270             :                      udav_ifmedia_change, udav_ifmedia_status);
     271           0 :         if (sc->sc_flags & UDAV_RD9700) {
     272             :                 /* no MII-PHY */
     273           0 :                 ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
     274           0 :                 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
     275           0 :         } else {
     276           0 :                 mii_attach(self, mii, 0xffffffff, 
     277             :                            MII_PHY_ANY, MII_OFFSET_ANY, 0);
     278           0 :                 if (LIST_FIRST(&mii->mii_phys) == NULL) {
     279           0 :                         ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE,
     280             :                                     0, NULL);
     281           0 :                         ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
     282           0 :                 } else
     283           0 :                         ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
     284             :         }
     285             : 
     286             :         /* attach the interface */
     287           0 :         if_attach(ifp);
     288           0 :         ether_ifattach(ifp);
     289             : 
     290           0 :         timeout_set(&sc->sc_stat_ch, udav_tick, sc);
     291             : 
     292           0 :         splx(s);
     293             : 
     294           0 :         return;
     295             : 
     296             :  bad:
     297           0 :         usbd_deactivate(sc->sc_udev);
     298           0 : }
     299             : 
     300             : /* detach */
     301             : int
     302           0 : udav_detach(struct device *self, int flags)
     303             : {
     304           0 :         struct udav_softc *sc = (struct udav_softc *)self;
     305           0 :         struct ifnet *ifp = GET_IFP(sc);
     306             :         int s;
     307             : 
     308             :         DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
     309             : 
     310             : 
     311           0 :         if (timeout_initialized(&sc->sc_stat_ch))
     312           0 :                 timeout_del(&sc->sc_stat_ch);
     313             : 
     314             :         /* Remove any pending tasks */
     315           0 :         usb_rem_task(sc->sc_udev, &sc->sc_tick_task);
     316           0 :         usb_rem_task(sc->sc_udev, &sc->sc_stop_task);
     317             : 
     318           0 :         s = splusb();
     319             : 
     320           0 :         if (--sc->sc_refcnt >= 0) {
     321             :                 /* Wait for processes to go away */
     322           0 :                 usb_detach_wait(&sc->sc_dev);
     323           0 :         }
     324           0 :         if (ifp->if_flags & IFF_RUNNING)
     325           0 :                 udav_stop(GET_IFP(sc), 1);
     326             : 
     327           0 :         if (!(sc->sc_flags & UDAV_RD9700))
     328           0 :                 mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
     329           0 :         ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
     330           0 :         if (ifp->if_softc != NULL) {
     331           0 :                 ether_ifdetach(ifp);
     332           0 :                 if_detach(ifp);
     333           0 :         }
     334             : 
     335             : #ifdef DIAGNOSTIC
     336           0 :         if (sc->sc_pipe_tx != NULL)
     337           0 :                 printf("%s: detach has active tx endpoint.\n",
     338           0 :                        sc->sc_dev.dv_xname);
     339           0 :         if (sc->sc_pipe_rx != NULL)
     340           0 :                 printf("%s: detach has active rx endpoint.\n",
     341           0 :                        sc->sc_dev.dv_xname);
     342           0 :         if (sc->sc_pipe_intr != NULL)
     343           0 :                 printf("%s: detach has active intr endpoint.\n",
     344           0 :                        sc->sc_dev.dv_xname);
     345             : #endif
     346           0 :         splx(s);
     347             : 
     348           0 :         return (0);
     349             : }
     350             : 
     351             : #if 0
     352             : /* read memory */
     353             : int
     354             : udav_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)
     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;
     372             :         req.bRequest = UDAV_REQ_MEM_READ;
     373             :         USETW(req.wValue, 0x0000);
     374             :         USETW(req.wIndex, offset);
     375             :         USETW(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 */
     390             : int
     391             : udav_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)
     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;
     409             :         req.bRequest = UDAV_REQ_MEM_WRITE;
     410             :         USETW(req.wValue, 0x0000);
     411             :         USETW(req.wIndex, offset);
     412             :         USETW(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 */
     427             : int
     428             : udav_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)
     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;
     445             :         req.bRequest = UDAV_REQ_MEM_WRITE1;
     446             :         USETW(req.wValue, ch);
     447             :         USETW(req.wIndex, offset);
     448             :         USETW(req.wLength, 0x0000);
     449             : 
     450             :         sc->sc_refcnt++;
     451             :         err = usbd_do_request(sc->sc_udev, &req, NULL);
     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) */
     464             : int
     465           0 : udav_csr_read(struct udav_softc *sc, int offset, void *buf, int len)
     466             : {
     467           0 :         usb_device_request_t req;
     468             :         usbd_status err;
     469             : 
     470           0 :         if (sc == NULL)
     471           0 :                 return (0);
     472             : 
     473             :         DPRINTFN(0x200,
     474             :                 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
     475             : 
     476           0 :         if (usbd_is_dying(sc->sc_udev))
     477           0 :                 return (0);
     478             : 
     479           0 :         offset &= 0xff;
     480           0 :         len &= 0xff;
     481             : 
     482           0 :         req.bmRequestType = UT_READ_VENDOR_DEVICE;
     483           0 :         req.bRequest = UDAV_REQ_REG_READ;
     484           0 :         USETW(req.wValue, 0x0000);
     485           0 :         USETW(req.wIndex, offset);
     486           0 :         USETW(req.wLength, len);
     487             : 
     488           0 :         sc->sc_refcnt++;
     489           0 :         err = usbd_do_request(sc->sc_udev, &req, buf);
     490           0 :         if (--sc->sc_refcnt < 0)
     491           0 :                 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           0 :         return (err);
     498           0 : }
     499             : 
     500             : /* write register(s) */
     501             : int
     502           0 : udav_csr_write(struct udav_softc *sc, int offset, void *buf, int len)
     503             : {
     504           0 :         usb_device_request_t req;
     505             :         usbd_status err;
     506             : 
     507           0 :         if (sc == NULL)
     508           0 :                 return (0);
     509             : 
     510             :         DPRINTFN(0x200,
     511             :                 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
     512             : 
     513           0 :         if (usbd_is_dying(sc->sc_udev))
     514           0 :                 return (0);
     515             : 
     516           0 :         offset &= 0xff;
     517           0 :         len &= 0xff;
     518             : 
     519           0 :         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
     520           0 :         req.bRequest = UDAV_REQ_REG_WRITE;
     521           0 :         USETW(req.wValue, 0x0000);
     522           0 :         USETW(req.wIndex, offset);
     523           0 :         USETW(req.wLength, len);
     524             : 
     525           0 :         sc->sc_refcnt++;
     526           0 :         err = usbd_do_request(sc->sc_udev, &req, buf);
     527           0 :         if (--sc->sc_refcnt < 0)
     528           0 :                 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           0 :         return (err);
     535           0 : }
     536             : 
     537             : int
     538           0 : udav_csr_read1(struct udav_softc *sc, int offset)
     539             : {
     540           0 :         u_int8_t val = 0;
     541             :         
     542           0 :         if (sc == NULL)
     543           0 :                 return (0);
     544             : 
     545             :         DPRINTFN(0x200,
     546             :                 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
     547             : 
     548           0 :         return (udav_csr_read(sc, offset, &val, 1) ? 0 : val);
     549           0 : }
     550             : 
     551             : /* write a register */
     552             : int
     553           0 : udav_csr_write1(struct udav_softc *sc, int offset, unsigned char ch)
     554             : {
     555           0 :         usb_device_request_t req;
     556             :         usbd_status err;
     557             : 
     558           0 :         if (sc == NULL)
     559           0 :                 return (0);
     560             : 
     561             :         DPRINTFN(0x200,
     562             :                 ("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
     563             : 
     564           0 :         if (usbd_is_dying(sc->sc_udev))
     565           0 :                 return (0);
     566             : 
     567           0 :         offset &= 0xff;
     568             : 
     569           0 :         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
     570           0 :         req.bRequest = UDAV_REQ_REG_WRITE1;
     571           0 :         USETW(req.wValue, ch);
     572           0 :         USETW(req.wIndex, offset);
     573           0 :         USETW(req.wLength, 0x0000);
     574             : 
     575           0 :         sc->sc_refcnt++;
     576           0 :         err = usbd_do_request(sc->sc_udev, &req, NULL);
     577           0 :         if (--sc->sc_refcnt < 0)
     578           0 :                 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           0 :         return (err);
     585           0 : }
     586             : 
     587             : int
     588           0 : udav_init(struct ifnet *ifp)
     589             : {
     590           0 :         struct udav_softc *sc = ifp->if_softc;
     591           0 :         struct mii_data *mii = GET_MII(sc);
     592             :         u_char *eaddr;
     593             :         int s;
     594             : 
     595             :         DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
     596             : 
     597           0 :         s = splnet();
     598             : 
     599             :         /* Cancel pending I/O and free all TX/RX buffers */
     600           0 :         udav_stop(ifp, 1);
     601             : 
     602           0 :         eaddr = sc->sc_ac.ac_enaddr;
     603           0 :         udav_csr_write(sc, UDAV_PAR, eaddr, ETHER_ADDR_LEN);
     604             : 
     605             :         /* Initialize network control register */
     606             :         /*  Disable loopback  */
     607           0 :         UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_LBK0 | UDAV_NCR_LBK1);
     608             : 
     609             :         /* Initialize RX control register */
     610           0 :         UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_DIS_LONG | UDAV_RCR_DIS_CRC);
     611             : 
     612             :         /* Initialize transmit ring */
     613           0 :         if (udav_tx_list_init(sc) == ENOBUFS) {
     614           0 :                 printf("%s: tx list init failed\n", sc->sc_dev.dv_xname);
     615           0 :                 splx(s);
     616           0 :                 return (EIO);
     617             :         }
     618             : 
     619             :         /* Initialize receive ring */
     620           0 :         if (udav_rx_list_init(sc) == ENOBUFS) {
     621           0 :                 printf("%s: rx list init failed\n", sc->sc_dev.dv_xname);
     622           0 :                 splx(s);
     623           0 :                 return (EIO);
     624             :         }
     625             : 
     626             :         /* Program promiscuous mode and multicast filters */
     627           0 :         udav_iff(sc);
     628             : 
     629             :         /* Enable RX */
     630           0 :         UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_RXEN);
     631             : 
     632             :         /* clear POWER_DOWN state of internal PHY */
     633           0 :         UDAV_SETBIT(sc, UDAV_GPCR, UDAV_GPCR_GEP_CNTL0);
     634           0 :         UDAV_CLRBIT(sc, UDAV_GPR, UDAV_GPR_GEPIO0);
     635             : 
     636           0 :         if (!(sc->sc_flags & UDAV_RD9700))
     637           0 :                 mii_mediachg(mii);
     638             : 
     639           0 :         if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) {
     640           0 :                 if (udav_openpipes(sc)) {
     641           0 :                         splx(s);
     642           0 :                         return (EIO);
     643             :                 }
     644             :         }
     645             : 
     646           0 :         ifp->if_flags |= IFF_RUNNING;
     647           0 :         ifq_clr_oactive(&ifp->if_snd);
     648             : 
     649           0 :         splx(s);
     650             : 
     651           0 :         timeout_add_sec(&sc->sc_stat_ch, 1);
     652             : 
     653           0 :         return (0);
     654           0 : }
     655             : 
     656             : void
     657           0 : udav_reset(struct udav_softc *sc)
     658             : {
     659             :         int i;
     660             : 
     661             :         DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
     662             : 
     663           0 :         if (usbd_is_dying(sc->sc_udev))
     664           0 :                 return;
     665             : 
     666             :         /* Select PHY */
     667             : #if 1
     668             :         /*
     669             :          * XXX: force select internal phy.
     670             :          *      external phy routines are not tested.
     671             :          */
     672           0 :         UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
     673             : #else
     674             :         if (sc->sc_flags & UDAV_EXT_PHY) {
     675             :                 UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
     676             :         } else {
     677             :                 UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
     678             :         }
     679             : #endif
     680             : 
     681           0 :         UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_RST);
     682             : 
     683           0 :         for (i = 0; i < UDAV_TX_TIMEOUT; i++) {
     684           0 :                 if (!(udav_csr_read1(sc, UDAV_NCR) & UDAV_NCR_RST))
     685             :                         break;
     686           0 :                 delay(10);      /* XXX */
     687             :         }
     688           0 :         delay(10000);           /* XXX */
     689           0 : }
     690             : 
     691             : #define UDAV_BITS       6
     692             : 
     693             : void
     694           0 : udav_iff(struct udav_softc *sc)
     695             : {
     696           0 :         struct ifnet *ifp = GET_IFP(sc);
     697             :         struct arpcom *ac = &sc->sc_ac;
     698             :         struct ether_multi *enm;
     699             :         struct ether_multistep step;
     700           0 :         u_int8_t hashes[8];
     701             :         int h = 0;
     702             : 
     703             :         DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
     704             : 
     705           0 :         if (usbd_is_dying(sc->sc_udev))
     706           0 :                 return;
     707             : 
     708           0 :         UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC);
     709           0 :         memset(hashes, 0x00, sizeof(hashes));
     710           0 :         ifp->if_flags &= ~IFF_ALLMULTI;
     711             : 
     712           0 :         if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
     713           0 :                 ifp->if_flags |= IFF_ALLMULTI;
     714           0 :                 UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
     715           0 :                 if (ifp->if_flags & IFF_PROMISC)
     716           0 :                         UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_PRMSC);
     717             :         } else {
     718           0 :                 hashes[7] |= 0x80;      /* broadcast address */
     719             : 
     720             :                 /* now program new ones */
     721           0 :                 ETHER_FIRST_MULTI(step, ac, enm);
     722           0 :                 while (enm != NULL) {
     723           0 :                         h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) &
     724             :                             ((1 << UDAV_BITS) - 1);
     725             : 
     726           0 :                         hashes[h>>3] |= 1 << (h & 0x7);
     727             : 
     728           0 :                         ETHER_NEXT_MULTI(step, enm);
     729             :                 }
     730             :         }
     731             : 
     732           0 :         udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes));
     733           0 : }
     734             : 
     735             : int
     736           0 : udav_openpipes(struct udav_softc *sc)
     737             : {
     738             :         struct udav_chain *c;
     739             :         usbd_status err;
     740             :         int i;
     741             :         int error = 0;
     742             : 
     743           0 :         if (usbd_is_dying(sc->sc_udev))
     744           0 :                 return (EIO);
     745             : 
     746           0 :         sc->sc_refcnt++;
     747             : 
     748             :         /* Open RX pipe */
     749           0 :         err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no,
     750           0 :                              USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx);
     751           0 :         if (err) {
     752           0 :                 printf("%s: open rx pipe failed: %s\n",
     753           0 :                        sc->sc_dev.dv_xname, usbd_errstr(err));
     754             :                 error = EIO;
     755           0 :                 goto done;
     756             :         }
     757             : 
     758             :         /* Open TX pipe */
     759           0 :         err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no,
     760           0 :                              USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx);
     761           0 :         if (err) {
     762           0 :                 printf("%s: open tx pipe failed: %s\n",
     763           0 :                        sc->sc_dev.dv_xname, usbd_errstr(err));
     764             :                 error = EIO;
     765           0 :                 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             :                                   USBD_EXCLUSIVE_USE, &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 = EIO;
     779             :                 goto done;
     780             :         }
     781             : #endif
     782             : 
     783             : 
     784             :         /* Start up the receive pipe. */
     785           0 :         for (i = 0; i < UDAV_RX_LIST_CNT; i++) {
     786           0 :                 c = &sc->sc_cdata.udav_rx_chain[i];
     787           0 :                 usbd_setup_xfer(c->udav_xfer, sc->sc_pipe_rx,
     788           0 :                                 c, c->udav_buf, UDAV_BUFSZ,
     789             :                                 USBD_SHORT_XFER_OK | USBD_NO_COPY,
     790             :                                 USBD_NO_TIMEOUT, udav_rxeof);
     791           0 :                 (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           0 :         if (--sc->sc_refcnt < 0)
     798           0 :                 usb_detach_wakeup(&sc->sc_dev);
     799             : 
     800           0 :         return (error);
     801           0 : }
     802             : 
     803             : int
     804           0 : udav_newbuf(struct udav_softc *sc, struct udav_chain *c, struct mbuf *m)
     805             : {
     806             :         struct mbuf *m_new = NULL;
     807             : 
     808             :         DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
     809             : 
     810           0 :         if (m == NULL) {
     811           0 :                 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
     812           0 :                 if (m_new == NULL) {
     813           0 :                         printf("%s: no memory for rx list "
     814           0 :                                "-- packet dropped!\n", sc->sc_dev.dv_xname);
     815           0 :                         return (ENOBUFS);
     816             :                 }
     817           0 :                 MCLGET(m_new, M_DONTWAIT);
     818           0 :                 if (!(m_new->m_flags & M_EXT)) {
     819           0 :                         printf("%s: no memory for rx list "
     820           0 :                                "-- packet dropped!\n", sc->sc_dev.dv_xname);
     821           0 :                         m_freem(m_new);
     822           0 :                         return (ENOBUFS);
     823             :                 }
     824           0 :                 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
     825           0 :         } else {
     826             :                 m_new = m;
     827           0 :                 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
     828           0 :                 m_new->m_data = m_new->m_ext.ext_buf;
     829             :         }
     830             : 
     831           0 :         m_adj(m_new, ETHER_ALIGN);
     832           0 :         c->udav_mbuf = m_new;
     833             : 
     834           0 :         return (0);
     835           0 : }
     836             : 
     837             : 
     838             : int
     839           0 : udav_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           0 :         cd = &sc->sc_cdata;
     848           0 :         for (i = 0; i < UDAV_RX_LIST_CNT; i++) {
     849           0 :                 c = &cd->udav_rx_chain[i];
     850           0 :                 c->udav_sc = sc;
     851           0 :                 c->udav_idx = i;
     852           0 :                 if (udav_newbuf(sc, c, NULL) == ENOBUFS)
     853           0 :                         return (ENOBUFS);
     854           0 :                 if (c->udav_xfer == NULL) {
     855           0 :                         c->udav_xfer = usbd_alloc_xfer(sc->sc_udev);
     856           0 :                         if (c->udav_xfer == NULL)
     857           0 :                                 return (ENOBUFS);
     858           0 :                         c->udav_buf = usbd_alloc_buffer(c->udav_xfer, UDAV_BUFSZ);
     859           0 :                         if (c->udav_buf == NULL) {
     860           0 :                                 usbd_free_xfer(c->udav_xfer);
     861           0 :                                 return (ENOBUFS);
     862             :                         }
     863             :                 }
     864             :         }
     865             : 
     866           0 :         return (0);
     867           0 : }
     868             : 
     869             : int
     870           0 : udav_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           0 :         cd = &sc->sc_cdata;
     879           0 :         for (i = 0; i < UDAV_TX_LIST_CNT; i++) {
     880           0 :                 c = &cd->udav_tx_chain[i];
     881           0 :                 c->udav_sc = sc;
     882           0 :                 c->udav_idx = i;
     883           0 :                 c->udav_mbuf = NULL;
     884           0 :                 if (c->udav_xfer == NULL) {
     885           0 :                         c->udav_xfer = usbd_alloc_xfer(sc->sc_udev);
     886           0 :                         if (c->udav_xfer == NULL)
     887           0 :                                 return (ENOBUFS);
     888           0 :                         c->udav_buf = usbd_alloc_buffer(c->udav_xfer, UDAV_BUFSZ);
     889           0 :                         if (c->udav_buf == NULL) {
     890           0 :                                 usbd_free_xfer(c->udav_xfer);
     891           0 :                                 return (ENOBUFS);
     892             :                         }
     893             :                 }
     894             :         }
     895             : 
     896           0 :         return (0);
     897           0 : }
     898             : 
     899             : void
     900           0 : udav_start(struct ifnet *ifp)
     901             : {
     902           0 :         struct udav_softc *sc = ifp->if_softc;
     903             :         struct mbuf *m_head = NULL;
     904             : 
     905             :         DPRINTF(("%s: %s: enter, link=%d\n", sc->sc_dev.dv_xname,
     906             :                  __func__, sc->sc_link));
     907             : 
     908           0 :         if (usbd_is_dying(sc->sc_udev))
     909           0 :                 return;
     910             : 
     911           0 :         if (!sc->sc_link)
     912           0 :                 return;
     913             : 
     914           0 :         if (ifq_is_oactive(&ifp->if_snd))
     915           0 :                 return;
     916             : 
     917           0 :         m_head = ifq_deq_begin(&ifp->if_snd);
     918           0 :         if (m_head == NULL)
     919           0 :                 return;
     920             : 
     921           0 :         if (udav_send(sc, m_head, 0)) {
     922           0 :                 ifq_deq_rollback(&ifp->if_snd, m_head);
     923           0 :                 ifq_set_oactive(&ifp->if_snd);
     924           0 :                 return;
     925             :         }
     926             : 
     927           0 :         ifq_deq_commit(&ifp->if_snd, m_head);
     928             : 
     929             : #if NBPFILTER > 0
     930           0 :         if (ifp->if_bpf)
     931           0 :                 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
     932             : #endif
     933             : 
     934           0 :         ifq_set_oactive(&ifp->if_snd);
     935             : 
     936             :         /* Set a timeout in case the chip goes out to lunch. */
     937           0 :         ifp->if_timer = 5;
     938           0 : }
     939             : 
     940             : int
     941           0 : udav_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           0 :         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           0 :         m_copydata(m, 0, m->m_pkthdr.len, c->udav_buf + 2);
     954           0 :         c->udav_mbuf = m;
     955           0 :         total_len = m->m_pkthdr.len;
     956           0 :         if (total_len < UDAV_MIN_FRAME_LEN) {
     957           0 :                 memset(c->udav_buf + 2 + total_len, 0,
     958             :                     UDAV_MIN_FRAME_LEN - total_len);
     959             :                 total_len = UDAV_MIN_FRAME_LEN;
     960           0 :         }
     961             : 
     962             :         /* Frame length is specified in the first 2bytes of the buffer */
     963           0 :         c->udav_buf[0] = (u_int8_t)total_len;
     964           0 :         c->udav_buf[1] = (u_int8_t)(total_len >> 8);
     965           0 :         total_len += 2;
     966             : 
     967           0 :         usbd_setup_xfer(c->udav_xfer, sc->sc_pipe_tx, c, c->udav_buf, total_len,
     968             :                         USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
     969             :                         UDAV_TX_TIMEOUT, udav_txeof);
     970             : 
     971             :         /* Transmit */
     972           0 :         sc->sc_refcnt++;
     973           0 :         err = usbd_transfer(c->udav_xfer);
     974           0 :         if (--sc->sc_refcnt < 0)
     975           0 :                 usb_detach_wakeup(&sc->sc_dev);
     976           0 :         if (err != USBD_IN_PROGRESS) {
     977           0 :                 printf("%s: udav_send error=%s\n", sc->sc_dev.dv_xname,
     978           0 :                        usbd_errstr(err));
     979             :                 /* Stop the interface */
     980           0 :                 usb_add_task(sc->sc_udev, &sc->sc_stop_task);
     981           0 :                 return (EIO);
     982             :         }
     983             : 
     984             :         DPRINTF(("%s: %s: send %d bytes\n", sc->sc_dev.dv_xname,
     985             :                  __func__, total_len));
     986             : 
     987           0 :         sc->sc_cdata.udav_tx_cnt++;
     988             : 
     989           0 :         return (0);
     990           0 : }
     991             : 
     992             : void
     993           0 : udav_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
     994             : {
     995           0 :         struct udav_chain *c = priv;
     996           0 :         struct udav_softc *sc = c->udav_sc;
     997           0 :         struct ifnet *ifp = GET_IFP(sc);
     998             :         int s;
     999             : 
    1000           0 :         if (usbd_is_dying(sc->sc_udev))
    1001           0 :                 return;
    1002             : 
    1003           0 :         s = splnet();
    1004             : 
    1005             :         DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
    1006             : 
    1007           0 :         ifp->if_timer = 0;
    1008           0 :         ifq_clr_oactive(&ifp->if_snd);
    1009             : 
    1010           0 :         if (status != USBD_NORMAL_COMPLETION) {
    1011           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
    1012           0 :                         splx(s);
    1013           0 :                         return;
    1014             :                 }
    1015           0 :                 ifp->if_oerrors++;
    1016           0 :                 printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname,
    1017           0 :                        usbd_errstr(status));
    1018           0 :                 if (status == USBD_STALLED) {
    1019           0 :                         sc->sc_refcnt++;
    1020           0 :                         usbd_clear_endpoint_stall_async(sc->sc_pipe_tx);
    1021           0 :                         if (--sc->sc_refcnt < 0)
    1022           0 :                                 usb_detach_wakeup(&sc->sc_dev);
    1023             :                 }
    1024           0 :                 splx(s);
    1025           0 :                 return;
    1026             :         }
    1027             : 
    1028           0 :         m_freem(c->udav_mbuf);
    1029           0 :         c->udav_mbuf = NULL;
    1030             : 
    1031           0 :         if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    1032           0 :                 udav_start(ifp);
    1033             : 
    1034           0 :         splx(s);
    1035           0 : }
    1036             : 
    1037             : void
    1038           0 : udav_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
    1039             : {
    1040           0 :         struct udav_chain *c = priv;
    1041           0 :         struct udav_softc *sc = c->udav_sc;
    1042           0 :         struct ifnet *ifp = GET_IFP(sc);
    1043             :         struct udav_rx_hdr *h;
    1044           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
    1045             :         struct mbuf *m;
    1046           0 :         u_int32_t total_len;
    1047             :         int s;
    1048             : 
    1049             :         DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__));
    1050             : 
    1051           0 :         if (usbd_is_dying(sc->sc_udev))
    1052           0 :                 return;
    1053             : 
    1054           0 :         if (status != USBD_NORMAL_COMPLETION) {
    1055           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    1056           0 :                         return;
    1057           0 :                 sc->sc_rx_errs++;
    1058           0 :                 if (usbd_ratecheck(&sc->sc_rx_notice)) {
    1059           0 :                         printf("%s: %u usb errors on rx: %s\n",
    1060           0 :                                sc->sc_dev.dv_xname, sc->sc_rx_errs,
    1061           0 :                                usbd_errstr(status));
    1062           0 :                         sc->sc_rx_errs = 0;
    1063           0 :                 }
    1064           0 :                 if (status == USBD_STALLED) {
    1065           0 :                         sc->sc_refcnt++;
    1066           0 :                         usbd_clear_endpoint_stall_async(sc->sc_pipe_rx);
    1067           0 :                         if (--sc->sc_refcnt < 0)
    1068           0 :                                 usb_detach_wakeup(&sc->sc_dev);
    1069             :                 }
    1070             :                 goto done;
    1071             :         }
    1072             : 
    1073           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
    1074             : 
    1075           0 :         if (total_len < UDAV_RX_HDRLEN) {
    1076           0 :                 ifp->if_ierrors++;
    1077           0 :                 goto done;
    1078             :         }
    1079             :         
    1080           0 :         h = (struct udav_rx_hdr *)c->udav_buf;
    1081           0 :         total_len = UGETW(h->length) - ETHER_CRC_LEN;
    1082             :         
    1083             :         DPRINTF(("%s: RX Status: 0x%02x\n", sc->sc_dev.dv_xname, h->pktstat));
    1084             : 
    1085           0 :         if (h->pktstat & UDAV_RSR_LCS) {
    1086           0 :                 ifp->if_collisions++;
    1087           0 :                 goto done;
    1088             :         }
    1089             : 
    1090             :         /* RX status may still be correct but total_len is bogus */
    1091           0 :         if (total_len < sizeof(struct ether_header) ||
    1092           0 :             h->pktstat & UDAV_RSR_ERR ||
    1093           0 :             total_len > UDAV_BUFSZ ) {
    1094           0 :                 ifp->if_ierrors++;
    1095           0 :                 goto done;
    1096             :         }
    1097             : 
    1098             :         /* copy data to mbuf */
    1099           0 :         m = c->udav_mbuf;
    1100           0 :         memcpy(mtod(m, char *), c->udav_buf + UDAV_RX_HDRLEN, total_len);
    1101             : 
    1102           0 :         m->m_pkthdr.len = m->m_len = total_len;
    1103           0 :         ml_enqueue(&ml, m);
    1104             : 
    1105           0 :         if (udav_newbuf(sc, c, NULL) == ENOBUFS) {
    1106           0 :                 ifp->if_ierrors++;
    1107           0 :                 goto done;
    1108             :         }
    1109             : 
    1110           0 :         s = splnet();
    1111           0 :         if_input(ifp, &ml);
    1112           0 :         splx(s);
    1113             : 
    1114             :  done:
    1115             :         /* Setup new transfer */
    1116           0 :         usbd_setup_xfer(xfer, sc->sc_pipe_rx, c, c->udav_buf, UDAV_BUFSZ,
    1117             :                         USBD_SHORT_XFER_OK | USBD_NO_COPY,
    1118             :                         USBD_NO_TIMEOUT, udav_rxeof);
    1119           0 :         sc->sc_refcnt++;
    1120           0 :         usbd_transfer(xfer);
    1121           0 :         if (--sc->sc_refcnt < 0)
    1122           0 :                 usb_detach_wakeup(&sc->sc_dev);
    1123             : 
    1124             :         DPRINTF(("%s: %s: start rx\n", sc->sc_dev.dv_xname, __func__));
    1125           0 : }
    1126             : 
    1127             : int
    1128           0 : udav_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
    1129             : {
    1130           0 :         struct udav_softc *sc = ifp->if_softc;
    1131           0 :         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           0 :         if (usbd_is_dying(sc->sc_udev))
    1137           0 :                 return (EIO);
    1138             : 
    1139           0 :         s = splnet();
    1140             : 
    1141           0 :         switch (cmd) {
    1142             :         case SIOCSIFADDR:
    1143           0 :                 ifp->if_flags |= IFF_UP;
    1144           0 :                 if (!(ifp->if_flags & IFF_RUNNING))
    1145           0 :                         udav_init(ifp);
    1146             :                 break;
    1147             : 
    1148             :         case SIOCSIFFLAGS:
    1149           0 :                 if (ifp->if_flags & IFF_UP) {
    1150           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1151           0 :                                 error = ENETRESET;
    1152             :                         else
    1153           0 :                                 udav_init(ifp);
    1154             :                 } else {
    1155           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1156           0 :                                 udav_stop(ifp, 1);
    1157             :                 }
    1158             :                 break;
    1159             : 
    1160             :         case SIOCGIFMEDIA:
    1161             :         case SIOCSIFMEDIA:
    1162           0 :                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
    1163           0 :                 break;
    1164             : 
    1165             :         default:
    1166           0 :                 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
    1167           0 :         }
    1168             : 
    1169           0 :         if (error == ENETRESET) {
    1170           0 :                 if (ifp->if_flags & IFF_RUNNING)
    1171           0 :                         udav_iff(sc);
    1172             :                 error = 0;
    1173           0 :         }
    1174             : 
    1175           0 :         splx(s);
    1176           0 :         return (error);
    1177           0 : }
    1178             : 
    1179             : void
    1180           0 : udav_watchdog(struct ifnet *ifp)
    1181             : {
    1182           0 :         struct udav_softc *sc = ifp->if_softc;
    1183             :         struct udav_chain *c;
    1184           0 :         usbd_status stat;
    1185             :         int s;
    1186             : 
    1187             :         DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
    1188             : 
    1189           0 :         ifp->if_oerrors++;
    1190           0 :         printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
    1191             : 
    1192           0 :         s = splusb();
    1193           0 :         c = &sc->sc_cdata.udav_tx_chain[0];
    1194           0 :         usbd_get_xfer_status(c->udav_xfer, NULL, NULL, NULL, &stat);
    1195           0 :         udav_txeof(c->udav_xfer, c, stat);
    1196             : 
    1197           0 :         if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    1198           0 :                 udav_start(ifp);
    1199           0 :         splx(s);
    1200           0 : }
    1201             : 
    1202             : void
    1203           0 : udav_stop_task(struct udav_softc *sc)
    1204             : {
    1205           0 :         udav_stop(GET_IFP(sc), 1);
    1206           0 : }
    1207             : 
    1208             : /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */
    1209             : void
    1210           0 : udav_stop(struct ifnet *ifp, int disable)
    1211             : {
    1212           0 :         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           0 :         ifp->if_timer = 0;
    1219           0 :         ifp->if_flags &= ~IFF_RUNNING;
    1220           0 :         ifq_clr_oactive(&ifp->if_snd);
    1221             : 
    1222           0 :         udav_reset(sc);
    1223             : 
    1224           0 :         timeout_del(&sc->sc_stat_ch);
    1225             : 
    1226             :         /* Stop transfers */
    1227             :         /* RX endpoint */
    1228           0 :         if (sc->sc_pipe_rx != NULL) {
    1229           0 :                 usbd_abort_pipe(sc->sc_pipe_rx);
    1230           0 :                 err = usbd_close_pipe(sc->sc_pipe_rx);
    1231           0 :                 if (err)
    1232           0 :                         printf("%s: close rx pipe failed: %s\n",
    1233           0 :                                sc->sc_dev.dv_xname, usbd_errstr(err));
    1234           0 :                 sc->sc_pipe_rx = NULL;
    1235           0 :         }
    1236             : 
    1237             :         /* TX endpoint */
    1238           0 :         if (sc->sc_pipe_tx != NULL) {
    1239           0 :                 usbd_abort_pipe(sc->sc_pipe_tx);
    1240           0 :                 err = usbd_close_pipe(sc->sc_pipe_tx);
    1241           0 :                 if (err)
    1242           0 :                         printf("%s: close tx pipe failed: %s\n",
    1243           0 :                                sc->sc_dev.dv_xname, usbd_errstr(err));
    1244           0 :                 sc->sc_pipe_tx = NULL;
    1245           0 :         }
    1246             : 
    1247             : #if 0
    1248             :         /* XXX: Interrupt endpoint is not yet supported!! */
    1249             :         /* Interrupt endpoint */
    1250             :         if (sc->sc_pipe_intr != NULL) {
    1251             :                 usbd_abort_pipe(sc->sc_pipe_intr);
    1252             :                 err = usbd_close_pipe(sc->sc_pipe_intr);
    1253             :                 if (err)
    1254             :                         printf("%s: close intr pipe failed: %s\n",
    1255             :                                sc->sc_dev.dv_xname, usbd_errstr(err));
    1256             :                 sc->sc_pipe_intr = NULL;
    1257             :         }
    1258             : #endif
    1259             : 
    1260             :         /* Free RX resources. */
    1261           0 :         for (i = 0; i < UDAV_RX_LIST_CNT; i++) {
    1262           0 :                 if (sc->sc_cdata.udav_rx_chain[i].udav_mbuf != NULL) {
    1263           0 :                         m_freem(sc->sc_cdata.udav_rx_chain[i].udav_mbuf);
    1264           0 :                         sc->sc_cdata.udav_rx_chain[i].udav_mbuf = NULL;
    1265           0 :                 }
    1266           0 :                 if (sc->sc_cdata.udav_rx_chain[i].udav_xfer != NULL) {
    1267           0 :                         usbd_free_xfer(sc->sc_cdata.udav_rx_chain[i].udav_xfer);
    1268           0 :                         sc->sc_cdata.udav_rx_chain[i].udav_xfer = NULL;
    1269           0 :                 }
    1270             :         }
    1271             : 
    1272             :         /* Free TX resources. */
    1273           0 :         for (i = 0; i < UDAV_TX_LIST_CNT; i++) {
    1274           0 :                 if (sc->sc_cdata.udav_tx_chain[i].udav_mbuf != NULL) {
    1275           0 :                         m_freem(sc->sc_cdata.udav_tx_chain[i].udav_mbuf);
    1276           0 :                         sc->sc_cdata.udav_tx_chain[i].udav_mbuf = NULL;
    1277           0 :                 }
    1278           0 :                 if (sc->sc_cdata.udav_tx_chain[i].udav_xfer != NULL) {
    1279           0 :                         usbd_free_xfer(sc->sc_cdata.udav_tx_chain[i].udav_xfer);
    1280           0 :                         sc->sc_cdata.udav_tx_chain[i].udav_xfer = NULL;
    1281           0 :                 }
    1282             :         }
    1283             : 
    1284           0 :         sc->sc_link = 0;
    1285           0 : }
    1286             : 
    1287             : /* Set media options */
    1288             : int
    1289           0 : udav_ifmedia_change(struct ifnet *ifp)
    1290             : {
    1291           0 :         struct udav_softc *sc = ifp->if_softc;
    1292           0 :         struct mii_data *mii = GET_MII(sc);
    1293             : 
    1294             :         DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
    1295             : 
    1296           0 :         if (usbd_is_dying(sc->sc_udev))
    1297           0 :                 return (0);
    1298             : 
    1299           0 :         sc->sc_link = 0;
    1300             : 
    1301           0 :         if (sc->sc_flags & UDAV_RD9700)
    1302           0 :                 return (0);
    1303             : 
    1304           0 :         if (mii->mii_instance) {
    1305             :                 struct mii_softc *miisc;
    1306           0 :                 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
    1307           0 :                         mii_phy_reset(miisc);
    1308           0 :         }
    1309             : 
    1310           0 :         return (mii_mediachg(mii));
    1311           0 : }
    1312             : 
    1313             : /* Report current media status. */
    1314             : void
    1315           0 : udav_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr)
    1316             : {
    1317           0 :         struct udav_softc *sc = ifp->if_softc;
    1318           0 :         struct mii_data *mii = GET_MII(sc);
    1319             : 
    1320             :         DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
    1321             : 
    1322           0 :         if (usbd_is_dying(sc->sc_udev))
    1323           0 :                 return;
    1324             : 
    1325           0 :         if ((ifp->if_flags & IFF_RUNNING) == 0) {
    1326           0 :                 ifmr->ifm_active = IFM_ETHER | IFM_NONE;
    1327           0 :                 ifmr->ifm_status = 0;
    1328           0 :                 return;
    1329             :         }
    1330             : 
    1331           0 :         if (sc->sc_flags & UDAV_RD9700) {
    1332           0 :                 ifmr->ifm_active = IFM_ETHER | IFM_10_T;
    1333           0 :                 ifmr->ifm_status = IFM_AVALID;
    1334           0 :                 if (sc->sc_link) ifmr->ifm_status |= IFM_ACTIVE;
    1335           0 :                 return;
    1336             :         }
    1337             : 
    1338           0 :         mii_pollstat(mii);
    1339           0 :         ifmr->ifm_active = mii->mii_media_active;
    1340           0 :         ifmr->ifm_status = mii->mii_media_status;
    1341           0 : }
    1342             : 
    1343             : void
    1344           0 : udav_tick(void *xsc)
    1345             : {
    1346           0 :         struct udav_softc *sc = xsc;
    1347             : 
    1348           0 :         if (sc == NULL)
    1349           0 :                 return;
    1350             : 
    1351             :         DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
    1352             :                         __func__));
    1353             : 
    1354             :         /* Perform periodic stuff in process context */
    1355           0 :         usb_add_task(sc->sc_udev, &sc->sc_tick_task);
    1356           0 : }
    1357             : 
    1358             : void
    1359           0 : udav_tick_task(void *xsc)
    1360             : {
    1361           0 :         struct udav_softc *sc = xsc;
    1362             :         struct ifnet *ifp;
    1363             :         struct mii_data *mii;
    1364             :         int s, sts;
    1365             : 
    1366           0 :         if (sc == NULL)
    1367           0 :                 return;
    1368             : 
    1369             :         DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
    1370             :                         __func__));
    1371             : 
    1372           0 :         if (usbd_is_dying(sc->sc_udev))
    1373           0 :                 return;
    1374             : 
    1375           0 :         ifp = GET_IFP(sc);
    1376           0 :         mii = GET_MII(sc);
    1377             : 
    1378           0 :         if (mii == NULL)
    1379           0 :                 return;
    1380             : 
    1381           0 :         s = splnet();
    1382             : 
    1383           0 :         if (sc->sc_flags & UDAV_RD9700) {
    1384           0 :                 sts = udav_csr_read1(sc, UDAV_NSR) & UDAV_NSR_LINKST;
    1385           0 :                 if (!sts)
    1386           0 :                         sc->sc_link = 0;
    1387             :         } else {
    1388           0 :                 mii_tick(mii);
    1389           0 :                 sts = (mii->mii_media_status & IFM_ACTIVE &&
    1390           0 :                        IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) ? 1 : 0;
    1391             :         }
    1392             : 
    1393           0 :         if (!sc->sc_link && sts) {
    1394             :                 DPRINTF(("%s: %s: got link\n",
    1395             :                          sc->sc_dev.dv_xname, __func__));
    1396           0 :                 sc->sc_link++;
    1397           0 :                 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    1398           0 :                            udav_start(ifp);
    1399             :         }
    1400             : 
    1401           0 :         timeout_add_sec(&sc->sc_stat_ch, 1);
    1402             : 
    1403           0 :         splx(s);
    1404           0 : }
    1405             : 
    1406             : /* Get exclusive access to the MII registers */
    1407             : void
    1408           0 : udav_lock_mii(struct udav_softc *sc)
    1409             : {
    1410             :         DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
    1411             :                         __func__));
    1412             : 
    1413           0 :         sc->sc_refcnt++;
    1414           0 :         rw_enter_write(&sc->sc_mii_lock);
    1415           0 : }
    1416             : 
    1417             : void
    1418           0 : udav_unlock_mii(struct udav_softc *sc)
    1419             : {
    1420             :         DPRINTFN(0xff, ("%s: %s: enter\n", sc->sc_dev.dv_xname,
    1421             :                        __func__));
    1422             : 
    1423           0 :         rw_exit_write(&sc->sc_mii_lock);
    1424           0 :         if (--sc->sc_refcnt < 0)
    1425           0 :                 usb_detach_wakeup(&sc->sc_dev);
    1426           0 : }
    1427             : 
    1428             : int
    1429           0 : udav_miibus_readreg(struct device *dev, int phy, int reg)
    1430             : {
    1431             :         struct udav_softc *sc;
    1432           0 :         u_int8_t val[2];
    1433             :         u_int16_t data16;
    1434             : 
    1435           0 :         if (dev == NULL)
    1436           0 :                 return (0);
    1437             : 
    1438           0 :         sc = (void *)dev;
    1439             : 
    1440             :         DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n",
    1441             :                  sc->sc_dev.dv_xname, __func__, phy, reg));
    1442             : 
    1443           0 :         if (usbd_is_dying(sc->sc_udev)) {
    1444             : #ifdef DIAGNOSTIC
    1445           0 :                 printf("%s: %s: dying\n", sc->sc_dev.dv_xname,
    1446             :                        __func__);
    1447             : #endif
    1448           0 :                 return (0);
    1449             :         }
    1450             : 
    1451             :         /* XXX: one PHY only for the internal PHY */
    1452           0 :         if (phy != 0) {
    1453             :                 DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
    1454             :                          sc->sc_dev.dv_xname, __func__, phy));
    1455           0 :                 return (0);
    1456             :         }
    1457             : 
    1458           0 :         udav_lock_mii(sc);
    1459             : 
    1460             :         /* select internal PHY and set PHY register address */
    1461           0 :         udav_csr_write1(sc, UDAV_EPAR,
    1462           0 :                         UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
    1463             : 
    1464             :         /* select PHY operation and start read command */
    1465           0 :         udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRR);
    1466             : 
    1467             :         /* XXX: should be wait? */
    1468             : 
    1469             :         /* end read command */
    1470           0 :         UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRR);
    1471             : 
    1472             :         /* retrieve the result from data registers */
    1473           0 :         udav_csr_read(sc, UDAV_EPDRL, val, 2);
    1474             : 
    1475           0 :         udav_unlock_mii(sc);
    1476             : 
    1477           0 :         data16 = val[0] | (val[1] << 8);
    1478             : 
    1479             :         DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04x\n",
    1480             :                  sc->sc_dev.dv_xname, __func__, phy, reg, data16));
    1481             : 
    1482           0 :         return (data16);
    1483           0 : }
    1484             : 
    1485             : void
    1486           0 : udav_miibus_writereg(struct device *dev, int phy, int reg, int data)
    1487             : {
    1488             :         struct udav_softc *sc;
    1489           0 :         u_int8_t val[2];
    1490             : 
    1491           0 :         if (dev == NULL)
    1492           0 :                 return;
    1493             : 
    1494           0 :         sc = (void *)dev;
    1495             : 
    1496             :         DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n",
    1497             :                  sc->sc_dev.dv_xname, __func__, phy, reg, data));
    1498             : 
    1499           0 :         if (usbd_is_dying(sc->sc_udev)) {
    1500             : #ifdef DIAGNOSTIC
    1501           0 :                 printf("%s: %s: dying\n", sc->sc_dev.dv_xname,
    1502             :                        __func__);
    1503             : #endif
    1504           0 :                 return;
    1505             :         }
    1506             : 
    1507             :         /* XXX: one PHY only for the internal PHY */
    1508           0 :         if (phy != 0) {
    1509             :                 DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
    1510             :                          sc->sc_dev.dv_xname, __func__, phy));
    1511           0 :                 return;
    1512             :         }
    1513             : 
    1514           0 :         udav_lock_mii(sc);
    1515             : 
    1516             :         /* select internal PHY and set PHY register address */
    1517           0 :         udav_csr_write1(sc, UDAV_EPAR,
    1518           0 :                         UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
    1519             : 
    1520             :         /* put the value to the data registers */
    1521           0 :         val[0] = data & 0xff;
    1522           0 :         val[1] = (data >> 8) & 0xff;
    1523           0 :         udav_csr_write(sc, UDAV_EPDRL, val, 2);
    1524             : 
    1525             :         /* select PHY operation and start write command */
    1526           0 :         udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRW);
    1527             : 
    1528             :         /* XXX: should be wait? */
    1529             : 
    1530             :         /* end write command */
    1531           0 :         UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRW);
    1532             : 
    1533           0 :         udav_unlock_mii(sc);
    1534             : 
    1535           0 :         return;
    1536           0 : }
    1537             : 
    1538             : void
    1539           0 : udav_miibus_statchg(struct device *dev)
    1540             : {
    1541             : #ifdef UDAV_DEBUG
    1542             :         struct udav_softc *sc;
    1543             : 
    1544             :         if (dev == NULL)
    1545             :                 return;
    1546             : 
    1547             :         sc = (void *)dev;
    1548             :         DPRINTF(("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__));
    1549             : #endif
    1550             :         /* Nothing to do */
    1551           0 : }

Generated by: LCOV version 1.13