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;
-};