Module Name: src
Committed By: skrll
Date: Wed Aug 7 07:05:54 UTC 2019
Modified Files:
src/sys/dev/usb: if_smsc.c
Removed Files:
src/sys/dev/usb: if_smscvar.h
Log Message:
Convert smsc(4) to usbnet
To generate a diff of this commit:
cvs rdiff -u -r1.46 -r1.47 src/sys/dev/usb/if_smsc.c
cvs rdiff -u -r1.8 -r0 src/sys/dev/usb/if_smscvar.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/if_smsc.c
diff -u src/sys/dev/usb/if_smsc.c:1.46 src/sys/dev/usb/if_smsc.c:1.47
--- src/sys/dev/usb/if_smsc.c:1.46 Thu Aug 1 00:10:22 2019
+++ src/sys/dev/usb/if_smsc.c Wed Aug 7 07:05:54 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: if_smsc.c,v 1.46 2019/08/01 00:10:22 mrg Exp $ */
+/* $NetBSD: if_smsc.c,v 1.47 2019/08/07 07:05:54 skrll Exp $ */
/* $OpenBSD: if_smsc.c,v 1.4 2012/09/27 12:38:11 jsg Exp $ */
/* $FreeBSD: src/sys/dev/usb/net/if_smsc.c,v 1.1 2012/08/15 04:03:55 gonzo Exp $ */
@@ -61,48 +61,18 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_smsc.c,v 1.46 2019/08/01 00:10:22 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_smsc.c,v 1.47 2019/08/07 07:05:54 skrll Exp $");
#ifdef _KERNEL_OPT
#include "opt_usb.h"
-#include "opt_inet.h"
#endif
#include <sys/param.h>
-#include <sys/bus.h>
-#include <sys/device.h>
-#include <sys/kernel.h>
-#include <sys/mbuf.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/rndsource.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/systm.h>
-
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-#include <net/if_ether.h>
-
-#include <net/bpf.h>
-
-#ifdef INET
-#include <netinet/in.h>
-#include <netinet/if_inarp.h>
-#endif
-
-#include <dev/mii/mii.h>
-#include <dev/mii/miivar.h>
+#include <sys/module.h>
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usbdivar.h>
-#include <dev/usb/usbdevs.h>
+#include <dev/usb/usbnet.h>
#include <dev/usb/if_smscreg.h>
-#include <dev/usb/if_smscvar.h>
#include "ioconf.h"
@@ -110,6 +80,22 @@ __KERNEL_RCSID(0, "$NetBSD: if_smsc.c,v
int smsc_debug = 0;
#endif
+struct smsc_softc {
+ struct usbnet smsc_un;
+
+ /*
+ * The following stores the settings in the mac control (MAC_CSR)
+ * register
+ */
+ uint32_t sc_mac_csr;
+ uint32_t sc_rev_id;
+
+ uint32_t sc_coe_ctrl;
+};
+
+#define SMSC_MIN_BUFSZ 2048
+#define SMSC_MAX_BUFSZ 18944
+
/*
* Various supported device vendors/products.
*/
@@ -135,84 +121,71 @@ static const struct usb_devno smsc_devs[
};
#ifdef USB_DEBUG
-#define smsc_dbg_printf(sc, fmt, args...) \
+#define smsc_dbg_printf(un, fmt, args...) \
do { \
if (smsc_debug > 0) \
printf("debug: " fmt, ##args); \
} while(0)
#else
-#define smsc_dbg_printf(sc, fmt, args...)
+#define smsc_dbg_printf(un, fmt, args...)
#endif
-#define smsc_warn_printf(sc, fmt, args...) \
- printf("%s: warning: " fmt, device_xname((sc)->sc_dev), ##args)
+#define smsc_warn_printf(un, fmt, args...) \
+ printf("%s: warning: " fmt, device_xname((un)->un_dev), ##args)
-#define smsc_err_printf(sc, fmt, args...) \
- printf("%s: error: " fmt, device_xname((sc)->sc_dev), ##args)
+#define smsc_err_printf(un, fmt, args...) \
+ printf("%s: error: " fmt, device_xname((un)->un_dev), ##args)
/* Function declarations */
-int smsc_chip_init(struct smsc_softc *);
-void smsc_setmulti(struct smsc_softc *);
-int smsc_setmacaddress(struct smsc_softc *, const uint8_t *);
-
int smsc_match(device_t, cfdata_t, void *);
void smsc_attach(device_t, device_t, void *);
-int smsc_detach(device_t, int);
-int smsc_activate(device_t, enum devact);
+
+CFATTACH_DECL_NEW(usmsc, sizeof(struct smsc_softc),
+ smsc_match, smsc_attach, usbnet_detach, usbnet_activate);
+
+int smsc_chip_init(struct usbnet *);
+int smsc_setmacaddress(struct usbnet *, const uint8_t *);
int smsc_init(struct ifnet *);
int smsc_init_locked(struct ifnet *);
-void smsc_start(struct ifnet *);
-void smsc_start_locked(struct ifnet *);
int smsc_ioctl(struct ifnet *, u_long, void *);
-void smsc_stop(struct ifnet *, int);
-void smsc_stop_locked(struct ifnet *, int);
+void smsc_stop_cb(struct ifnet *, int);
void smsc_reset(struct smsc_softc *);
-struct mbuf *smsc_newbuf(void);
-
-void smsc_tick(void *);
-void smsc_tick_task(void *);
-void smsc_miibus_statchg(struct ifnet *);
-void smsc_miibus_statchg_locked(struct ifnet *);
-int smsc_miibus_readreg(device_t, int, int, uint16_t *);
-int smsc_miibus_writereg(device_t, int, int, uint16_t);
-int smsc_ifmedia_upd(struct ifnet *);
-void smsc_lock_mii(struct smsc_softc *);
-void smsc_unlock_mii(struct smsc_softc *);
-
-int smsc_tx_list_init(struct smsc_softc *);
-void smsc_tx_list_free(struct smsc_softc *);
-int smsc_rx_list_init(struct smsc_softc *);
-void smsc_rx_list_free(struct smsc_softc *);
-int smsc_encap(struct smsc_softc *, struct mbuf *, int);
-void smsc_rxeof(struct usbd_xfer *, void *, usbd_status);
-void smsc_txeof(struct usbd_xfer *, void *, usbd_status);
-
-int smsc_read_reg(struct smsc_softc *, uint32_t, uint32_t *);
-int smsc_write_reg(struct smsc_softc *, uint32_t, uint32_t);
-int smsc_wait_for_bits(struct smsc_softc *, uint32_t, uint32_t);
-int smsc_sethwcsum(struct smsc_softc *);
-CFATTACH_DECL_NEW(usmsc, sizeof(struct smsc_softc), smsc_match, smsc_attach,
- smsc_detach, smsc_activate);
+static void smsc_miibus_statchg(struct ifnet *);
+int smsc_readreg(struct usbnet *, uint32_t, uint32_t *);
+int smsc_writereg(struct usbnet *, uint32_t, uint32_t);
+int smsc_wait_for_bits(struct usbnet *, uint32_t, uint32_t);
+usbd_status smsc_miibus_readreg(struct usbnet *, int, int, uint16_t *);
+usbd_status smsc_miibus_writereg(struct usbnet *, int, int, uint16_t);
+
+static unsigned smsc_tx_prepare(struct usbnet *, struct mbuf *,
+ struct usbnet_chain *);
+static void smsc_rxeof_loop(struct usbnet *, struct usbd_xfer *,
+ struct usbnet_chain *, uint32_t);
int
-smsc_read_reg(struct smsc_softc *sc, uint32_t off, uint32_t *data)
+smsc_readreg(struct usbnet *un, uint32_t off, uint32_t *data)
{
usb_device_request_t req;
uint32_t buf;
usbd_status err;
+ usbnet_isowned_mii(un);
+
+ if (un->un_dying)
+ return 0;
+
req.bmRequestType = UT_READ_VENDOR_DEVICE;
req.bRequest = SMSC_UR_READ_REG;
USETW(req.wValue, 0);
USETW(req.wIndex, off);
USETW(req.wLength, 4);
- err = usbd_do_request(sc->sc_udev, &req, &buf);
+ err = usbd_do_request(un->un_udev, &req, &buf);
if (err != 0)
- smsc_warn_printf(sc, "Failed to read register 0x%0x\n", off);
+ smsc_warn_printf(un, "Failed to read register 0x%0x\n", off);
*data = le32toh(buf);
@@ -220,12 +193,17 @@ smsc_read_reg(struct smsc_softc *sc, uin
}
int
-smsc_write_reg(struct smsc_softc *sc, uint32_t off, uint32_t data)
+smsc_writereg(struct usbnet *un, uint32_t off, uint32_t data)
{
usb_device_request_t req;
uint32_t buf;
usbd_status err;
+ usbnet_isowned_mii(un);
+
+ if (un->un_dying)
+ return 0;
+
buf = htole32(data);
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
@@ -234,21 +212,21 @@ smsc_write_reg(struct smsc_softc *sc, ui
USETW(req.wIndex, off);
USETW(req.wLength, 4);
- err = usbd_do_request(sc->sc_udev, &req, &buf);
+ err = usbd_do_request(un->un_udev, &req, &buf);
if (err != 0)
- smsc_warn_printf(sc, "Failed to write register 0x%0x\n", off);
+ smsc_warn_printf(un, "Failed to write register 0x%0x\n", off);
return err;
}
int
-smsc_wait_for_bits(struct smsc_softc *sc, uint32_t reg, uint32_t bits)
+smsc_wait_for_bits(struct usbnet *un, uint32_t reg, uint32_t bits)
{
uint32_t val;
int err, i;
for (i = 0; i < 100; i++) {
- if ((err = smsc_read_reg(sc, reg, &val)) != 0)
+ if ((err = smsc_readreg(un, reg, &val)) != 0)
return err;
if (!(val & bits))
return 0;
@@ -258,62 +236,58 @@ smsc_wait_for_bits(struct smsc_softc *sc
return 1;
}
-int
-smsc_miibus_readreg(device_t dev, int phy, int reg, uint16_t *val)
+usbd_status
+smsc_miibus_readreg(struct usbnet *un, int phy, int reg, uint16_t *val)
{
- struct smsc_softc * const sc = device_private(dev);
uint32_t addr;
uint32_t data = 0;
int rv = 0;
- smsc_lock_mii(sc);
- if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) {
- smsc_warn_printf(sc, "MII is busy\n");
+ usbnet_isowned_mii(un);
+
+ if (smsc_wait_for_bits(un, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) {
+ smsc_warn_printf(un, "MII is busy\n");
rv = -1;
goto done;
}
addr = (phy << 11) | (reg << 6) | SMSC_MII_READ;
- smsc_write_reg(sc, SMSC_MII_ADDR, addr);
+ smsc_writereg(un, SMSC_MII_ADDR, addr);
- if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) {
- smsc_warn_printf(sc, "MII read timeout\n");
+ if (smsc_wait_for_bits(un, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) {
+ smsc_warn_printf(un, "MII read timeout\n");
rv = ETIMEDOUT;
}
- smsc_read_reg(sc, SMSC_MII_DATA, &data);
+ smsc_readreg(un, SMSC_MII_DATA, &data);
done:
- smsc_unlock_mii(sc);
-
*val = data & 0xffff;
return rv;
}
-int
-smsc_miibus_writereg(device_t dev, int phy, int reg, uint16_t val)
+usbd_status
+smsc_miibus_writereg(struct usbnet *un, int phy, int reg, uint16_t val)
{
- struct smsc_softc * const sc = device_private(dev);
uint32_t addr;
- if (sc->sc_phyno != phy)
+ usbnet_isowned_mii(un);
+
+ if (un->un_phyno != phy)
return -1;
- smsc_lock_mii(sc);
- if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) {
- smsc_warn_printf(sc, "MII is busy\n");
- smsc_unlock_mii(sc);
+ if (smsc_wait_for_bits(un, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) {
+ smsc_warn_printf(un, "MII is busy\n");
return -1;
}
- smsc_write_reg(sc, SMSC_MII_DATA, val);
+ smsc_writereg(un, SMSC_MII_DATA, val);
addr = (phy << 11) | (reg << 6) | SMSC_MII_WRITE;
- smsc_write_reg(sc, SMSC_MII_ADDR, addr);
- smsc_unlock_mii(sc);
+ smsc_writereg(un, SMSC_MII_ADDR, addr);
- if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) {
- smsc_warn_printf(sc, "MII write timeout\n");
+ if (smsc_wait_for_bits(un, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) {
+ smsc_warn_printf(un, "MII write timeout\n");
return ETIMEDOUT;
}
@@ -323,46 +297,23 @@ smsc_miibus_writereg(device_t dev, int p
void
smsc_miibus_statchg(struct ifnet *ifp)
{
- if (ifp == NULL)
- return;
+ struct usbnet * const un = ifp->if_softc;
- struct smsc_softc * const sc = ifp->if_softc;
-
- mutex_enter(&sc->sc_lock);
- if (sc->sc_dying) {
- mutex_exit(&sc->sc_lock);
+ if (un->un_dying)
return;
- }
- smsc_miibus_statchg_locked(ifp);
- mutex_exit(&sc->sc_lock);
-}
-
-
-void
-smsc_miibus_statchg_locked(struct ifnet *ifp)
-{
- struct smsc_softc * const sc = ifp->if_softc;
- struct mii_data * const mii = &sc->sc_mii;
- int err;
+ struct smsc_softc * const sc = usbnet_softc(un);
+ struct mii_data * const mii = usbnet_mii(un);
uint32_t flow;
uint32_t afc_cfg;
- KASSERT(mutex_owned(&sc->sc_lock));
-
- if ((ifp->if_flags & IFF_RUNNING) == 0) {
- smsc_dbg_printf(sc, "%s: not running\n", __func__);
- return;
- }
-
- /* Use the MII status to determine link status */
- sc->sc_flags &= ~SMSC_FLAG_LINK;
+ un->un_link = false;
if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
(IFM_ACTIVE | IFM_AVALID)) {
switch (IFM_SUBTYPE(mii->mii_media_active)) {
case IFM_10_T:
case IFM_100_TX:
- sc->sc_flags |= SMSC_FLAG_LINK;
+ un->un_link = true;
break;
case IFM_1000_T:
/* Gigabit ethernet not supported by chipset */
@@ -373,21 +324,21 @@ smsc_miibus_statchg_locked(struct ifnet
}
/* Lost link, do nothing. */
- if ((sc->sc_flags & SMSC_FLAG_LINK) == 0) {
- smsc_dbg_printf(sc, "link flag not set\n");
+ if (!un->un_link)
return;
- }
- err = smsc_read_reg(sc, SMSC_AFC_CFG, &afc_cfg);
+ usbnet_lock_mii(un);
+ int err = smsc_readreg(un, SMSC_AFC_CFG, &afc_cfg);
+ usbnet_unlock_mii(un);
if (err) {
- smsc_warn_printf(sc, "failed to read initial AFC_CFG, "
+ smsc_warn_printf(un, "failed to read initial AFC_CFG, "
"error %d\n", err);
return;
}
/* Enable/disable full duplex operation and TX/RX pause */
if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
- smsc_dbg_printf(sc, "full duplex operation\n");
+ smsc_dbg_printf(un, "full duplex operation\n");
sc->sc_mac_csr &= ~SMSC_MAC_CSR_RCVOWN;
sc->sc_mac_csr |= SMSC_MAC_CSR_FDPX;
@@ -401,7 +352,7 @@ smsc_miibus_statchg_locked(struct ifnet
else
afc_cfg &= ~0xf;
} else {
- smsc_dbg_printf(sc, "half duplex operation\n");
+ smsc_dbg_printf(un, "half duplex operation\n");
sc->sc_mac_csr &= ~SMSC_MAC_CSR_FDPX;
sc->sc_mac_csr |= SMSC_MAC_CSR_RCVOWN;
@@ -409,27 +360,14 @@ smsc_miibus_statchg_locked(struct ifnet
afc_cfg |= 0xf;
}
- err = smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
- err += smsc_write_reg(sc, SMSC_FLOW, flow);
- err += smsc_write_reg(sc, SMSC_AFC_CFG, afc_cfg);
- if (err)
- smsc_warn_printf(sc, "media change failed, error %d\n", err);
-}
-
-int
-smsc_ifmedia_upd(struct ifnet *ifp)
-{
- struct smsc_softc * const sc = ifp->if_softc;
- struct mii_data * const mii = &sc->sc_mii;
-
- if (mii->mii_instance) {
- struct mii_softc *miisc;
-
- LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
- mii_phy_reset(miisc);
- }
+ usbnet_lock_mii(un);
+ err = smsc_writereg(un, SMSC_MAC_CSR, sc->sc_mac_csr);
+ err += smsc_writereg(un, SMSC_FLOW, flow);
+ err += smsc_writereg(un, SMSC_AFC_CFG, afc_cfg);
+ usbnet_unlock_mii(un);
- return ether_mediachange(ifp);
+ if (err)
+ smsc_warn_printf(un, "media change failed, error %d\n", err);
}
static inline uint32_t
@@ -439,27 +377,28 @@ smsc_hash(uint8_t addr[ETHER_ADDR_LEN])
return (ether_crc32_be(addr, ETHER_ADDR_LEN) >> 26) & 0x3f;
}
-void
-smsc_setmulti(struct smsc_softc *sc)
+static void
+smsc_setiff_locked(struct usbnet *un)
{
- struct ethercom *ec = &sc->sc_ec;
- struct ifnet * const ifp = &ec->ec_if;
+ struct smsc_softc * const sc = usbnet_softc(un);
+ struct ifnet * const ifp = usbnet_ifp(un);
+ struct ethercom *ec = usbnet_ec(un);
struct ether_multi *enm;
struct ether_multistep step;
uint32_t hashtbl[2] = { 0, 0 };
uint32_t hash;
- KASSERT(mutex_owned(&sc->sc_lock));
+ usbnet_isowned_mii(un);
- if (sc->sc_dying)
+ if (un->un_dying)
return;
if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
allmulti:
- smsc_dbg_printf(sc, "receive all multicast enabled\n");
+ smsc_dbg_printf(un, "receive all multicast enabled\n");
sc->sc_mac_csr |= SMSC_MAC_CSR_MCPAS;
sc->sc_mac_csr &= ~SMSC_MAC_CSR_HPFILT;
- smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+ smsc_writereg(un, SMSC_MAC_CSR, sc->sc_mac_csr);
return;
} else {
sc->sc_mac_csr |= SMSC_MAC_CSR_HPFILT;
@@ -482,28 +421,41 @@ allmulti:
/* Debug */
if (sc->sc_mac_csr & SMSC_MAC_CSR_HPFILT) {
- smsc_dbg_printf(sc, "receive select group of macs\n");
+ smsc_dbg_printf(un, "receive select group of macs\n");
} else {
- smsc_dbg_printf(sc, "receive own packets only\n");
+ smsc_dbg_printf(un, "receive own packets only\n");
}
/* Write the hash table and mac control registers */
+
+ //XXX should we be doing this?
ifp->if_flags &= ~IFF_ALLMULTI;
- smsc_write_reg(sc, SMSC_HASHH, hashtbl[1]);
- smsc_write_reg(sc, SMSC_HASHL, hashtbl[0]);
- smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+ smsc_writereg(un, SMSC_HASHH, hashtbl[1]);
+ smsc_writereg(un, SMSC_HASHL, hashtbl[0]);
+ smsc_writereg(un, SMSC_MAC_CSR, sc->sc_mac_csr);
}
-int
-smsc_sethwcsum(struct smsc_softc *sc)
+static void
+smsc_setiff(struct usbnet *un)
+{
+ usbnet_lock_mii(un);
+ smsc_setiff_locked(un);
+ usbnet_unlock_mii(un);
+}
+
+static int
+smsc_setoe_locked(struct usbnet *un)
{
- struct ifnet * const ifp = &sc->sc_ec.ec_if;
+ struct smsc_softc * const sc = usbnet_softc(un);
+ struct ifnet * const ifp = usbnet_ifp(un);
uint32_t val;
int err;
- err = smsc_read_reg(sc, SMSC_COE_CTRL, &val);
+ usbnet_isowned_mii(un);
+
+ err = smsc_readreg(un, SMSC_COE_CTRL, &val);
if (err != 0) {
- smsc_warn_printf(sc, "failed to read SMSC_COE_CTRL (err=%d)\n",
+ smsc_warn_printf(un, "failed to read SMSC_COE_CTRL (err=%d)\n",
err);
return err;
}
@@ -522,9 +474,9 @@ smsc_sethwcsum(struct smsc_softc *sc)
sc->sc_coe_ctrl = val;
- err = smsc_write_reg(sc, SMSC_COE_CTRL, val);
+ err = smsc_writereg(un, SMSC_COE_CTRL, val);
if (err != 0) {
- smsc_warn_printf(sc, "failed to write SMSC_COE_CTRL (err=%d)\n",
+ smsc_warn_printf(un, "failed to write SMSC_COE_CTRL (err=%d)\n",
err);
return err;
}
@@ -532,22 +484,32 @@ smsc_sethwcsum(struct smsc_softc *sc)
return 0;
}
+static void
+smsc_setoe(struct usbnet *un)
+{
+
+ usbnet_lock_mii(un);
+ smsc_setoe_locked(un);
+ usbnet_unlock_mii(un);
+}
+
+
int
-smsc_setmacaddress(struct smsc_softc *sc, const uint8_t *addr)
+smsc_setmacaddress(struct usbnet *un, const uint8_t *addr)
{
int err;
uint32_t val;
- smsc_dbg_printf(sc, "setting mac address to "
+ smsc_dbg_printf(un, "setting mac address to "
"%02x:%02x:%02x:%02x:%02x:%02x\n",
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
val = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
- if ((err = smsc_write_reg(sc, SMSC_MAC_ADDRL, val)) != 0)
+ if ((err = smsc_writereg(un, SMSC_MAC_ADDRL, val)) != 0)
goto done;
val = (addr[5] << 8) | addr[4];
- err = smsc_write_reg(sc, SMSC_MAC_ADDRH, val);
+ err = smsc_writereg(un, SMSC_MAC_ADDRH, val);
done:
return err;
@@ -556,25 +518,27 @@ done:
void
smsc_reset(struct smsc_softc *sc)
{
- KASSERT(mutex_owned(&sc->sc_lock));
- if (sc->sc_dying)
+ struct usbnet * const un = &sc->smsc_un;
+
+ usbnet_isowned(un);
+ if (un->un_dying)
return;
/* Wait a little while for the chip to get its brains in order. */
DELAY(1000);
/* Reinitialize controller to achieve full reset. */
- smsc_chip_init(sc);
+ smsc_chip_init(un);
}
int
smsc_init(struct ifnet *ifp)
{
- struct smsc_softc * const sc = ifp->if_softc;
+ struct usbnet * const un = ifp->if_softc;
- mutex_enter(&sc->sc_lock);
+ usbnet_lock(un);
int ret = smsc_init_locked(ifp);
- mutex_exit(&sc->sc_lock);
+ usbnet_unlock(un);
return ret;
}
@@ -582,295 +546,77 @@ smsc_init(struct ifnet *ifp)
int
smsc_init_locked(struct ifnet *ifp)
{
- struct smsc_softc * const sc = ifp->if_softc;
- usbd_status err;
+ struct usbnet * const un = ifp->if_softc;
+ struct smsc_softc * const sc = usbnet_softc(un);
- if (sc->sc_dying)
+ if (un->un_dying)
return EIO;
/* Cancel pending I/O */
- smsc_stop_locked(ifp, 1);
+ usbnet_stop(un, ifp, 1);
/* Reset the ethernet interface. */
smsc_reset(sc);
+ usbnet_lock_mii_un_locked(un);
+
/* Load the multicast filter. */
- smsc_setmulti(sc);
+ smsc_setiff_locked(un);
/* TCP/UDP checksum offload engines. */
- smsc_sethwcsum(sc);
+ smsc_setoe_locked(un);
- /* Open RX and TX pipes. */
- err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_RX],
- USBD_EXCLUSIVE_USE | USBD_MPSAFE, &sc->sc_ep[SMSC_ENDPT_RX]);
- if (err) {
- printf("%s: open rx pipe failed: %s\n",
- device_xname(sc->sc_dev), usbd_errstr(err));
- goto fail;
- }
+ usbnet_unlock_mii_un_locked(un);
- err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_TX],
- USBD_EXCLUSIVE_USE | USBD_MPSAFE, &sc->sc_ep[SMSC_ENDPT_TX]);
- if (err) {
- printf("%s: open tx pipe failed: %s\n",
- device_xname(sc->sc_dev), usbd_errstr(err));
- goto fail1;
- }
-
- /* Init RX ring. */
- if (smsc_rx_list_init(sc)) {
- aprint_error_dev(sc->sc_dev, "rx list init failed\n");
- goto fail2;
- }
-
- /* Init TX ring. */
- if (smsc_tx_list_init(sc)) {
- aprint_error_dev(sc->sc_dev, "tx list init failed\n");
- goto fail3;
- }
-
- mutex_enter(&sc->sc_rxlock);
- mutex_enter(&sc->sc_txlock);
- sc->sc_stopping = false;
-
- /* Start up the receive pipe. */
- for (size_t i = 0; i < SMSC_RX_LIST_CNT; i++) {
- struct smsc_chain * const c = &sc->sc_cdata.rx_chain[i];
- usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, sc->sc_bufsz,
- USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, smsc_rxeof);
- usbd_transfer(c->sc_xfer);
- }
-
- mutex_exit(&sc->sc_txlock);
- mutex_exit(&sc->sc_rxlock);
-
- /* Indicate we are up and running. */
- ifp->if_flags |= IFF_RUNNING;
- ifp->if_flags &= ~IFF_OACTIVE;
-
- callout_reset(&sc->sc_stat_ch, hz, smsc_tick, sc);
-
- return 0;
-
-fail3:
- smsc_rx_list_free(sc);
-fail2:
- usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_TX]);
-fail1:
- usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_RX]);
-fail:
- return EIO;
-}
-
-void
-smsc_start(struct ifnet *ifp)
-{
- struct smsc_softc * const sc = ifp->if_softc;
- KASSERT(ifp->if_extflags & IFEF_MPSAFE);
-
- mutex_enter(&sc->sc_txlock);
- if (!sc->sc_stopping)
- smsc_start_locked(ifp);
- mutex_exit(&sc->sc_txlock);
+ return usbnet_init_rx_tx(un, 0, USBD_FORCE_SHORT_XFER);;
}
void
-smsc_start_locked(struct ifnet *ifp)
+smsc_stop_cb(struct ifnet *ifp, int disable)
{
- struct smsc_softc * const sc = ifp->if_softc;
- struct mbuf *m_head = NULL;
-
- KASSERT(mutex_owned(&sc->sc_txlock));
+ struct usbnet * const un = ifp->if_softc;
+ struct smsc_softc * const sc = usbnet_softc(un);
- /* Don't send anything if there is no link or controller is busy. */
- if ((sc->sc_flags & SMSC_FLAG_LINK) == 0) {
- smsc_dbg_printf(sc, "%s: no link\n", __func__);
- return;
- }
-
- /* Any free USB transfers? */
- if (sc->sc_cdata.tx_free == 0) {
- smsc_dbg_printf(sc, "%s: all USB transfers in use\n", __func__);
- return;
- }
-
- if ((ifp->if_flags & (IFF_OACTIVE | IFF_RUNNING)) != IFF_RUNNING) {
- smsc_dbg_printf(sc, "%s: not running\n", __func__);
- return;
- }
-
- IFQ_POLL(&ifp->if_snd, m_head);
- if (m_head == NULL)
- return;
-
- sc->sc_cdata.tx_free--;
-
- IFQ_DEQUEUE(&ifp->if_snd, m_head);
- if (smsc_encap(sc, m_head, sc->sc_cdata.tx_next)) {
- m_free(m_head);
- sc->sc_cdata.tx_free++;
- return;
- }
-
- sc->sc_cdata.tx_next = (sc->sc_cdata.tx_next + 1) % SMSC_TX_LIST_CNT;
-
- bpf_mtap(ifp, m_head, BPF_D_OUT);
-
- if (sc->sc_cdata.tx_free == 0)
- ifp->if_flags |= IFF_OACTIVE;
-
- /*
- * Set a timeout in case the chip goes out to lunch.
- */
- ifp->if_timer = 5;
-}
-
-void
-smsc_tick(void *xsc)
-{
- struct smsc_softc * const sc = xsc;
-
- if (sc == NULL)
- return;
-
- mutex_enter(&sc->sc_lock);
-
- if (sc->sc_dying) {
- mutex_exit(&sc->sc_lock);
- return;
- }
-
- if (!sc->sc_ttpending) {
- sc->sc_ttpending = true;
- usb_add_task(sc->sc_udev, &sc->sc_tick_task, USB_TASKQ_DRIVER);
- }
-
- mutex_exit(&sc->sc_lock);
-}
-
-void
-smsc_stop(struct ifnet *ifp, int disable)
-{
- struct smsc_softc * const sc = ifp->if_softc;
-
- mutex_enter(&sc->sc_lock);
- smsc_stop_locked(ifp, disable);
- mutex_exit(&sc->sc_lock);
-}
-
-void
-smsc_stop_locked(struct ifnet *ifp, int disable)
-{
- struct smsc_softc * const sc = ifp->if_softc;
- usbd_status err;
-
- KASSERT(mutex_owned(&sc->sc_lock));
- mutex_enter(&sc->sc_rxlock);
- mutex_enter(&sc->sc_txlock);
- sc->sc_stopping = true;
- mutex_exit(&sc->sc_txlock);
- mutex_exit(&sc->sc_rxlock);
-
- callout_stop(&sc->sc_stat_ch);
-
- /* Stop transfers. */
- if (sc->sc_ep[SMSC_ENDPT_RX] != NULL) {
- err = usbd_abort_pipe(sc->sc_ep[SMSC_ENDPT_RX]);
- if (err) {
- printf("%s: abort rx pipe failed: %s\n",
- device_xname(sc->sc_dev), usbd_errstr(err));
- }
- }
-
- if (sc->sc_ep[SMSC_ENDPT_TX] != NULL) {
- err = usbd_abort_pipe(sc->sc_ep[SMSC_ENDPT_TX]);
- if (err) {
- printf("%s: abort tx pipe failed: %s\n",
- device_xname(sc->sc_dev), usbd_errstr(err));
- }
- }
-
- if (sc->sc_ep[SMSC_ENDPT_INTR] != NULL) {
- err = usbd_abort_pipe(sc->sc_ep[SMSC_ENDPT_INTR]);
- if (err) {
- printf("%s: abort intr pipe failed: %s\n",
- device_xname(sc->sc_dev), usbd_errstr(err));
- }
- }
-
- smsc_rx_list_free(sc);
-
- smsc_tx_list_free(sc);
-
- /* Close pipes */
- if (sc->sc_ep[SMSC_ENDPT_RX] != NULL) {
- err = usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_RX]);
- if (err) {
- printf("%s: close rx pipe failed: %s\n",
- device_xname(sc->sc_dev), usbd_errstr(err));
- }
- sc->sc_ep[SMSC_ENDPT_RX] = NULL;
- }
-
- if (sc->sc_ep[SMSC_ENDPT_TX] != NULL) {
- err = usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_TX]);
- if (err) {
- printf("%s: close tx pipe failed: %s\n",
- device_xname(sc->sc_dev), usbd_errstr(err));
- }
- sc->sc_ep[SMSC_ENDPT_TX] = NULL;
- }
-
- if (sc->sc_ep[SMSC_ENDPT_INTR] != NULL) {
- err = usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_INTR]);
- if (err) {
- printf("%s: close intr pipe failed: %s\n",
- device_xname(sc->sc_dev), usbd_errstr(err));
- }
- sc->sc_ep[SMSC_ENDPT_INTR] = NULL;
- }
-
- ifp->if_timer = 0;
- ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
-
- if (disable) {
- /* drain */
- }
+ // XXXNH didn't do this before
+ smsc_reset(sc);
}
int
-smsc_chip_init(struct smsc_softc *sc)
+smsc_chip_init(struct usbnet *un)
{
- int err;
+ struct smsc_softc * const sc = usbnet_softc(un);
uint32_t reg_val;
int burst_cap;
+ int err;
+
+ usbnet_lock_mii_un_locked(un);
/* Enter H/W config mode */
- smsc_write_reg(sc, SMSC_HW_CFG, SMSC_HW_CFG_LRST);
+ smsc_writereg(un, SMSC_HW_CFG, SMSC_HW_CFG_LRST);
- if ((err = smsc_wait_for_bits(sc, SMSC_HW_CFG,
+ if ((err = smsc_wait_for_bits(un, SMSC_HW_CFG,
SMSC_HW_CFG_LRST)) != 0) {
- smsc_warn_printf(sc, "timed-out waiting for reset to "
+ smsc_warn_printf(un, "timed-out waiting for reset to "
"complete\n");
goto init_failed;
}
/* Reset the PHY */
- smsc_write_reg(sc, SMSC_PM_CTRL, SMSC_PM_CTRL_PHY_RST);
+ smsc_writereg(un, SMSC_PM_CTRL, SMSC_PM_CTRL_PHY_RST);
- if ((err = smsc_wait_for_bits(sc, SMSC_PM_CTRL,
+ if ((err = smsc_wait_for_bits(un, SMSC_PM_CTRL,
SMSC_PM_CTRL_PHY_RST)) != 0) {
- smsc_warn_printf(sc, "timed-out waiting for phy reset to "
+ smsc_warn_printf(un, "timed-out waiting for phy reset to "
"complete\n");
goto init_failed;
}
- usbd_delay_ms(sc->sc_udev, 40);
+ usbd_delay_ms(un->un_udev, 40);
/* Set the mac address */
- struct ifnet * const ifp = &sc->sc_ec.ec_if;
+ struct ifnet * const ifp = usbnet_ifp(un);
const char *eaddr = CLLADDR(ifp->if_sadl);
- if ((err = smsc_setmacaddress(sc, eaddr)) != 0) {
- smsc_warn_printf(sc, "failed to set the MAC address\n");
+ if ((err = smsc_setmacaddress(un, eaddr)) != 0) {
+ smsc_warn_printf(un, "failed to set the MAC address\n");
goto init_failed;
}
@@ -878,12 +624,12 @@ smsc_chip_init(struct smsc_softc *sc)
* Don't know what the HW_CFG_BIR bit is, but following the reset
* sequence as used in the Linux driver.
*/
- if ((err = smsc_read_reg(sc, SMSC_HW_CFG, ®_val)) != 0) {
- smsc_warn_printf(sc, "failed to read HW_CFG: %d\n", err);
+ if ((err = smsc_readreg(un, SMSC_HW_CFG, ®_val)) != 0) {
+ smsc_warn_printf(un, "failed to read HW_CFG: %d\n", err);
goto init_failed;
}
reg_val |= SMSC_HW_CFG_BIR;
- smsc_write_reg(sc, SMSC_HW_CFG, reg_val);
+ smsc_writereg(un, SMSC_HW_CFG, reg_val);
/*
* There is a so called 'turbo mode' that the linux driver supports, it
@@ -900,21 +646,21 @@ smsc_chip_init(struct smsc_softc *sc)
* data/ethernet frames.
*/
- if (sc->sc_udev->ud_speed == USB_SPEED_HIGH)
+ if (un->un_udev->ud_speed == USB_SPEED_HIGH)
burst_cap = 37;
else
burst_cap = 128;
- smsc_write_reg(sc, SMSC_BURST_CAP, burst_cap);
+ smsc_writereg(un, SMSC_BURST_CAP, burst_cap);
/* Set the default bulk in delay (magic value from Linux driver) */
- smsc_write_reg(sc, SMSC_BULK_IN_DLY, 0x00002000);
+ smsc_writereg(un, SMSC_BULK_IN_DLY, 0x00002000);
/*
* Initialise the RX interface
*/
- if ((err = smsc_read_reg(sc, SMSC_HW_CFG, ®_val)) < 0) {
- smsc_warn_printf(sc, "failed to read HW_CFG: (err = %d)\n",
+ if ((err = smsc_readreg(un, SMSC_HW_CFG, ®_val)) < 0) {
+ smsc_warn_printf(un, "failed to read HW_CFG: (err = %d)\n",
err);
goto init_failed;
}
@@ -931,32 +677,32 @@ smsc_chip_init(struct smsc_softc *sc)
*/
reg_val |= ETHER_ALIGN << SMSC_HW_CFG_RXDOFF_SHIFT;
- smsc_write_reg(sc, SMSC_HW_CFG, reg_val);
+ smsc_writereg(un, SMSC_HW_CFG, reg_val);
/* Clear the status register ? */
- smsc_write_reg(sc, SMSC_INTR_STATUS, 0xffffffff);
+ smsc_writereg(un, SMSC_INTR_STATUS, 0xffffffff);
/* Read and display the revision register */
- if ((err = smsc_read_reg(sc, SMSC_ID_REV, &sc->sc_rev_id)) < 0) {
- smsc_warn_printf(sc, "failed to read ID_REV (err = %d)\n", err);
+ if ((err = smsc_readreg(un, SMSC_ID_REV, &sc->sc_rev_id)) < 0) {
+ smsc_warn_printf(un, "failed to read ID_REV (err = %d)\n", err);
goto init_failed;
}
/* GPIO/LED setup */
reg_val = SMSC_LED_GPIO_CFG_SPD_LED | SMSC_LED_GPIO_CFG_LNK_LED |
SMSC_LED_GPIO_CFG_FDX_LED;
- smsc_write_reg(sc, SMSC_LED_GPIO_CFG, reg_val);
+ smsc_writereg(un, SMSC_LED_GPIO_CFG, reg_val);
/*
* Initialise the TX interface
*/
- smsc_write_reg(sc, SMSC_FLOW, 0);
+ smsc_writereg(un, SMSC_FLOW, 0);
- smsc_write_reg(sc, SMSC_AFC_CFG, AFC_CFG_DEFAULT);
+ smsc_writereg(un, SMSC_AFC_CFG, AFC_CFG_DEFAULT);
/* Read the current MAC configuration */
- if ((err = smsc_read_reg(sc, SMSC_MAC_CSR, &sc->sc_mac_csr)) < 0) {
- smsc_warn_printf(sc, "failed to read MAC_CSR (err=%d)\n", err);
+ if ((err = smsc_readreg(un, SMSC_MAC_CSR, &sc->sc_mac_csr)) < 0) {
+ smsc_warn_printf(un, "failed to read MAC_CSR (err=%d)\n", err);
goto init_failed;
}
@@ -964,90 +710,53 @@ smsc_chip_init(struct smsc_softc *sc)
sc->sc_mac_csr &= ~SMSC_MAC_CSR_PADSTR;
/* Vlan */
- smsc_write_reg(sc, SMSC_VLAN1, (uint32_t)ETHERTYPE_VLAN);
+ smsc_writereg(un, SMSC_VLAN1, (uint32_t)ETHERTYPE_VLAN);
/*
* Start TX
*/
sc->sc_mac_csr |= SMSC_MAC_CSR_TXEN;
- smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
- smsc_write_reg(sc, SMSC_TX_CFG, SMSC_TX_CFG_ON);
+ smsc_writereg(un, SMSC_MAC_CSR, sc->sc_mac_csr);
+ smsc_writereg(un, SMSC_TX_CFG, SMSC_TX_CFG_ON);
/*
* Start RX
*/
sc->sc_mac_csr |= SMSC_MAC_CSR_RXEN;
- smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+ smsc_writereg(un, SMSC_MAC_CSR, sc->sc_mac_csr);
+ usbnet_unlock_mii_un_locked(un);
return 0;
init_failed:
- smsc_err_printf(sc, "smsc_chip_init failed (err=%d)\n", err);
+ usbnet_unlock_mii_un_locked(un);
+ smsc_err_printf(un, "smsc_chip_init failed (err=%d)\n", err);
return err;
}
+
static int
-smsc_ifflags_cb(struct ethercom *ec)
+smsc_ioctl_cb(struct ifnet *ifp, u_long cmd, void *data)
{
- struct ifnet *ifp = &ec->ec_if;
- struct smsc_softc *sc = ifp->if_softc;
-
- mutex_enter(&sc->sc_lock);
-
- const int change = ifp->if_flags ^ sc->sc_if_flags;
- if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) {
- mutex_exit(&sc->sc_lock);
- return ENETRESET;
- }
-
- smsc_dbg_printf(sc, "%s: change %x\n", __func__, change);
+ struct usbnet * const un = ifp->if_softc;
- if ((change & IFF_PROMISC) != 0) {
- if (ifp->if_flags & IFF_PROMISC) {
- sc->sc_mac_csr |= SMSC_MAC_CSR_PRMS;
- smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
- } else if (!(ifp->if_flags & IFF_PROMISC)) {
- sc->sc_mac_csr &= ~SMSC_MAC_CSR_PRMS;
- smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
- }
- smsc_setmulti(sc);
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ case SIOCSETHERCAP:
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ smsc_setiff(un);
+ break;
+ case SIOCSIFCAP:
+ smsc_setoe(un);
+ break;
+ default:
+ break;
}
- mutex_exit(&sc->sc_lock);
-
return 0;
}
-
-int
-smsc_ioctl(struct ifnet *ifp, u_long cmd, void *data)
-{
- struct smsc_softc * const sc = ifp->if_softc;
-
- smsc_dbg_printf(sc, "%s: cmd %0lx data %p\n", __func__, cmd, data);
-
- int error = ether_ioctl(ifp, cmd, data);
-
- if (error == ENETRESET) {
- error = 0;
- if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI) {
- if (ifp->if_flags & IFF_RUNNING) {
- mutex_enter(&sc->sc_lock);
- smsc_setmulti(sc);
- mutex_exit(&sc->sc_lock);
- }
- }
- }
-
- mutex_enter(&sc->sc_rxlock);
- mutex_enter(&sc->sc_txlock);
- sc->sc_if_flags = ifp->if_flags;
- mutex_exit(&sc->sc_txlock);
- mutex_exit(&sc->sc_rxlock);
-
- return error;
-}
-
int
smsc_match(device_t parent, cfdata_t match, void *aux)
{
@@ -1060,27 +769,37 @@ smsc_match(device_t parent, cfdata_t mat
void
smsc_attach(device_t parent, device_t self, void *aux)
{
- struct smsc_softc *sc = device_private(self);
+ struct smsc_softc * const sc = device_private(self);
+ struct usbnet * const un = &sc->smsc_un;
struct usb_attach_arg *uaa = aux;
struct usbd_device *dev = uaa->uaa_device;
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
char *devinfop;
- struct mii_data *mii;
- struct ifnet *ifp;
int err, i;
uint32_t mac_h, mac_l;
- sc->sc_dev = self;
- sc->sc_udev = dev;
- sc->sc_dying = false;
- sc->sc_stopping = false;
- sc->sc_ttpending = false;
+ /* Switch to usbnet for device_private() */
+ self->dv_private = un;
aprint_naive("\n");
aprint_normal("\n");
- devinfop = usbd_devinfo_alloc(sc->sc_udev, 0);
+ un->un_dev = self;
+ un->un_udev = dev;
+ un->un_sc = sc;
+ un->un_stop_cb = smsc_stop_cb;
+ un->un_ioctl_cb = smsc_ioctl_cb;
+ un->un_read_reg_cb = smsc_miibus_readreg;
+ un->un_write_reg_cb = smsc_miibus_writereg;
+ un->un_statchg_cb = smsc_miibus_statchg;
+ un->un_tx_prepare_cb = smsc_tx_prepare;
+ un->un_rx_loop_cb = smsc_rxeof_loop;
+ un->un_init_cb = smsc_init;
+ un->un_rx_xfer_flags = USBD_SHORT_XFER_OK;
+ un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER;
+
+ devinfop = usbd_devinfo_alloc(un->un_udev, 0);
aprint_normal_dev(self, "%s\n", devinfop);
usbd_devinfo_free(devinfop);
@@ -1092,76 +811,67 @@ smsc_attach(device_t parent, device_t se
}
/* Setup the endpoints for the SMSC LAN95xx device(s) */
- err = usbd_device2interface_handle(dev, SMSC_IFACE_IDX, &sc->sc_iface);
+ err = usbd_device2interface_handle(dev, SMSC_IFACE_IDX, &un->un_iface);
if (err) {
aprint_error_dev(self, "getting interface handle failed\n");
return;
}
- id = usbd_get_interface_descriptor(sc->sc_iface);
+ id = usbd_get_interface_descriptor(un->un_iface);
- if (sc->sc_udev->ud_speed >= USB_SPEED_HIGH)
- sc->sc_bufsz = SMSC_MAX_BUFSZ;
- else
- sc->sc_bufsz = SMSC_MIN_BUFSZ;
+ if (dev->ud_speed >= USB_SPEED_HIGH) {
+ un->un_cdata.uncd_rx_bufsz = SMSC_MAX_BUFSZ;
+ un->un_cdata.uncd_tx_bufsz = SMSC_MAX_BUFSZ;
+ } else {
+ un->un_cdata.uncd_rx_bufsz = SMSC_MIN_BUFSZ;
+ un->un_cdata.uncd_tx_bufsz = SMSC_MIN_BUFSZ;
+ }
/* Find endpoints. */
for (i = 0; i < id->bNumEndpoints; i++) {
- ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
+ ed = usbd_interface2endpoint_descriptor(un->un_iface, i);
if (!ed) {
aprint_error_dev(self, "couldn't get ep %d\n", i);
return;
}
if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
- sc->sc_ed[SMSC_ENDPT_RX] = ed->bEndpointAddress;
+ un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress;
} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
- sc->sc_ed[SMSC_ENDPT_TX] = ed->bEndpointAddress;
+ un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress;
+#if 0 /* not used yet */
} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
- sc->sc_ed[SMSC_ENDPT_INTR] = ed->bEndpointAddress;
+ un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress;
+#endif
}
}
- usb_init_task(&sc->sc_tick_task, smsc_tick_task, sc, USB_TASKQ_MPSAFE);
-
- mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
- mutex_init(&sc->sc_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
- mutex_init(&sc->sc_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
- mutex_init(&sc->sc_mii_lock, MUTEX_DEFAULT, IPL_NONE);
- cv_init(&sc->sc_detachcv, "smsc_det");
-
- ifp = &sc->sc_ec.ec_if;
- ifp->if_softc = sc;
- strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_extflags = IFEF_MPSAFE;
- ifp->if_init = smsc_init;
- ifp->if_ioctl = smsc_ioctl;
- ifp->if_start = smsc_start;
- ifp->if_stop = smsc_stop;
+ usbnet_attach(un, "smscdet", SMSC_RX_LIST_CNT, SMSC_TX_LIST_CNT);
#ifdef notyet
/*
* We can do TCPv4, and UDPv4 checksums in hardware.
*/
+ struct ifnet *ifp = usbnet_ifp(un);
+
ifp->if_capabilities |=
/*IFCAP_CSUM_TCPv4_Tx |*/ IFCAP_CSUM_TCPv4_Rx |
/*IFCAP_CSUM_UDPv4_Tx |*/ IFCAP_CSUM_UDPv4_Rx;
#endif
-
- sc->sc_ec.ec_capabilities = ETHERCAP_VLAN_MTU;
+ un->un_ec.ec_capabilities = ETHERCAP_VLAN_MTU;
/* Setup some of the basics */
- sc->sc_phyno = 1;
+ un->un_phyno = 1;
+ usbnet_lock_mii(un);
/*
* Attempt to get the mac address, if an EEPROM is not attached this
* will just return FF:FF:FF:FF:FF:FF, so in such cases we invent a MAC
* address based on urandom.
*/
- memset(sc->sc_enaddr, 0xff, ETHER_ADDR_LEN);
+ memset(un->un_eaddr, 0xff, ETHER_ADDR_LEN);
prop_dictionary_t dict = device_properties(self);
prop_data_t eaprop = prop_dictionary_get(dict, "mac-address");
@@ -1169,249 +879,43 @@ smsc_attach(device_t parent, device_t se
if (eaprop != NULL) {
KASSERT(prop_object_type(eaprop) == PROP_TYPE_DATA);
KASSERT(prop_data_size(eaprop) == ETHER_ADDR_LEN);
- memcpy(sc->sc_enaddr, prop_data_data_nocopy(eaprop),
+ memcpy(un->un_eaddr, prop_data_data_nocopy(eaprop),
ETHER_ADDR_LEN);
} else {
/* Check if there is already a MAC address in the register */
- if ((smsc_read_reg(sc, SMSC_MAC_ADDRL, &mac_l) == 0) &&
- (smsc_read_reg(sc, SMSC_MAC_ADDRH, &mac_h) == 0)) {
- sc->sc_enaddr[5] = (uint8_t)((mac_h >> 8) & 0xff);
- sc->sc_enaddr[4] = (uint8_t)((mac_h) & 0xff);
- sc->sc_enaddr[3] = (uint8_t)((mac_l >> 24) & 0xff);
- sc->sc_enaddr[2] = (uint8_t)((mac_l >> 16) & 0xff);
- sc->sc_enaddr[1] = (uint8_t)((mac_l >> 8) & 0xff);
- sc->sc_enaddr[0] = (uint8_t)((mac_l) & 0xff);
+ if ((smsc_readreg(un, SMSC_MAC_ADDRL, &mac_l) == 0) &&
+ (smsc_readreg(un, SMSC_MAC_ADDRH, &mac_h) == 0)) {
+ un->un_eaddr[5] = (uint8_t)((mac_h >> 8) & 0xff);
+ un->un_eaddr[4] = (uint8_t)((mac_h) & 0xff);
+ un->un_eaddr[3] = (uint8_t)((mac_l >> 24) & 0xff);
+ un->un_eaddr[2] = (uint8_t)((mac_l >> 16) & 0xff);
+ un->un_eaddr[1] = (uint8_t)((mac_l >> 8) & 0xff);
+ un->un_eaddr[0] = (uint8_t)((mac_l) & 0xff);
}
}
+ usbnet_unlock_mii(un);
- aprint_normal_dev(self, "Ethernet address %s\n",
- ether_sprintf(sc->sc_enaddr));
-
- IFQ_SET_READY(&ifp->if_snd);
-
- /* Initialize MII/media info. */
- mii = &sc->sc_mii;
- mii->mii_ifp = ifp;
- mii->mii_readreg = smsc_miibus_readreg;
- mii->mii_writereg = smsc_miibus_writereg;
- mii->mii_statchg = smsc_miibus_statchg;
- mii->mii_flags = MIIF_AUTOTSLEEP;
- sc->sc_ec.ec_mii = mii;
- ifmedia_init(&mii->mii_media, 0, smsc_ifmedia_upd, 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);
-
- callout_init(&sc->sc_stat_ch, CALLOUT_MPSAFE);
-
- if_initialize(ifp);
- sc->sc_ipq = if_percpuq_create(&sc->sc_ec.ec_if);
- ether_ifattach(ifp, sc->sc_enaddr);
- ether_set_ifflags_cb(&sc->sc_ec, smsc_ifflags_cb);
- if_register(ifp);
-
- rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev),
- RND_TYPE_NET, RND_FLAG_DEFAULT);
-
- usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
-}
-
-int
-smsc_detach(device_t self, int flags)
-{
- struct smsc_softc *sc = device_private(self);
- struct ifnet *ifp = &sc->sc_ec.ec_if;
-
- mutex_enter(&sc->sc_lock);
- sc->sc_dying = true;
- mutex_exit(&sc->sc_lock);
-
- callout_halt(&sc->sc_stat_ch, NULL);
-
- if (ifp->if_flags & IFF_RUNNING)
- smsc_stop_locked(ifp, 1);
-
- /*
- * Remove any pending tasks. They cannot be executing because they run
- * in the same thread as detach.
- */
- usb_rem_task_wait(sc->sc_udev, &sc->sc_tick_task, USB_TASKQ_DRIVER,
- NULL);
-
- mutex_enter(&sc->sc_lock);
- sc->sc_refcnt--;
- while (sc->sc_refcnt > 0) {
- /* Wait for processes to go away */
- cv_wait(&sc->sc_detachcv, &sc->sc_lock);
- }
-
-#ifdef DIAGNOSTIC
- if (sc->sc_ep[SMSC_ENDPT_TX] != NULL ||
- sc->sc_ep[SMSC_ENDPT_RX] != NULL ||
- sc->sc_ep[SMSC_ENDPT_INTR] != NULL)
- printf("%s: detach has active endpoints\n",
- device_xname(sc->sc_dev));
-#endif
-
- mutex_exit(&sc->sc_lock);
-
- rnd_detach_source(&sc->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);
- if (ifp->if_softc != NULL) {
- ether_ifdetach(ifp);
- if_detach(ifp);
- }
-
- usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
-
- cv_destroy(&sc->sc_detachcv);
- mutex_destroy(&sc->sc_mii_lock);
- mutex_destroy(&sc->sc_rxlock);
- mutex_destroy(&sc->sc_txlock);
- mutex_destroy(&sc->sc_lock);
-
- return 0;
+ usbnet_attach_ifp(un, true, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST,
+ 0, 0);
}
void
-smsc_tick_task(void *xsc)
+smsc_rxeof_loop(struct usbnet * un, struct usbd_xfer *xfer,
+ struct usbnet_chain *c, uint32_t total_len)
{
- struct smsc_softc * const sc = xsc;
-
- if (sc == NULL)
- return;
-
- mutex_enter(&sc->sc_lock);
-
- if (sc->sc_dying) {
- mutex_exit(&sc->sc_lock);
- return;
- }
-
- struct ifnet * const ifp = &sc->sc_ec.ec_if;
- struct mii_data * const mii = &sc->sc_mii;
-
- sc->sc_refcnt++;
- mutex_exit(&sc->sc_lock);
-
- mii_tick(mii);
- if ((sc->sc_flags & SMSC_FLAG_LINK) == 0)
- smsc_miibus_statchg(ifp);
-
- mutex_enter(&sc->sc_lock);
- sc->sc_ttpending = false;
-
- if (--sc->sc_refcnt < 0)
- cv_broadcast(&sc->sc_detachcv);
-
- if (sc->sc_dying) {
- mutex_exit(&sc->sc_lock);
- return;
- }
- callout_reset(&sc->sc_stat_ch, hz, smsc_tick, sc);
-
- mutex_exit(&sc->sc_lock);
-}
-
-int
-smsc_activate(device_t self, enum devact act)
-{
- struct smsc_softc *sc = device_private(self);
-
- switch (act) {
- case DVACT_DEACTIVATE:
- if_deactivate(&sc->sc_ec.ec_if);
-
- mutex_enter(&sc->sc_lock);
- sc->sc_dying = true;
-
- mutex_enter(&sc->sc_rxlock);
- mutex_enter(&sc->sc_txlock);
- sc->sc_stopping = true;
- mutex_exit(&sc->sc_txlock);
- mutex_exit(&sc->sc_rxlock);
-
- mutex_exit(&sc->sc_lock);
- return 0;
- default:
- return EOPNOTSUPP;
- }
- return 0;
-}
-
-void
-smsc_lock_mii(struct smsc_softc *sc)
-{
-
- mutex_enter(&sc->sc_lock);
- sc->sc_refcnt++;
- mutex_exit(&sc->sc_lock);
-
- mutex_enter(&sc->sc_mii_lock);
-}
-
-void
-smsc_unlock_mii(struct smsc_softc *sc)
-{
-
- mutex_exit(&sc->sc_mii_lock);
- mutex_enter(&sc->sc_lock);
- if (--sc->sc_refcnt < 0)
- cv_broadcast(&sc->sc_detachcv);
- mutex_exit(&sc->sc_lock);
-}
-
-void
-smsc_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
-{
- struct smsc_chain * const c = (struct smsc_chain *)priv;
- struct smsc_softc * const sc = c->sc_sc;
- struct ifnet * const ifp = &sc->sc_ec.ec_if;
- u_char *buf = c->sc_buf;
- uint32_t total_len;
-
- mutex_enter(&sc->sc_rxlock);
- if (sc->sc_stopping) {
- smsc_dbg_printf(sc, "%s: stopping\n", __func__);
- mutex_exit(&sc->sc_rxlock);
- return;
- }
-
- if (!(sc->sc_if_flags & IFF_RUNNING)) {
- smsc_dbg_printf(sc, "%s: not running\n", __func__);
- mutex_exit(&sc->sc_rxlock);
- return;
- }
-
- if (status != USBD_NORMAL_COMPLETION) {
- if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
- mutex_exit(&sc->sc_rxlock);
- return;
- }
- if (usbd_ratecheck(&sc->sc_rx_notice)) {
- printf("%s: usb errors on rx: %s\n",
- device_xname(sc->sc_dev), usbd_errstr(status));
- }
- if (status == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->sc_ep[SMSC_ENDPT_RX]);
- goto done;
- }
+ struct smsc_softc * const sc = usbnet_softc(un);
+ struct ifnet *ifp = usbnet_ifp(un);
+ uint8_t *buf = c->unc_buf;
- usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
- smsc_dbg_printf(sc, "xfer status total_len %d\n", total_len);
+ KASSERT(mutex_owned(&un->un_rxlock));
while (total_len != 0) {
uint32_t rxhdr;
if (total_len < sizeof(rxhdr)) {
- smsc_dbg_printf(sc, "total_len %d < sizeof(rxhdr) %zu\n",
+ smsc_dbg_printf(un, "total_len %d < sizeof(rxhdr) %zu\n",
total_len, sizeof(rxhdr));
ifp->if_ierrors++;
- goto done;
+ return;
}
memcpy(&rxhdr, buf, sizeof(rxhdr));
@@ -1425,62 +929,68 @@ smsc_rxeof(struct usbd_xfer *xfer, void
if (rxhdr & (SMSC_RX_STAT_ERROR
| SMSC_RX_STAT_LENGTH_ERROR
| SMSC_RX_STAT_MII_ERROR)) {
- smsc_dbg_printf(sc, "rx error (hdr 0x%08x)\n", rxhdr);
+ smsc_dbg_printf(un, "rx error (hdr 0x%08x)\n", rxhdr);
ifp->if_ierrors++;
- goto done;
+ return;
}
uint16_t pktlen = (uint16_t)SMSC_RX_STAT_FRM_LENGTH(rxhdr);
- smsc_dbg_printf(sc, "rxeof total_len %d pktlen %d rxhdr "
+ smsc_dbg_printf(un, "rxeof total_len %d pktlen %d rxhdr "
"0x%08x\n", total_len, pktlen, rxhdr);
if (pktlen < ETHER_HDR_LEN) {
- smsc_dbg_printf(sc, "pktlen %d < ETHER_HDR_LEN %d\n",
+ smsc_dbg_printf(un, "pktlen %d < ETHER_HDR_LEN %d\n",
pktlen, ETHER_HDR_LEN);
ifp->if_ierrors++;
- goto done;
+ return;
}
pktlen += ETHER_ALIGN;
if (pktlen > MCLBYTES) {
- smsc_dbg_printf(sc, "pktlen %d > MCLBYTES %d\n",
+ smsc_dbg_printf(un, "pktlen %d > MCLBYTES %d\n",
pktlen, MCLBYTES);
ifp->if_ierrors++;
- goto done;
+ return;
}
if (pktlen > total_len) {
- smsc_dbg_printf(sc, "pktlen %d > total_len %d\n",
+ smsc_dbg_printf(un, "pktlen %d > total_len %d\n",
pktlen, total_len);
ifp->if_ierrors++;
- goto done;
+ return;
}
- struct mbuf *m = smsc_newbuf();
+#if 0
+ struct mbuf *m = usbnet_newbuf();
if (m == NULL) {
- smsc_dbg_printf(sc, "smc_newbuf returned NULL\n");
+ smsc_dbg_printf(un, "smc_newbuf returned NULL\n");
ifp->if_ierrors++;
- goto done;
+ return;
}
m_set_rcvif(m, ifp);
m->m_pkthdr.len = m->m_len = pktlen;
m->m_flags |= M_HASFCS;
m_adj(m, ETHER_ALIGN);
+#endif
+ uint8_t *pktbuf = buf + ETHER_ALIGN;
+ size_t buflen = pktlen;
+ int mbuf_flags = M_HASFCS;
+ int csum_flags = 0;
+ uint16_t csum_data = 0;
- KASSERT(m->m_len < MCLBYTES);
- memcpy(mtod(m, char *), buf + ETHER_ALIGN, m->m_len);
+ KASSERT(pktlen < MCLBYTES);
+// memcpy(mtod(m, char *), buf + ETHER_ALIGN, m->m_len);
/* Check if RX TCP/UDP checksumming is being offloaded */
if (sc->sc_coe_ctrl & SMSC_COE_CTRL_RX_EN) {
- smsc_dbg_printf(sc,"RX checksum offload checking\n");
- struct ether_header *eh;
-
- eh = mtod(m, struct ether_header *);
+ smsc_dbg_printf(un,"RX checksum offload checking\n");
+ struct ether_header *eh = (struct ether_header *)pktbuf;
+ const size_t cssz = sizeof(csum_data);
/* Remove the extra 2 bytes of the csum */
- m_adj(m, -2);
+ buflen -= cssz;
/*
* The checksum appears to be simplistically calculated
@@ -1493,12 +1003,12 @@ smsc_rxeof(struct usbd_xfer *xfer, void
*
* Ignore H/W csum for non-IPv4 packets.
*/
- smsc_dbg_printf(sc,"Ethertype %02x pktlen %02x\n",
+ smsc_dbg_printf(un,"Ethertype %02x pktlen %02x\n",
be16toh(eh->ether_type), pktlen);
if (be16toh(eh->ether_type) == ETHERTYPE_IP &&
pktlen > ETHER_MIN_LEN) {
- m->m_pkthdr.csum_flags |=
+ csum_flags |=
(M_CSUM_TCPv4 | M_CSUM_UDPv4 | M_CSUM_DATA);
/*
@@ -1506,18 +1016,17 @@ smsc_rxeof(struct usbd_xfer *xfer, void
* bytes of the transfer and put in the
* csum_data field.
*/
- memcpy(&m->m_pkthdr.csum_data,
- buf + pktlen - 2, 2);
+ memcpy(&csum_data, buf + pktlen - cssz, cssz);
+
/*
* The data is copied in network order, but the
* csum algorithm in the kernel expects it to be
* in host network order.
*/
- m->m_pkthdr.csum_data =
- ntohs(m->m_pkthdr.csum_data);
- smsc_dbg_printf(sc,
+ csum_data = ntohs(csum_data);
+ smsc_dbg_printf(un,
"RX checksum offloaded (0x%04x)\n",
- m->m_pkthdr.csum_data);
+ csum_data);
}
}
@@ -1531,179 +1040,20 @@ smsc_rxeof(struct usbd_xfer *xfer, void
buf += pktlen;
total_len -= pktlen;
- mutex_exit(&sc->sc_rxlock);
-
/* push the packet up */
- if_percpuq_enqueue(sc->sc_ipq, m);
-
- mutex_enter(&sc->sc_rxlock);
- if (sc->sc_stopping) {
- smsc_dbg_printf(sc, "%s: stopping\n", __func__);
- mutex_exit(&sc->sc_rxlock);
- return;
- }
+ usbnet_enqueue(un, pktbuf, buflen, csum_flags, csum_data,
+ mbuf_flags);
}
-
-done:
- mutex_exit(&sc->sc_rxlock);
-
- /* Setup new transfer. */
- usbd_setup_xfer(xfer, c, c->sc_buf, sc->sc_bufsz, USBD_SHORT_XFER_OK,
- USBD_NO_TIMEOUT, smsc_rxeof);
- usbd_transfer(xfer);
-
- return;
}
-void
-smsc_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
-{
- struct smsc_chain *c = priv;
- struct smsc_softc *sc = c->sc_sc;
- struct ifnet *ifp = &sc->sc_ec.ec_if;
-
- mutex_enter(&sc->sc_txlock);
- if (sc->sc_stopping) {
- smsc_dbg_printf(sc, "%s: stopping\n", __func__);
- mutex_exit(&sc->sc_txlock);
- return;
- }
-
- sc->sc_cdata.tx_free++;
- ifp->if_timer = 0;
- ifp->if_flags &= ~IFF_OACTIVE;
-
- if (status != USBD_NORMAL_COMPLETION) {
- if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
- mutex_exit(&sc->sc_txlock);
- return;
- }
- ifp->if_oerrors++;
- printf("%s: usb error on tx: %s\n", device_xname(sc->sc_dev),
- usbd_errstr(status));
- if (status == USBD_STALLED)
- usbd_clear_endpoint_stall_async(sc->sc_ep[SMSC_ENDPT_TX]);
- mutex_exit(&sc->sc_txlock);
- return;
- }
- ifp->if_opackets++;
-
- m_freem(c->sc_mbuf);
- c->sc_mbuf = NULL;
-
- if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
- smsc_start_locked(ifp);
-
- mutex_exit(&sc->sc_txlock);
-}
-
-int
-smsc_tx_list_init(struct smsc_softc *sc)
-{
- struct smsc_cdata *cd = &sc->sc_cdata;
- struct smsc_chain *c;
- int i;
-
- for (i = 0; i < SMSC_TX_LIST_CNT; i++) {
- c = &cd->tx_chain[i];
- c->sc_sc = sc;
- c->sc_mbuf = NULL;
- if (c->sc_xfer == NULL) {
- int error = usbd_create_xfer(sc->sc_ep[SMSC_ENDPT_TX],
- sc->sc_bufsz, USBD_FORCE_SHORT_XFER, 0,
- &c->sc_xfer);
- if (error)
- return EIO;
- c->sc_buf = usbd_get_buffer(c->sc_xfer);
- }
- }
-
- cd->tx_free = SMSC_TX_LIST_CNT;
- cd->tx_next = 0;
-
- return 0;
-}
-
-void
-smsc_tx_list_free(struct smsc_softc *sc)
+static unsigned
+smsc_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c)
{
- /* Free TX resources. */
- for (size_t i = 0; i < SMSC_TX_LIST_CNT; i++) {
- if (sc->sc_cdata.tx_chain[i].sc_mbuf != NULL) {
- m_freem(sc->sc_cdata.tx_chain[i].sc_mbuf);
- sc->sc_cdata.tx_chain[i].sc_mbuf = NULL;
- }
- if (sc->sc_cdata.tx_chain[i].sc_xfer != NULL) {
- usbd_destroy_xfer(sc->sc_cdata.tx_chain[i].sc_xfer);
- sc->sc_cdata.tx_chain[i].sc_xfer = NULL;
- }
- }
-}
-
-int
-smsc_rx_list_init(struct smsc_softc *sc)
-{
- struct smsc_cdata *cd = &sc->sc_cdata;
- struct smsc_chain *c;
- int i;
-
- for (i = 0; i < SMSC_RX_LIST_CNT; i++) {
- c = &cd->rx_chain[i];
- c->sc_sc = sc;
- c->sc_mbuf = NULL;
- if (c->sc_xfer == NULL) {
- int error = usbd_create_xfer(sc->sc_ep[SMSC_ENDPT_RX],
- sc->sc_bufsz, USBD_SHORT_XFER_OK, 0, &c->sc_xfer);
- if (error)
- return error;
- c->sc_buf = usbd_get_buffer(c->sc_xfer);
- }
- }
-
- return 0;
-}
-
-void
-smsc_rx_list_free(struct smsc_softc *sc)
-{
- /* Free RX resources. */
- for (size_t i = 0; i < SMSC_RX_LIST_CNT; i++) {
- if (sc->sc_cdata.rx_chain[i].sc_mbuf != NULL) {
- m_freem(sc->sc_cdata.rx_chain[i].sc_mbuf);
- sc->sc_cdata.rx_chain[i].sc_mbuf = NULL;
- }
- if (sc->sc_cdata.rx_chain[i].sc_xfer != NULL) {
- usbd_destroy_xfer(sc->sc_cdata.rx_chain[i].sc_xfer);
- sc->sc_cdata.rx_chain[i].sc_xfer = NULL;
- }
- }
-}
-
-struct mbuf *
-smsc_newbuf(void)
-{
- struct mbuf *m;
-
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return NULL;
-
- MCLGET(m, M_DONTWAIT);
- if (!(m->m_flags & M_EXT)) {
- m_freem(m);
- return NULL;
- }
-
- return m;
-}
-
-int
-smsc_encap(struct smsc_softc *sc, struct mbuf *m, int idx)
-{
- struct smsc_chain * const c = &sc->sc_cdata.tx_chain[idx];
uint32_t txhdr;
uint32_t frm_len = 0;
+ KASSERT(mutex_owned(&un->un_txlock));
+
/*
* Each frame is prefixed with two 32-bit values describing the
* length of the packet and buffer.
@@ -1711,27 +1061,46 @@ smsc_encap(struct smsc_softc *sc, struct
txhdr = SMSC_TX_CTRL_0_BUF_SIZE(m->m_pkthdr.len) |
SMSC_TX_CTRL_0_FIRST_SEG | SMSC_TX_CTRL_0_LAST_SEG;
txhdr = htole32(txhdr);
- memcpy(c->sc_buf, &txhdr, sizeof(txhdr));
+ memcpy(c->unc_buf, &txhdr, sizeof(txhdr));
txhdr = SMSC_TX_CTRL_1_PKT_LENGTH(m->m_pkthdr.len);
txhdr = htole32(txhdr);
- memcpy(c->sc_buf + 4, &txhdr, sizeof(txhdr));
+ memcpy(c->unc_buf + 4, &txhdr, sizeof(txhdr));
frm_len += 8;
/* Next copy in the actual packet */
- m_copydata(m, 0, m->m_pkthdr.len, c->sc_buf + frm_len);
+ m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf + frm_len);
frm_len += m->m_pkthdr.len;
- c->sc_mbuf = m;
+ return frm_len;
+}
- usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, frm_len,
- USBD_FORCE_SHORT_XFER, 10000, smsc_txeof);
+MODULE(MODULE_CLASS_DRIVER, if_smsc, "usbnet");
- usbd_status err = usbd_transfer(c->sc_xfer);
- if (err != USBD_IN_PROGRESS) {
- return EIO;
- }
+#ifdef _MODULE
+#include "ioconf.c"
+#endif
- return 0;
+static int
+if_smsc_modcmd(modcmd_t cmd, void *aux)
+{
+ int error = 0;
+
+ switch (cmd) {
+ case MODULE_CMD_INIT:
+#ifdef _MODULE
+ error = config_init_component(cfdriver_ioconf_smsc,
+ cfattach_ioconf_smsc, cfdata_ioconf_smsc);
+#endif
+ return error;
+ case MODULE_CMD_FINI:
+#ifdef _MODULE
+ error = config_fini_component(cfdriver_ioconf_smsc,
+ cfattach_ioconf_axen, cfdata_ioconf_smsc);
+#endif
+ return error;
+ default:
+ return ENOTTY;
+ }
}