Module Name: src Committed By: skrll Date: Wed Aug 7 19:21:48 UTC 2019
Modified Files: src/sys/dev/usb: files.usb if_udav.c if_udavreg.h Log Message: Convert udav(4) to usbnet. Based on a diff from mrg@ To generate a diff of this commit: cvs rdiff -u -r1.160 -r1.161 src/sys/dev/usb/files.usb cvs rdiff -u -r1.60 -r1.61 src/sys/dev/usb/if_udav.c cvs rdiff -u -r1.14 -r1.15 src/sys/dev/usb/if_udavreg.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/files.usb diff -u src/sys/dev/usb/files.usb:1.160 src/sys/dev/usb/files.usb:1.161 --- src/sys/dev/usb/files.usb:1.160 Wed Aug 7 07:25:09 2019 +++ src/sys/dev/usb/files.usb Wed Aug 7 19:21:48 2019 @@ -1,4 +1,4 @@ -# $NetBSD: files.usb,v 1.160 2019/08/07 07:25:09 skrll Exp $ +# $NetBSD: files.usb,v 1.161 2019/08/07 19:21:48 skrll Exp $ # # Config file and device description for machine-independent USB code. # Included by ports that need it. Ports that use it must provide @@ -378,7 +378,7 @@ attach mue at usbdevif file dev/usb/if_mue.c mue # DAVICOM DM9601 -device udav: arp, ether, ifnet, mii, mii_phy +device udav: arp, ether, ifnet, mii, mii_phy, usbnet attach udav at usbdevif file dev/usb/if_udav.c udav Index: src/sys/dev/usb/if_udav.c diff -u src/sys/dev/usb/if_udav.c:1.60 src/sys/dev/usb/if_udav.c:1.61 --- src/sys/dev/usb/if_udav.c:1.60 Thu Aug 1 00:10:22 2019 +++ src/sys/dev/usb/if_udav.c Wed Aug 7 19:21:48 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: if_udav.c,v 1.60 2019/08/01 00:10:22 mrg Exp $ */ +/* $NetBSD: if_udav.c,v 1.61 2019/08/07 19:21:48 skrll Exp $ */ /* $nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $ */ /* @@ -45,95 +45,64 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_udav.c,v 1.60 2019/08/01 00:10:22 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_udav.c,v 1.61 2019/08/07 19:21:48 skrll Exp $"); #ifdef _KERNEL_OPT -#include "opt_inet.h" #include "opt_usb.h" #endif #include <sys/param.h> #include <sys/systm.h> -#include <sys/mutex.h> -#include <sys/mbuf.h> +#include <sys/module.h> #include <sys/kernel.h> -#include <sys/socket.h> -#include <sys/device.h> -#include <sys/rndsource.h> - -#include <net/if.h> -#include <net/if_arp.h> -#include <net/if_dl.h> -#include <net/if_media.h> - -#include <net/bpf.h> - -#include <net/if_ether.h> -#ifdef INET -#include <netinet/in.h> -#include <netinet/if_inarp.h> -#endif - -#include <dev/mii/mii.h> -#include <dev/mii/miivar.h> - -#include <dev/usb/usb.h> -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdevs.h> +#include <dev/usb/usbnet.h> #include <dev/usb/if_udavreg.h> +struct udav_softc { + struct usbnet sc_un; + uint16_t sc_flags; +}; /* Function declarations */ int udav_match(device_t, cfdata_t, void *); void udav_attach(device_t, device_t, void *); -int udav_detach(device_t, int); -int udav_activate(device_t, enum devact); CFATTACH_DECL_NEW(udav, sizeof(struct udav_softc), udav_match, udav_attach, - udav_detach, udav_activate); + usbnet_detach, usbnet_activate); + +static void udav_chip_init(struct usbnet *); -Static int udav_openpipes(struct udav_softc *); -Static int udav_rx_list_init(struct udav_softc *); -Static int udav_tx_list_init(struct udav_softc *); -Static int udav_newbuf(struct udav_softc *, struct udav_chain *, struct mbuf *); -Static void udav_start(struct ifnet *); -Static int udav_send(struct udav_softc *, struct mbuf *, int); -Static void udav_txeof(struct usbd_xfer *, void *, usbd_status); -Static void udav_rxeof(struct usbd_xfer *, void *, usbd_status); -Static void udav_tick(void *); -Static void udav_tick_task(void *); -Static int udav_ioctl(struct ifnet *, u_long, void *); -Static void udav_stop_task(struct udav_softc *); -Static void udav_stop(struct ifnet *, int); -Static void udav_watchdog(struct ifnet *); -Static int udav_ifmedia_change(struct ifnet *); -Static void udav_lock_mii(struct udav_softc *); -Static void udav_unlock_mii(struct udav_softc *); -Static int udav_miibus_readreg(device_t, int, int, uint16_t *); -Static int udav_miibus_writereg(device_t, int, int, uint16_t); -Static void udav_miibus_statchg(struct ifnet *); -Static int udav_init(struct ifnet *); -Static void udav_setmulti(struct udav_softc *); -Static void udav_reset(struct udav_softc *); - -Static int udav_csr_read(struct udav_softc *, int, void *, int); -Static int udav_csr_write(struct udav_softc *, int, void *, int); -Static int udav_csr_read1(struct udav_softc *, int); -Static int udav_csr_write1(struct udav_softc *, int, unsigned char); +static unsigned udav_tx_prepare(struct usbnet *, struct mbuf *, + struct usbnet_chain *); +static void udav_rxeof_loop(struct usbnet *, struct usbd_xfer *, + struct usbnet_chain *, uint32_t); +static void udav_stop_cb(struct ifnet *, int); +static int udav_ioctl_cb(struct ifnet *, u_long, void *); +static usbd_status udav_mii_read_reg(struct usbnet *, int, int, uint16_t *); +static usbd_status udav_mii_write_reg(struct usbnet *, int, int, uint16_t); +static void udav_mii_statchg(struct ifnet *); +static int udav_init(struct ifnet *); +static void udav_setiff(struct usbnet *); +static void udav_setiff_locked(struct usbnet *); +static void udav_reset(struct usbnet *); + +static int udav_csr_read(struct udav_softc *, int, void *, int); +static int udav_csr_write(struct udav_softc *, int, void *, int); +static int udav_csr_read1(struct udav_softc *, int); +static int udav_csr_write1(struct udav_softc *, int, unsigned char); #if 0 -Static int udav_mem_read(struct udav_softc *, int, void *, int); -Static int udav_mem_write(struct udav_softc *, int, void *, int); -Static int udav_mem_write1(struct udav_softc *, int, unsigned char); +static int udav_mem_read(struct udav_softc *, int, void *, int); +static int udav_mem_write(struct udav_softc *, int, void *, int); +static int udav_mem_write1(struct udav_softc *, int, unsigned char); #endif /* Macros */ #ifdef UDAV_DEBUG #define DPRINTF(x) if (udavdebug) printf x #define DPRINTFN(n, x) if (udavdebug >= (n)) printf x -int udavdebug = 0; +int udavdebug = 10; #else #define DPRINTF(x) #define DPRINTFN(n, x) @@ -187,6 +156,7 @@ void udav_attach(device_t parent, device_t self, void *aux) { struct udav_softc *sc = device_private(self); + struct usbnet * const un = &sc->sc_un; struct usb_attach_arg *uaa = aux; struct usbd_device *dev = uaa->uaa_device; struct usbd_interface *iface; @@ -194,208 +164,114 @@ udav_attach(device_t parent, device_t se usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; char *devinfop; - struct ifnet *ifp; - struct mii_data *mii; - u_char eaddr[ETHER_ADDR_LEN]; - int i, s; + int i; - sc->sc_dev = self; + /* Switch to usbnet for device_private() */ + self->dv_private = un; aprint_naive("\n"); aprint_normal("\n"); - devinfop = usbd_devinfo_alloc(dev, 0); aprint_normal_dev(self, "%s\n", devinfop); usbd_devinfo_free(devinfop); + un->un_dev = self; + un->un_udev = dev; + un->un_sc = sc; + un->un_stop_cb = udav_stop_cb; + un->un_ioctl_cb = udav_ioctl_cb; + un->un_read_reg_cb = udav_mii_read_reg; + un->un_write_reg_cb = udav_mii_write_reg; + un->un_statchg_cb = udav_mii_statchg; + un->un_tx_prepare_cb = udav_tx_prepare; + un->un_rx_loop_cb = udav_rxeof_loop; + un->un_init_cb = udav_init; + un->un_rx_xfer_flags = USBD_SHORT_XFER_OK; + un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER; + /* Move the device into the configured state. */ err = usbd_set_config_no(dev, UDAV_CONFIG_NO, 1); /* idx 0 */ if (err) { aprint_error_dev(self, "failed to set configuration" ", err=%s\n", usbd_errstr(err)); - goto bad; + return; } - usb_init_task(&sc->sc_tick_task, udav_tick_task, sc, 0); - mutex_init(&sc->sc_mii_lock, MUTEX_DEFAULT, IPL_NONE); - usb_init_task(&sc->sc_stop_task, (void (*)(void *))udav_stop_task, sc, - 0); - /* get control interface */ err = usbd_device2interface_handle(dev, UDAV_IFACE_INDEX, &iface); if (err) { aprint_error_dev(self, "failed to get interface, err=%s\n", usbd_errstr(err)); - goto bad; + return; } - sc->sc_udev = dev; - sc->sc_ctl_iface = iface; + un->un_iface = iface; sc->sc_flags = udav_lookup(uaa->uaa_vendor, uaa->uaa_product)->udav_flags; /* get interface descriptor */ - id = usbd_get_interface_descriptor(sc->sc_ctl_iface); + id = usbd_get_interface_descriptor(un->un_iface); /* find endpoints */ - sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1; + un->un_ed[USBNET_ENDPT_RX] = un->un_ed[USBNET_ENDPT_TX] = + un->un_ed[USBNET_ENDPT_INTR] = -1; for (i = 0; i < id->bNumEndpoints; i++) { - ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i); + ed = usbd_interface2endpoint_descriptor(un->un_iface, i); if (ed == NULL) { aprint_error_dev(self, "couldn't get endpoint %d\n", i); - goto bad; + return; } if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) - sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */ + un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress; else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT) - sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */ + un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress; else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) - sc->sc_intrin_no = ed->bEndpointAddress; /* Status */ + un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress; } - if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 || - sc->sc_intrin_no == -1) { + if (un->un_ed[USBNET_ENDPT_RX] == -1 || + un->un_ed[USBNET_ENDPT_TX] == -1 || + un->un_ed[USBNET_ENDPT_INTR] == -1) { aprint_error_dev(self, "missing endpoint\n"); - goto bad; + return; } - s = splnet(); + /* Not supported yet. */ + un->un_ed[USBNET_ENDPT_INTR] = 0; + + un->un_cdata.uncd_rx_bufsz = un->un_cdata.uncd_tx_bufsz = UDAV_BUFSZ; + +// /* reset the adapter */ +// udav_reset(un); - /* reset the adapter */ - udav_reset(sc); + usbnet_attach(un, "udavdet", UDAV_RX_LIST_CNT, UDAV_TX_LIST_CNT); /* Get Ethernet Address */ - err = udav_csr_read(sc, UDAV_PAR, (void *)eaddr, ETHER_ADDR_LEN); + usbnet_lock_mii(un); + err = udav_csr_read(sc, UDAV_PAR, un->un_eaddr, ETHER_ADDR_LEN); + usbnet_unlock_mii(un); if (err) { aprint_error_dev(self, "read MAC address failed\n"); - splx(s); - goto bad; + return; } - /* Print Ethernet Address */ - aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(eaddr)); + bool have_mii = !ISSET(sc->sc_flags, UDAV_NO_PHY); + if (!have_mii) + un->un_link = 1; /* initialize interface information */ - ifp = GET_IFP(sc); - ifp->if_softc = sc; - ifp->if_mtu = ETHERMTU; - strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_start = udav_start; - ifp->if_ioctl = udav_ioctl; - ifp->if_watchdog = udav_watchdog; - ifp->if_init = udav_init; - ifp->if_stop = udav_stop; - - IFQ_SET_READY(&ifp->if_snd); - - if (ISSET(sc->sc_flags, UDAV_NO_PHY)) { - sc->sc_link = 1; - goto skipmii; - } + usbnet_attach_ifp(un, have_mii, + IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 0, 0); - /* - * Do ifmedia setup. - */ - mii = &sc->sc_mii; - mii->mii_ifp = ifp; - mii->mii_readreg = udav_miibus_readreg; - mii->mii_writereg = udav_miibus_writereg; - mii->mii_statchg = udav_miibus_statchg; - mii->mii_flags = MIIF_AUTOTSLEEP; - sc->sc_ec.ec_mii = mii; - ifmedia_init(&mii->mii_media, 0, - udav_ifmedia_change, ether_mediastatus); - mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0); - if (LIST_FIRST(&mii->mii_phys) == NULL) { - ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL); - ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE); - } else - ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); - -skipmii: - /* attach the interface */ - if_attach(ifp); - ether_ifattach(ifp, eaddr); - - rnd_attach_source(&sc->rnd_source, device_xname(self), - RND_TYPE_NET, RND_FLAG_DEFAULT); - - callout_init(&sc->sc_stat_ch, 0); - sc->sc_attached = 1; - splx(s); - - usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, sc->sc_dev); - - return; - - bad: - sc->sc_dying = 1; return; } -/* detach */ -int -udav_detach(device_t self, int flags) -{ - struct udav_softc *sc = device_private(self); - struct ifnet *ifp = GET_IFP(sc); - int s; - - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); - - /* Detached before attached finished */ - if (!sc->sc_attached) - return 0; - - callout_halt(&sc->sc_stat_ch, NULL); - - /* Remove any pending tasks */ - usb_rem_task_wait(sc->sc_udev, &sc->sc_tick_task, USB_TASKQ_DRIVER, - NULL); - usb_rem_task_wait(sc->sc_udev, &sc->sc_stop_task, USB_TASKQ_DRIVER, - NULL); - - s = splusb(); - - if (--sc->sc_refcnt >= 0) { - /* Wait for processes to go away */ - usb_detach_waitold(sc->sc_dev); - } - if (ifp->if_flags & IFF_RUNNING) - udav_stop(GET_IFP(sc), 1); - - rnd_detach_source(&sc->rnd_source); - mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); - ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY); - ether_ifdetach(ifp); - if_detach(ifp); - -#ifdef DIAGNOSTIC - if (sc->sc_pipe_tx != NULL) - aprint_debug_dev(self, "detach has active tx endpoint.\n"); - if (sc->sc_pipe_rx != NULL) - aprint_debug_dev(self, "detach has active rx endpoint.\n"); - if (sc->sc_pipe_intr != NULL) - aprint_debug_dev(self, "detach has active intr endpoint.\n"); -#endif - sc->sc_attached = 0; - - splx(s); - - usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); - - mutex_destroy(&sc->sc_mii_lock); - - return 0; -} - #if 0 /* read memory */ -Static int +static int udav_mem_read(struct udav_softc *sc, int offset, void *buf, int len) { usb_device_request_t req; @@ -405,9 +281,9 @@ udav_mem_read(struct udav_softc *sc, int return 0; DPRINTFN(0x200, - ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); + ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - if (sc->sc_dying) + if (un->un_dying) return 0; offset &= 0xffff; @@ -419,20 +295,17 @@ udav_mem_read(struct udav_softc *sc, int USETW(req.wIndex, offset); USETW(req.wLength, len); - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, buf); - if (--sc->sc_refcnt < 0) - usb_detach_wakeupold(sc->sc_dev); + err = usbd_do_request(un->un_udev, &req, buf); if (err) { DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n", - device_xname(sc->sc_dev), __func__, offset, err)); + device_xname(un->un_dev), __func__, offset, err)); } return err; } /* write memory */ -Static int +static int udav_mem_write(struct udav_softc *sc, int offset, void *buf, int len) { usb_device_request_t req; @@ -442,9 +315,9 @@ udav_mem_write(struct udav_softc *sc, in return 0; DPRINTFN(0x200, - ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); + ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - if (sc->sc_dying) + if (un->un_dying) return 0; offset &= 0xffff; @@ -456,20 +329,17 @@ udav_mem_write(struct udav_softc *sc, in USETW(req.wIndex, offset); USETW(req.wLength, len); - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, buf); - if (--sc->sc_refcnt < 0) - usb_detach_wakeupold(sc->sc_dev); + err = usbd_do_request(un->un_udev, &req, buf); if (err) { DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n", - device_xname(sc->sc_dev), __func__, offset, err)); + device_xname(un->un_dev), __func__, offset, err)); } return err; } /* write memory */ -Static int +static int udav_mem_write1(struct udav_softc *sc, int offset, unsigned char ch) { usb_device_request_t req; @@ -479,9 +349,9 @@ udav_mem_write1(struct udav_softc *sc, i return 0; DPRINTFN(0x200, - ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); + ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - if (sc->sc_dying) + if (un->un_dying) return 0; offset &= 0xffff; @@ -492,13 +362,10 @@ udav_mem_write1(struct udav_softc *sc, i USETW(req.wIndex, offset); USETW(req.wLength, 0x0000); - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, NULL); - if (--sc->sc_refcnt < 0) - usb_detach_wakeupold(sc->sc_dev); + err = usbd_do_request(un->un_udev, &req, NULL); if (err) { DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n", - device_xname(sc->sc_dev), __func__, offset, err)); + device_xname(un->un_dev), __func__, offset, err)); } return err; @@ -506,20 +373,18 @@ udav_mem_write1(struct udav_softc *sc, i #endif /* read register(s) */ -Static int +static int udav_csr_read(struct udav_softc *sc, int offset, void *buf, int len) { + struct usbnet * const un = &sc->sc_un; usb_device_request_t req; usbd_status err; - if (sc == NULL) - return 0; + usbnet_isowned_mii(un); + KASSERT(!un->un_dying); DPRINTFN(0x200, - ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return 0; + ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); offset &= 0xff; len &= 0xff; @@ -530,33 +395,28 @@ udav_csr_read(struct udav_softc *sc, int USETW(req.wIndex, offset); USETW(req.wLength, len); - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, buf); - if (--sc->sc_refcnt < 0) - usb_detach_wakeupold(sc->sc_dev); + err = usbd_do_request(un->un_udev, &req, buf); if (err) { DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n", - device_xname(sc->sc_dev), __func__, offset, err)); + device_xname(un->un_dev), __func__, offset, err)); } return err; } /* write register(s) */ -Static int +static int udav_csr_write(struct udav_softc *sc, int offset, void *buf, int len) { + struct usbnet * const un = &sc->sc_un; usb_device_request_t req; usbd_status err; - if (sc == NULL) - return 0; + usbnet_isowned_mii(un); + KASSERT(!un->un_dying); DPRINTFN(0x200, - ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return 0; + ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); offset &= 0xff; len &= 0xff; @@ -567,50 +427,45 @@ udav_csr_write(struct udav_softc *sc, in USETW(req.wIndex, offset); USETW(req.wLength, len); - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, buf); - if (--sc->sc_refcnt < 0) - usb_detach_wakeupold(sc->sc_dev); + err = usbd_do_request(un->un_udev, &req, buf); if (err) { DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n", - device_xname(sc->sc_dev), __func__, offset, err)); + device_xname(un->un_dev), __func__, offset, err)); } return err; } -Static int +static int udav_csr_read1(struct udav_softc *sc, int offset) { + struct usbnet * const un = &sc->sc_un; uint8_t val = 0; - if (sc == NULL) - return 0; + usbnet_isowned_mii(un); DPRINTFN(0x200, - ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); + ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - if (sc->sc_dying) + if (un->un_dying) return 0; return udav_csr_read(sc, offset, &val, 1) ? 0 : val; } /* write a register */ -Static int +static int udav_csr_write1(struct udav_softc *sc, int offset, unsigned char ch) { + struct usbnet * const un = &sc->sc_un; usb_device_request_t req; usbd_status err; - if (sc == NULL) - return 0; + usbnet_isowned_mii(un); + KASSERT(!un->un_dying); DPRINTFN(0x200, - ("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return 0; + ("%s: %s: enter\n", device_xname(un->un_dev), __func__)); offset &= 0xff; @@ -620,35 +475,36 @@ udav_csr_write1(struct udav_softc *sc, i USETW(req.wIndex, offset); USETW(req.wLength, 0x0000); - sc->sc_refcnt++; - err = usbd_do_request(sc->sc_udev, &req, NULL); - if (--sc->sc_refcnt < 0) - usb_detach_wakeupold(sc->sc_dev); + err = usbd_do_request(un->un_udev, &req, NULL); if (err) { DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n", - device_xname(sc->sc_dev), __func__, offset, err)); + device_xname(un->un_dev), __func__, offset, err)); } return err; } -Static int -udav_init(struct ifnet *ifp) +static int +udav_init_locked(struct ifnet *ifp) { - struct udav_softc *sc = ifp->if_softc; - struct mii_data *mii = GET_MII(sc); + struct usbnet * const un = ifp->if_softc; + struct mii_data * const mii = usbnet_mii(un); + struct udav_softc *sc = usbnet_softc(un); uint8_t eaddr[ETHER_ADDR_LEN]; - int rc, s; + int rc; - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); + DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - if (sc->sc_dying) - return EIO; + usbnet_isowned(un); - s = splnet(); + if (un->un_dying) + return EIO; /* Cancel pending I/O and free all TX/RX buffers */ - udav_stop(ifp, 1); + if (ifp->if_flags & IFF_RUNNING) + usbnet_stop(un, ifp, 1); + + usbnet_lock_mii_un_locked(un); memcpy(eaddr, CLLADDR(ifp->if_sadl), sizeof(eaddr)); udav_csr_write(sc, UDAV_PAR, eaddr, ETHER_ADDR_LEN); @@ -667,7 +523,7 @@ udav_init(struct ifnet *ifp) UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC); /* Load the multicast filter */ - udav_setmulti(sc); + udav_setiff_locked(un); /* Enable RX */ UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_RXEN); @@ -676,62 +532,52 @@ udav_init(struct ifnet *ifp) UDAV_SETBIT(sc, UDAV_GPCR, UDAV_GPCR_GEP_CNTL0); UDAV_CLRBIT(sc, UDAV_GPR, UDAV_GPR_GEPIO0); - if ((rc = mii_mediachg(mii)) == ENXIO) - rc = 0; - else if (rc != 0) - goto out; - - if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) { - if (udav_openpipes(sc)) { - splx(s); - return EIO; - } - } + usbnet_unlock_mii_un_locked(un); - /* Initialize transmit ring */ - if (udav_tx_list_init(sc)) { - printf("%s: tx list init failed\n", device_xname(sc->sc_dev)); - splx(s); - return EIO; + rc = 0; + if (mii) { + if ((rc = mii_mediachg(mii)) == ENXIO) + rc = 0; } - /* Initialize receive ring */ - if (udav_rx_list_init(sc)) { - printf("%s: rx list init failed\n", device_xname(sc->sc_dev)); - splx(s); - return EIO; - } + if (rc != 0) + return rc; - /* Start up the receive pipe. */ - for (size_t i = 0; i < UDAV_RX_LIST_CNT; i++) { - struct udav_chain *c = &sc->sc_cdata.udav_rx_chain[i]; - usbd_setup_xfer(c->udav_xfer, c, c->udav_buf, UDAV_BUFSZ, - USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, udav_rxeof); - (void)usbd_transfer(c->udav_xfer); - DPRINTF(("%s: %s: start read\n", device_xname(sc->sc_dev), - __func__)); - } + return usbnet_init_rx_tx(un, 0, USBD_FORCE_SHORT_XFER); +} - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; +static int +udav_init(struct ifnet *ifp) +{ + struct usbnet * const un = ifp->if_softc; - callout_reset(&sc->sc_stat_ch, hz, udav_tick, sc); + usbnet_lock(un); + int ret = udav_init_locked(ifp); + usbnet_unlock(un); -out: - splx(s); - return rc; + return ret; } -Static void -udav_reset(struct udav_softc *sc) +static void +udav_reset(struct usbnet *un) { - int i; - - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); + usbnet_isowned(un); - if (sc->sc_dying) + if (un->un_dying) return; + DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); + + udav_chip_init(un); +} + +static void +udav_chip_init(struct usbnet *un) +{ + struct udav_softc * const sc = usbnet_softc(un); + + usbnet_lock_mii_un_locked(un); + /* Select PHY */ #if 1 /* @@ -749,29 +595,14 @@ udav_reset(struct udav_softc *sc) UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_RST); - for (i = 0; i < UDAV_TX_TIMEOUT; i++) { + for (int i = 0; i < UDAV_TX_TIMEOUT; i++) { if (!(udav_csr_read1(sc, UDAV_NCR) & UDAV_NCR_RST)) break; delay(10); /* XXX */ } delay(10000); /* XXX */ -} - -int -udav_activate(device_t self, enum devact act) -{ - struct udav_softc *sc = device_private(self); - DPRINTF(("%s: %s: enter, act=%d\n", device_xname(sc->sc_dev), - __func__, act)); - switch (act) { - case DVACT_DEACTIVATE: - if_deactivate(&sc->sc_ec.ec_if); - sc->sc_dying = 1; - return 0; - default: - return EOPNOTSUPP; - } + usbnet_unlock_mii_un_locked(un); } #define UDAV_BITS 6 @@ -779,22 +610,23 @@ udav_activate(device_t self, enum devact #define UDAV_CALCHASH(addr) \ (ether_crc32_le((addr), ETHER_ADDR_LEN) & ((1 << UDAV_BITS) - 1)) -Static void -udav_setmulti(struct udav_softc *sc) +static void +udav_setiff_locked(struct usbnet *un) { - struct ethercom *ec = &sc->sc_ec; - struct ifnet *ifp; + struct udav_softc *sc = usbnet_softc(un); + struct ethercom *ec = usbnet_ec(un); + struct ifnet * const ifp = usbnet_ifp(un); struct ether_multi *enm; struct ether_multistep step; uint8_t hashes[8]; int h = 0; - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); + DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - if (sc->sc_dying) - return; + usbnet_isowned_mii(un); - ifp = GET_IFP(sc); + if (un->un_dying) + return; if (ISSET(sc->sc_flags, UDAV_NO_PHY)) { UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL); @@ -842,661 +674,146 @@ allmulti: udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes)); } -Static int -udav_openpipes(struct udav_softc *sc) -{ - usbd_status err; - int error = 0; - - if (sc->sc_dying) - return EIO; - - sc->sc_refcnt++; - - /* Open RX pipe */ - err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no, - USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx); - if (err) { - printf("%s: open rx pipe failed: %s\n", - device_xname(sc->sc_dev), usbd_errstr(err)); - error = EIO; - goto done; - } - - /* Open TX pipe */ - err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no, - USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx); - if (err) { - printf("%s: open tx pipe failed: %s\n", - device_xname(sc->sc_dev), usbd_errstr(err)); - error = EIO; - goto done; - } - -#if 0 - /* XXX: interrupt endpoint is not yet supported */ - /* Open Interrupt pipe */ - err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no, - USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc, - &sc->sc_cdata.udav_ibuf, UDAV_INTR_PKGLEN, - udav_intr, USBD_DEFAULT_INTERVAL); - if (err) { - printf("%s: open intr pipe failed: %s\n", - device_xname(sc->sc_dev), usbd_errstr(err)); - error = EIO; - goto done; - } -#endif - done: - if (--sc->sc_refcnt < 0) - usb_detach_wakeupold(sc->sc_dev); - - return error; -} - -Static int -udav_newbuf(struct udav_softc *sc, struct udav_chain *c, struct mbuf *m) -{ - struct mbuf *m_new = NULL; - - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); - - if (m == NULL) { - MGETHDR(m_new, M_DONTWAIT, MT_DATA); - if (m_new == NULL) { - printf("%s: no memory for rx list " - "-- packet dropped!\n", device_xname(sc->sc_dev)); - return ENOBUFS; - } - MCLGET(m_new, M_DONTWAIT); - if (!(m_new->m_flags & M_EXT)) { - printf("%s: no memory for rx list " - "-- packet dropped!\n", device_xname(sc->sc_dev)); - m_freem(m_new); - return ENOBUFS; - } - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - } else { - m_new = m; - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; - m_new->m_data = m_new->m_ext.ext_buf; - } - - m_adj(m_new, ETHER_ALIGN); - c->udav_mbuf = m_new; - - return 0; -} - - -Static int -udav_rx_list_init(struct udav_softc *sc) +static void +udav_setiff(struct usbnet *un) { - struct udav_cdata *cd; - struct udav_chain *c; - int i; - - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); - - cd = &sc->sc_cdata; - for (i = 0; i < UDAV_RX_LIST_CNT; i++) { - c = &cd->udav_rx_chain[i]; - c->udav_sc = sc; - if (udav_newbuf(sc, c, NULL) == ENOBUFS) - return ENOBUFS; - if (c->udav_xfer == NULL) { - int error = usbd_create_xfer(sc->sc_pipe_rx, - UDAV_BUFSZ, 0, 0, &c->udav_xfer); - if (error) - return error; - c->udav_buf = usbd_get_buffer(c->udav_xfer); - } - } - - return 0; + usbnet_lock_mii(un); + udav_setiff_locked(un); + usbnet_unlock_mii(un); } -Static int -udav_tx_list_init(struct udav_softc *sc) -{ - struct udav_cdata *cd; - struct udav_chain *c; - int i; - - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); - - cd = &sc->sc_cdata; - for (i = 0; i < UDAV_TX_LIST_CNT; i++) { - c = &cd->udav_tx_chain[i]; - c->udav_sc = sc; - c->udav_mbuf = NULL; - if (c->udav_xfer == NULL) { - int error = usbd_create_xfer(sc->sc_pipe_tx, UDAV_BUFSZ, - USBD_FORCE_SHORT_XFER, 0, &c->udav_xfer); - if (error) - return error; - c->udav_buf = usbd_get_buffer(c->udav_xfer); - } - } - - return 0; -} -Static void -udav_start(struct ifnet *ifp) -{ - struct udav_softc *sc = ifp->if_softc; - struct mbuf *m_head = NULL; - - DPRINTF(("%s: %s: enter, link=%d\n", device_xname(sc->sc_dev), - __func__, sc->sc_link)); - - if (sc->sc_dying) - return; - - if (!sc->sc_link) - return; - - if (ifp->if_flags & IFF_OACTIVE) - return; - - IFQ_POLL(&ifp->if_snd, m_head); - if (m_head == NULL) - return; - - if (udav_send(sc, m_head, 0)) { - ifp->if_flags |= IFF_OACTIVE; - return; - } - - IFQ_DEQUEUE(&ifp->if_snd, m_head); - - bpf_mtap(ifp, m_head, BPF_D_OUT); - - ifp->if_flags |= IFF_OACTIVE; - - /* Set a timeout in case the chip goes out to lunch. */ - ifp->if_timer = 5; -} - -Static int -udav_send(struct udav_softc *sc, struct mbuf *m, int idx) +static unsigned +udav_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c) { int total_len; - struct udav_chain *c; - usbd_status err; + uint8_t *buf = c->unc_buf; - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev),__func__)); + usbnet_isowned_tx(un); - c = &sc->sc_cdata.udav_tx_chain[idx]; + DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); + + if (m->m_pkthdr.len > UDAV_BUFSZ - 2) + return 0; /* Copy the mbuf data into a contiguous buffer */ - /* first 2 bytes are packet length */ - m_copydata(m, 0, m->m_pkthdr.len, c->udav_buf + 2); - c->udav_mbuf = m; + m_copydata(m, 0, m->m_pkthdr.len, buf + 2); total_len = m->m_pkthdr.len; if (total_len < UDAV_MIN_FRAME_LEN) { - memset(c->udav_buf + 2 + total_len, 0, + memset(buf + 2 + total_len, 0, UDAV_MIN_FRAME_LEN - total_len); total_len = UDAV_MIN_FRAME_LEN; } /* Frame length is specified in the first 2bytes of the buffer */ - c->udav_buf[0] = (uint8_t)total_len; - c->udav_buf[1] = (uint8_t)(total_len >> 8); + buf[0] = (uint8_t)total_len; + buf[1] = (uint8_t)(total_len >> 8); total_len += 2; - usbd_setup_xfer(c->udav_xfer, c, c->udav_buf, total_len, - USBD_FORCE_SHORT_XFER, UDAV_TX_TIMEOUT, udav_txeof); - - /* Transmit */ - sc->sc_refcnt++; - err = usbd_transfer(c->udav_xfer); - if (--sc->sc_refcnt < 0) - usb_detach_wakeupold(sc->sc_dev); - if (err != USBD_IN_PROGRESS) { - printf("%s: udav_send error=%s\n", device_xname(sc->sc_dev), - usbd_errstr(err)); - /* Stop the interface */ - usb_add_task(sc->sc_udev, &sc->sc_stop_task, - USB_TASKQ_DRIVER); - return EIO; - } - - DPRINTF(("%s: %s: send %d bytes\n", device_xname(sc->sc_dev), - __func__, total_len)); - - sc->sc_cdata.udav_tx_cnt++; - - return 0; -} - -Static void -udav_txeof(struct usbd_xfer *xfer, void *priv, - usbd_status status) -{ - struct udav_chain *c = priv; - struct udav_softc *sc = c->udav_sc; - struct ifnet *ifp = GET_IFP(sc); - int s; - - if (sc->sc_dying) - return; - - s = splnet(); - - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); - - ifp->if_timer = 0; - ifp->if_flags &= ~IFF_OACTIVE; - - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { - splx(s); - return; - } - ifp->if_oerrors++; - printf("%s: usb error on tx: %s\n", device_xname(sc->sc_dev), - usbd_errstr(status)); - if (status == USBD_STALLED) { - sc->sc_refcnt++; - usbd_clear_endpoint_stall_async(sc->sc_pipe_tx); - if (--sc->sc_refcnt < 0) - usb_detach_wakeupold(sc->sc_dev); - } - splx(s); - return; - } + DPRINTF(("%s: %s: send %d bytes\n", device_xname(un->un_dev), + __func__, total_len)); - ifp->if_opackets++; - - m_freem(c->udav_mbuf); - c->udav_mbuf = NULL; - - if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) - udav_start(ifp); - - splx(s); + return total_len; } -Static void -udav_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) +static void +udav_rxeof_loop(struct usbnet *un, struct usbd_xfer *xfer, + struct usbnet_chain *c, uint32_t total_len) { - struct udav_chain *c = priv; - struct udav_softc *sc = c->udav_sc; - struct ifnet *ifp = GET_IFP(sc); - struct mbuf *m; - uint32_t total_len; - uint8_t *pktstat; - int s; - - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev),__func__)); - - if (sc->sc_dying) - return; + struct ifnet *ifp = usbnet_ifp(un); + uint8_t *buf = c->unc_buf; + uint16_t pkt_len; + uint8_t pktstat; - if (status != USBD_NORMAL_COMPLETION) { - if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) - return; - sc->sc_rx_errs++; - if (usbd_ratecheck(&sc->sc_rx_notice)) { - printf("%s: %u usb errors on rx: %s\n", - device_xname(sc->sc_dev), sc->sc_rx_errs, - usbd_errstr(status)); - sc->sc_rx_errs = 0; - } - if (status == USBD_STALLED) { - sc->sc_refcnt++; - usbd_clear_endpoint_stall_async(sc->sc_pipe_rx); - if (--sc->sc_refcnt < 0) - usb_detach_wakeupold(sc->sc_dev); - } - goto done; - } + DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); + /* first byte in received data */ + pktstat = *buf; + total_len -= sizeof(pktstat); + buf += sizeof(pktstat); - /* copy data to mbuf */ - m = c->udav_mbuf; - memcpy(mtod(m, char *), c->udav_buf, total_len); + DPRINTF(("%s: RX Status: 0x%02x\n", device_xname(un->un_dev), pktstat)); - /* first byte in received data */ - pktstat = mtod(m, uint8_t *); - m_adj(m, sizeof(uint8_t)); - DPRINTF(("%s: RX Status: 0x%02x\n", device_xname(sc->sc_dev), - *pktstat)); + pkt_len = UGETW(buf); + total_len -= sizeof(pkt_len); + buf += sizeof(pkt_len); - total_len = UGETW(mtod(m, uint8_t *)); - m_adj(m, sizeof(uint16_t)); + DPRINTF(("%s: RX Length: 0x%02x\n", device_xname(un->un_dev), pkt_len)); - if (*pktstat & UDAV_RSR_LCS) { + if (pktstat & UDAV_RSR_LCS) { ifp->if_collisions++; - goto done; - } - - if (total_len < sizeof(struct ether_header) || - *pktstat & UDAV_RSR_ERR) { - ifp->if_ierrors++; - goto done; + return; } - total_len -= ETHER_CRC_LEN; - - m->m_pkthdr.len = m->m_len = total_len; - m_set_rcvif(m, ifp); - - s = splnet(); - - if (udav_newbuf(sc, c, NULL) == ENOBUFS) { + if (pkt_len < sizeof(struct ether_header) || + pkt_len > total_len || + (pktstat & UDAV_RSR_ERR)) { ifp->if_ierrors++; - goto done1; + return; } - DPRINTF(("%s: %s: deliver %d\n", device_xname(sc->sc_dev), - __func__, m->m_len)); - if_percpuq_enqueue((ifp)->if_percpuq, (m)); - - done1: - splx(s); - - done: - /* Setup new transfer */ - usbd_setup_xfer(xfer, c, c->udav_buf, UDAV_BUFSZ, USBD_SHORT_XFER_OK, - USBD_NO_TIMEOUT, udav_rxeof); - sc->sc_refcnt++; - usbd_transfer(xfer); - if (--sc->sc_refcnt < 0) - usb_detach_wakeupold(sc->sc_dev); + pkt_len -= ETHER_CRC_LEN; - DPRINTF(("%s: %s: start rx\n", device_xname(sc->sc_dev), __func__)); -} + DPRINTF(("%s: Rx deliver: 0x%02x\n", device_xname(un->un_dev), pkt_len)); -#if 0 -Static void udav_intr(void) -{ + usbnet_enqueue(un, buf, pkt_len, 0, 0, 0); } -#endif -Static int -udav_ioctl(struct ifnet *ifp, u_long cmd, void *data) +static int +udav_ioctl_cb(struct ifnet *ifp, u_long cmd, void *data) { - struct udav_softc *sc = ifp->if_softc; - int s, error = 0; - - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); + struct usbnet * const un = ifp->if_softc; - if (sc->sc_dying) - return EIO; - - s = splnet(); - - error = ether_ioctl(ifp, cmd, data); - if (error == ENETRESET) { - if (ifp->if_flags & IFF_RUNNING) - udav_setmulti(sc); - error = 0; + switch (cmd) { + case SIOCADDMULTI: + case SIOCDELMULTI: + udav_setiff(un); + break; + default: + break; } - splx(s); - - return error; -} - -Static void -udav_watchdog(struct ifnet *ifp) -{ - struct udav_softc *sc = ifp->if_softc; - struct udav_chain *c; - usbd_status stat; - int s; - - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); - - ifp->if_oerrors++; - printf("%s: watchdog timeout\n", device_xname(sc->sc_dev)); - s = splusb(); - c = &sc->sc_cdata.udav_tx_chain[0]; - usbd_get_xfer_status(c->udav_xfer, NULL, NULL, NULL, &stat); - udav_txeof(c->udav_xfer, c, stat); - - if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) - udav_start(ifp); - splx(s); -} - -Static void -udav_stop_task(struct udav_softc *sc) -{ - udav_stop(GET_IFP(sc), 1); + return 0; } /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */ -Static void -udav_stop(struct ifnet *ifp, int disable) +static void +udav_stop_cb(struct ifnet *ifp, int disable) { - struct udav_softc *sc = ifp->if_softc; - usbd_status err; - int i; - - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); - - ifp->if_timer = 0; - - udav_reset(sc); + struct usbnet * const un = ifp->if_softc; - callout_stop(&sc->sc_stat_ch); + DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__)); - /* Stop transfers */ - /* RX endpoint */ - if (sc->sc_pipe_rx != NULL) { - err = usbd_abort_pipe(sc->sc_pipe_rx); - if (err) - printf("%s: abort rx pipe failed: %s\n", - device_xname(sc->sc_dev), usbd_errstr(err)); - } - - /* TX endpoint */ - if (sc->sc_pipe_tx != NULL) { - err = usbd_abort_pipe(sc->sc_pipe_tx); - if (err) - printf("%s: abort tx pipe failed: %s\n", - device_xname(sc->sc_dev), usbd_errstr(err)); - } - -#if 0 - /* XXX: Interrupt endpoint is not yet supported!! */ - /* Interrupt endpoint */ - if (sc->sc_pipe_intr != NULL) { - err = usbd_abort_pipe(sc->sc_pipe_intr); - if (err) - printf("%s: abort intr pipe failed: %s\n", - device_xname(sc->sc_dev), usbd_errstr(err)); - err = usbd_close_pipe(sc->sc_pipe_intr); - if (err) - printf("%s: close intr pipe failed: %s\n", - device_xname(sc->sc_dev), usbd_errstr(err)); - sc->sc_pipe_intr = NULL; - } -#endif - - /* Free RX resources. */ - for (i = 0; i < UDAV_RX_LIST_CNT; i++) { - if (sc->sc_cdata.udav_rx_chain[i].udav_mbuf != NULL) { - m_freem(sc->sc_cdata.udav_rx_chain[i].udav_mbuf); - sc->sc_cdata.udav_rx_chain[i].udav_mbuf = NULL; - } - if (sc->sc_cdata.udav_rx_chain[i].udav_xfer != NULL) { - usbd_destroy_xfer(sc->sc_cdata.udav_rx_chain[i].udav_xfer); - sc->sc_cdata.udav_rx_chain[i].udav_xfer = NULL; - } - } - - /* Free TX resources. */ - for (i = 0; i < UDAV_TX_LIST_CNT; i++) { - if (sc->sc_cdata.udav_tx_chain[i].udav_mbuf != NULL) { - m_freem(sc->sc_cdata.udav_tx_chain[i].udav_mbuf); - sc->sc_cdata.udav_tx_chain[i].udav_mbuf = NULL; - } - if (sc->sc_cdata.udav_tx_chain[i].udav_xfer != NULL) { - usbd_destroy_xfer(sc->sc_cdata.udav_tx_chain[i].udav_xfer); - sc->sc_cdata.udav_tx_chain[i].udav_xfer = NULL; - } - } - - /* Close pipes */ - /* RX endpoint */ - if (sc->sc_pipe_rx != NULL) { - err = usbd_close_pipe(sc->sc_pipe_rx); - if (err) - printf("%s: close rx pipe failed: %s\n", - device_xname(sc->sc_dev), usbd_errstr(err)); - sc->sc_pipe_rx = NULL; - } - - /* TX endpoint */ - if (sc->sc_pipe_tx != NULL) { - err = usbd_close_pipe(sc->sc_pipe_tx); - if (err) - printf("%s: close tx pipe failed: %s\n", - device_xname(sc->sc_dev), usbd_errstr(err)); - sc->sc_pipe_tx = NULL; - } - - if (!ISSET(sc->sc_flags, UDAV_NO_PHY)) - sc->sc_link = 0; - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + udav_reset(un); } -/* Set media options */ -Static int -udav_ifmedia_change(struct ifnet *ifp) +static usbd_status +udav_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val) { - struct udav_softc *sc = ifp->if_softc; - - DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__)); - - if (sc->sc_dying) - return 0; - - return ether_mediachange(ifp); -} - -Static void -udav_tick(void *xsc) -{ - struct udav_softc *sc = xsc; - - if (sc == NULL) - return; - - DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev), - __func__)); - - if (sc->sc_dying) - return; - - /* Perform periodic stuff in process context */ - usb_add_task(sc->sc_udev, &sc->sc_tick_task, - USB_TASKQ_DRIVER); -} - -Static void -udav_tick_task(void *xsc) -{ - struct udav_softc *sc = xsc; - struct ifnet *ifp; - struct mii_data *mii; - int s; - - if (sc == NULL) - return; - - DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev), - __func__)); - - if (sc->sc_dying) - return; - - ifp = GET_IFP(sc); - mii = GET_MII(sc); - - if (mii == NULL) - return; - - s = splnet(); - - mii_tick(mii); - if (!sc->sc_link) { - mii_pollstat(mii); - if (mii->mii_media_status & IFM_ACTIVE && - IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { - DPRINTF(("%s: %s: got link\n", - device_xname(sc->sc_dev), __func__)); - sc->sc_link++; - if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) - udav_start(ifp); - } - } - - callout_reset(&sc->sc_stat_ch, hz, udav_tick, sc); - - splx(s); -} - -/* Get exclusive access to the MII registers */ -Static void -udav_lock_mii(struct udav_softc *sc) -{ - DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev), - __func__)); - - sc->sc_refcnt++; - mutex_enter(&sc->sc_mii_lock); -} - -Static void -udav_unlock_mii(struct udav_softc *sc) -{ - DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev), - __func__)); - - mutex_exit(&sc->sc_mii_lock); - if (--sc->sc_refcnt < 0) - usb_detach_wakeupold(sc->sc_dev); -} - -Static int -udav_miibus_readreg(device_t dev, int phy, int reg, uint16_t *val) -{ - struct udav_softc *sc; + struct udav_softc *sc = usbnet_softc(un); uint8_t data[2]; - if (dev == NULL) - return -1; - - sc = device_private(dev); + usbnet_isowned_mii(un); DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n", - device_xname(sc->sc_dev), __func__, phy, reg)); + device_xname(un->un_dev), __func__, phy, reg)); - if (sc->sc_dying) { + if (un->un_dying) { #ifdef DIAGNOSTIC - printf("%s: %s: dying\n", device_xname(sc->sc_dev), + printf("%s: %s: dying\n", device_xname(un->un_dev), __func__); #endif - return -1; + return USBD_INVAL; } /* XXX: one PHY only for the internal PHY */ if (phy != 0) { DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", - device_xname(sc->sc_dev), __func__, phy)); - return -1; + device_xname(un->un_dev), __func__, phy)); + return USBD_INVAL; } - udav_lock_mii(sc); - /* select internal PHY and set PHY register address */ udav_csr_write1(sc, UDAV_EPAR, UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK)); @@ -1512,33 +829,28 @@ udav_miibus_readreg(device_t dev, int ph /* retrieve the result from data registers */ udav_csr_read(sc, UDAV_EPDRL, data, 2); - udav_unlock_mii(sc); - *val = data[0] | (data[1] << 8); DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04hx\n", - device_xname(sc->sc_dev), __func__, phy, reg, *val)); + device_xname(un->un_dev), __func__, phy, reg, *val)); - return 0; + return USBD_NORMAL_COMPLETION; } -Static int -udav_miibus_writereg(device_t dev, int phy, int reg, uint16_t val) +static usbd_status +udav_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val) { - struct udav_softc *sc; + struct udav_softc *sc = usbnet_softc(un); uint8_t data[2]; - if (dev == NULL) - return -1; - - sc = device_private(dev); + usbnet_isowned_mii(un); DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x val=0x%04hx\n", - device_xname(sc->sc_dev), __func__, phy, reg, val)); + device_xname(un->un_dev), __func__, phy, reg, val)); - if (sc->sc_dying) { + if (un->un_dying) { #ifdef DIAGNOSTIC - printf("%s: %s: dying\n", device_xname(sc->sc_dev), + printf("%s: %s: dying\n", device_xname(un->un_dev), __func__); #endif return -1; @@ -1547,12 +859,10 @@ udav_miibus_writereg(device_t dev, int p /* XXX: one PHY only for the internal PHY */ if (phy != 0) { DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n", - device_xname(sc->sc_dev), __func__, phy)); + device_xname(un->un_dev), __func__, phy)); return -1; } - udav_lock_mii(sc); - /* select internal PHY and set PHY register address */ udav_csr_write1(sc, UDAV_EPAR, UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK)); @@ -1570,20 +880,54 @@ udav_miibus_writereg(device_t dev, int p /* end write command */ UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRW); - udav_unlock_mii(sc); - - return 0; + return USBD_NORMAL_COMPLETION; } -Static void -udav_miibus_statchg(struct ifnet *ifp) +static void +udav_mii_statchg(struct ifnet *ifp) { -#ifdef UDAV_DEBUG + struct usbnet * const un = ifp->if_softc; + struct mii_data * const mii = usbnet_mii(un); - if (ifp == NULL) + DPRINTF(("%s: %s: enter\n", ifp->if_xname, __func__)); + + if (un->un_dying) return; - DPRINTF(("%s: %s: enter\n", ifp->if_xname, __func__)); + un->un_link = false; + if (mii->mii_media_status & IFM_ACTIVE && + IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { + DPRINTF(("%s: %s: got link\n", + device_xname(un->un_dev), __func__)); + un->un_link = true; + } +} + +MODULE(MODULE_CLASS_DRIVER, if_udav, "usbnet"); + +#ifdef _MODULE +#include "ioconf.c" #endif - /* Nothing to do */ + +static int +if_udav_modcmd(modcmd_t cmd, void *aux) +{ + int error = 0; + + switch (cmd) { + case MODULE_CMD_INIT: +#ifdef _MODULE + error = config_init_component(cfdriver_ioconf_udav, + cfattach_ioconf_udav, cfdata_ioconf_udav); +#endif + return error; + case MODULE_CMD_FINI: +#ifdef _MODULE + error = config_fini_component(cfdriver_ioconf_udav, + cfattach_ioconf_udav, cfdata_ioconf_udav); +#endif + return error; + default: + return ENOTTY; + } } Index: src/sys/dev/usb/if_udavreg.h diff -u src/sys/dev/usb/if_udavreg.h:1.14 src/sys/dev/usb/if_udavreg.h:1.15 --- src/sys/dev/usb/if_udavreg.h:1.14 Thu Aug 1 00:10:22 2019 +++ src/sys/dev/usb/if_udavreg.h Wed Aug 7 19:21:48 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: if_udavreg.h,v 1.14 2019/08/01 00:10:22 mrg Exp $ */ +/* $NetBSD: if_udavreg.h,v 1.15 2019/08/07 19:21:48 skrll Exp $ */ /* $nabe: if_udavreg.h,v 1.2 2003/08/21 16:26:40 nabe Exp $ */ /* * Copyright (c) 2003 @@ -140,61 +140,3 @@ #define UDAV_GPR_GEPIO2 (1<<2) /* General purpose 2 */ #define UDAV_GPR_GEPIO1 (1<<1) /* General purpose 1 */ #define UDAV_GPR_GEPIO0 (1<<0) /* General purpose 0 */ - -#define GET_IFP(sc) (&(sc)->sc_ec.ec_if) -#define GET_MII(sc) (&(sc)->sc_mii) - -struct udav_chain { - struct udav_softc *udav_sc; - struct usbd_xfer *udav_xfer; - char *udav_buf; - struct mbuf *udav_mbuf; -}; - -struct udav_cdata { - struct udav_chain udav_tx_chain[UDAV_TX_LIST_CNT]; - struct udav_chain udav_rx_chain[UDAV_TX_LIST_CNT]; -#if 0 - /* XXX: Interrupt Endpoint is not yet supported! */ - struct udav_intrpkg udav_ibuf; -#endif - int udav_tx_prod; - int udav_tx_cnt; -}; - -struct udav_softc { - device_t sc_dev; /* base device */ - struct usbd_device * sc_udev; - - /* USB */ - struct usbd_interface * sc_ctl_iface; - /* int sc_ctl_iface_no; */ - int sc_bulkin_no; /* bulk in endpoint */ - int sc_bulkout_no; /* bulk out endpoint */ - int sc_intrin_no; /* intr in endpoint */ - struct usbd_pipe * sc_pipe_rx; - struct usbd_pipe * sc_pipe_tx; - struct usbd_pipe * sc_pipe_intr; - struct callout sc_stat_ch; - u_int sc_rx_errs; - /* u_int sc_intr_errs; */ - struct timeval sc_rx_notice; - - /* Ethernet */ - struct ethercom sc_ec; /* ethernet common */ - struct mii_data sc_mii; - kmutex_t sc_mii_lock; - int sc_link; -#define sc_media udav_mii.mii_media - krndsource_t rnd_source; - struct udav_cdata sc_cdata; - - int sc_attached; - int sc_dying; - int sc_refcnt; - - struct usb_task sc_tick_task; - struct usb_task sc_stop_task; - - uint16_t sc_flags; -};