67#include <sys/stdint.h>
68#include <sys/stddef.h>
73#include <sys/kernel.h>
75#include <sys/module.h>
78#include <sys/condvar.h>
79#include <sys/socket.h>
80#include <sys/sysctl.h>
82#include <sys/unistd.h>
83#include <sys/callout.h>
84#include <sys/malloc.h>
86#include <sys/random.h>
89#include <net/if_var.h>
90#include <net/if_media.h>
92#include <dev/mii/mii.h>
93#include <dev/mii/miivar.h>
95#include <netinet/in.h>
96#include <netinet/ip.h>
98#include "opt_platform.h"
101#include <dev/fdt/fdt_common.h>
102#include <dev/ofw/ofw_bus.h>
103#include <dev/ofw/ofw_bus_subr.h>
112#define USB_DEBUG_VAR smsc_debug
120#include "miibus_if.h"
122SYSCTL_NODE(_hw_usb, OID_AUTO, smsc, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
129 "If set, allows packet batching to increase throughput and latency. "
130 "Else throughput and latency is decreased.");
133static int smsc_debug = 0;
135SYSCTL_INT(_hw_usb_smsc, OID_AUTO,
debug, CTLFLAG_RWTUN, &smsc_debug, 0,
143#define SMSC_DEV(p,i) { USB_VPI(USB_VENDOR_SMC2, USB_PRODUCT_SMC2_##p, i) }
166#define smsc_dbg_printf(sc, fmt, args...) \
168 if (smsc_debug > 0) \
169 device_printf((sc)->sc_ue.ue_dev, "debug: " fmt, ##args); \
172#define smsc_dbg_printf(sc, fmt, args...) do { } while (0)
175#define smsc_warn_printf(sc, fmt, args...) \
176 device_printf((sc)->sc_ue.ue_dev, "warning: " fmt, ##args)
178#define smsc_err_printf(sc, fmt, args...) \
179 device_printf((sc)->sc_ue.ue_dev, "error: " fmt, ##args)
181#define ETHER_IS_VALID(addr) \
182 (!ETHER_IS_MULTICAST(addr) && !ETHER_IS_ZERO(addr))
208static int smsc_ioctl(
struct ifnet *ifp, u_long cmd, caddr_t data);
216 .bufsize = 16 * (MCLBYTES + 16),
227 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
282 *
data = le32toh(buf);
353 }
while (((
usb_ticks_t)(ticks - start_ticks)) < max_ticks);
383 locked = mtx_owned(&sc->
sc_mtx);
394 for (i = 0; i < buflen; i++) {
407 }
while (((
usb_ticks_t)(ticks - start_ticks)) < max_ticks);
418 buf[i] = (
val & 0xff);
451 locked = mtx_owned(&sc->
sc_mtx);
473 return (
val & 0xFFFF);
501 locked = mtx_owned(&sc->
sc_mtx);
546 locked = mtx_owned(&sc->
sc_mtx);
551 if (mii == NULL || ifp == NULL ||
552 (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
557 if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
558 (IFM_ACTIVE | IFM_AVALID)) {
559 switch (IFM_SUBTYPE(mii->mii_media_active)) {
585 if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
590 if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
595 if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0)
638 struct mii_softc *miisc;
643 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
645 err = mii_mediachg(mii);
668 ifmr->ifm_active = mii->mii_media_active;
669 ifmr->ifm_status = mii->mii_media_status;
684static inline uint32_t
687 return (ether_crc32_be(
addr, ETHER_ADDR_LEN) >> 26) & 0x3f;
693 uint32_t hash, *hashtbl = arg;
696 hashtbl[hash >> 5] |= 1 << (hash & 0x1F);
716 uint32_t hashtbl[2] = { 0, 0 };
720 if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
767 (ifp->if_flags & IFF_PROMISC) ?
"en" :
"dis");
771 if (ifp->if_flags & IFF_PROMISC)
807 if ((ifp->if_capabilities & ifp->if_capenable) & IFCAP_RXCSUM)
810 val &= ~SMSC_COE_CTRL_RX_EN;
813 if ((ifp->if_capabilities & ifp->if_capenable) & IFCAP_TXCSUM)
816 val &= ~SMSC_COE_CTRL_TX_EN;
847 smsc_dbg_printf(sc,
"setting mac address to %02x:%02x:%02x:%02x:%02x:%02x\n",
911 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
929 ifp->if_drv_flags |= IFF_DRV_RUNNING;
967 if (actlen < (
sizeof(rxhdr) + ETHER_CRC_LEN))
977 while (off < actlen) {
980 off = ((off + 0x3) & ~0x3);
982 if ((off +
sizeof(rxhdr)) > actlen)
986 off += (
sizeof(rxhdr) + ETHER_ALIGN);
987 rxhdr = le32toh(rxhdr);
992 "off %d\n", rxhdr, pktlen, actlen, off);
997 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
999 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
1002 if ((pktlen < ETHER_HDR_LEN) || (pktlen > (actlen - off)))
1009 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
1012 if (pktlen > m->m_len) {
1015 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
1022 if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
1023 struct ether_header *eh;
1025 eh = mtod(m,
struct ether_header *);
1040 if ((be16toh(eh->ether_type) == ETHERTYPE_IP) &&
1041 (pktlen > ETHER_MIN_LEN)) {
1044 ip = (
struct ip *)(eh + 1);
1045 if ((ip->ip_v == IPVERSION) &&
1046 ((ip->ip_p == IPPROTO_TCP) ||
1047 (ip->ip_p == IPPROTO_UDP))) {
1049 m->m_pkthdr.csum_flags |= CSUM_DATA_VALID;
1055 &m->m_pkthdr.csum_data, 2);
1061 m->m_pkthdr.csum_data = ntohs(m->m_pkthdr.csum_data);
1064 m->m_pkthdr.csum_data);
1077 if (pktlen < (4 + ETHER_HDR_LEN)) {
1126 uint32_t frm_len = 0;
1131 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1137 (ifp->if_drv_flags & IFF_DRV_OACTIVE) != 0) {
1142 for (nframes = 0; nframes < 16 &&
1143 !IFQ_DRV_IS_EMPTY(&ifp->if_snd); nframes++) {
1144 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1157 txhdr = htole32(txhdr);
1161 txhdr = htole32(txhdr);
1168 frm_len += m->m_pkthdr.len;
1170 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1183 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1188 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1189 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1259 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1293 start_ticks = ticks;
1297 }
while ((bmcr & BMCR_RESET) && ((ticks - start_ticks) < max_ticks));
1299 if (((
usb_ticks_t)(ticks - start_ticks)) >= max_ticks) {
1305 ANAR_10 | ANAR_10_FD | ANAR_TX | ANAR_TX_FD |
1317 bmcr |= BMCR_STARTNEG;
1341 locked = mtx_owned(&sc->
sc_mtx);
1411 reg_val &= ~SMSC_HW_CFG_RXDOFF;
1431 device_printf(sc->
sc_ue.
ue_dev,
"chip 0x%04lx, rev. %04lx\n",
1510 if (cmd == SIOCSIFCAP) {
1512 ifr = (
struct ifreq *)
data;
1519 mask = ifr->ifr_reqcap ^ ifp->if_capenable;
1522 if ((mask & IFCAP_RXCSUM) != 0 &&
1523 (ifp->if_capabilities & IFCAP_RXCSUM) != 0) {
1524 ifp->if_capenable ^= IFCAP_RXCSUM;
1526 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1527 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1557 uint32_t mac_h, mac_l;
1622 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1626 IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
1627 ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
1628 IFQ_SET_READY(&ifp->if_snd);
1633 ifp->if_capabilities |= IFCAP_RXCSUM | IFCAP_VLAN_MTU;
1634 ifp->if_hwassist = 0;
1642 ifp->if_capenable = ifp->if_capabilities;
1647 BMSR_DEFCAPMASK, sc->
sc_phyno, MII_OFFSET_ANY, 0);
1692 uint8_t iface_index;
1699 mtx_init(&sc->
sc_mtx, device_get_nameunit(
dev), NULL, MTX_DEF);
1706 device_printf(
dev,
"error: allocating USB transfers failed\n");
1718 device_printf(
dev,
"error: could not attach interface\n");
1743 mtx_destroy(&sc->
sc_mtx);
1755 DEVMETHOD(bus_print_child, bus_generic_print_child),
1756 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, phy_type, CTLFLAG_RDTUN, &dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2/3 - ULPI/HSIC/INTERNAL/UTMI+")
SYSCTL_BOOL(_hw_usb_smsc, OID_AUTO, smsc_rx_packet_batching, CTLFLAG_RDTUN, &smsc_rx_packet_batching, 0, "If set, allows packet batching to increase throughput and latency. " "Else throughput and latency is decreased.")
static int smsc_wait_for_bits(struct smsc_softc *sc, uint32_t reg, uint32_t bits)
static driver_t smsc_driver
static int smsc_eeprom_read(struct smsc_softc *sc, uint16_t off, uint8_t *buf, uint16_t buflen)
static uether_fn_t smsc_stop
static device_probe_t smsc_probe
static miibus_statchg_t smsc_miibus_statchg
static uether_fn_t smsc_tick
static void smsc_ifmedia_sts(struct ifnet *, struct ifmediareq *)
static usb_callback_t smsc_bulk_write_callback
static int smsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
static int smsc_sethwcsum(struct smsc_softc *sc)
static uether_fn_t smsc_attach_post
static int smsc_read_reg(struct smsc_softc *sc, uint32_t off, uint32_t *data)
static miibus_writereg_t smsc_miibus_writereg
static const struct usb_device_id smsc_devs[]
static u_int smsc_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
DRIVER_MODULE(smsc, uhub, smsc_driver, smsc_devclass, NULL, 0)
static devclass_t smsc_devclass
static const struct usb_config smsc_config[SMSC_N_TRANSFER]
static device_detach_t smsc_detach
static uether_fn_t smsc_setmulti
#define ETHER_IS_VALID(addr)
#define smsc_dbg_printf(sc, fmt, args...)
static int smsc_ifmedia_upd(struct ifnet *)
static const struct usb_ether_methods smsc_ue_methods
static uint32_t smsc_hash(uint8_t addr[ETHER_ADDR_LEN])
static uether_fn_t smsc_init
MODULE_DEPEND(smsc, uether, 1, 1, 1)
static bool smsc_rx_packet_batching
static device_method_t smsc_methods[]
static int smsc_phy_init(struct smsc_softc *sc)
USB_PNP_HOST_INFO(smsc_devs)
#define smsc_warn_printf(sc, fmt, args...)
static int smsc_write_reg(struct smsc_softc *sc, uint32_t off, uint32_t data)
static uether_fn_t smsc_start
static usb_callback_t smsc_bulk_read_callback
static int smsc_chip_init(struct smsc_softc *sc)
static void smsc_reset(struct smsc_softc *sc)
static int smsc_setmacaddress(struct smsc_softc *sc, const uint8_t *addr)
static device_attach_t smsc_attach
SYSCTL_NODE(_hw_usb, OID_AUTO, smsc, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "USB smsc")
static uether_fn_t smsc_setpromisc
static miibus_readreg_t smsc_miibus_readreg
static int smsc_attach_post_sub(struct usb_ether *ue)
#define smsc_err_printf(sc, fmt, args...)
#define SMSC_PHY_INTR_STAT
#define SMSC_PHY_INTR_MASK
#define SMSC_LOCK_ASSERT(_sc, t)
#define SMSC_HW_CFG_RXDOFF
#define SMSC_PHY_INTR_LINK_DOWN
#define SMSC_ID_REV_CHIP_ID_MASK
#define SMSC_MAC_CSR_PRMS
#define SMSC_LED_GPIO_CFG_FDX_LED
#define SMSC_EEPROM_CMD_BUSY
#define SMSC_UR_WRITE_REG
#define SMSC_TX_CTRL_0_FIRST_SEG
#define SMSC_MAC_CSR_HPFILT
#define SMSC_MAC_CSR_MCPAS
#define SMSC_CONFIG_INDEX
#define SMSC_ID_REV_CHIP_REV_MASK
#define SMSC_TX_CTRL_0_LAST_SEG
#define SMSC_LED_GPIO_CFG
#define SMSC_MAC_CSR_RCVOWN
#define SMSC_MAC_CSR_FDPX
#define SMSC_PHY_INTR_ANEG_COMP
#define SMSC_TX_CTRL_1_PKT_LENGTH(x)
#define SMSC_COE_CTRL_TX_EN
#define SMSC_LED_GPIO_CFG_LNK_LED
#define SMSC_RX_STAT_FRM_LENGTH(x)
#define SMSC_EEPROM_CMD_ADDR_MASK
#define SMSC_MAC_CSR_RXEN
#define SMSC_RX_STAT_ERROR
#define SMSC_TX_CTRL_0_BUF_SIZE(x)
#define SMSC_EEPROM_CMD_TIMEOUT
#define SMSC_MAC_CSR_TXEN
#define SMSC_COE_CTRL_RX_EN
#define SMSC_RX_STAT_COLLISION
#define SMSC_PM_CTRL_PHY_RST
#define SMSC_LED_GPIO_CFG_SPD_LED
struct usb_xfer * sc_xfer[SMSC_N_TRANSFER]
enum usb_hc_mode usb_mode
struct usbd_lookup_info info
struct usb_device * device
uByte bConfigurationValue
struct usb_xfer_flags flags
void(* ue_mii_sts)(struct ifnet *, struct ifmediareq *)
uether_fn_t * ue_attach_post
const struct usb_ether_methods * ue_methods
struct usb_device * ue_udev
uint8_t ue_eaddr[ETHER_ADDR_LEN]
#define UT_WRITE_VENDOR_DEVICE
#define UT_READ_VENDOR_DEVICE
void usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset, const void *ptr, usb_frlength_t len)
void usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset, void *ptr, usb_frlength_t len)
struct usb_config_descriptor * usbd_get_config_descriptor(struct usb_device *udev)
enum usb_dev_speed usbd_get_speed(struct usb_device *udev)
const char * usbd_errstr(usb_error_t err)
void uether_rxflush(struct usb_ether *ue)
struct mbuf * uether_newbuf(void)
void uether_ifdetach(struct usb_ether *ue)
void * uether_getsc(struct usb_ether *ue)
struct ifnet * uether_getifp(struct usb_ether *ue)
uint8_t uether_pause(struct usb_ether *ue, unsigned int _ticks)
int uether_rxmbuf(struct usb_ether *ue, struct mbuf *m, unsigned int len)
struct mii_data * uether_getmii(struct usb_ether *ue)
int uether_ifmedia_upd(struct ifnet *ifp)
void uether_init(void *arg)
int uether_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
int uether_ifattach(struct usb_ether *ue)
void uether_start(struct ifnet *ifp)
#define uether_do_request(ue, req, data, timo)
void() uether_fn_t(struct usb_ether *)
int usb_fdt_get_mac_addr(device_t dev, struct usb_ether *ue)
int usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, struct usb_attach_arg *uaa)
usb_error_t usbd_req_set_config(struct usb_device *udev, struct mtx *mtx, uint8_t conf)
void usbd_transfer_submit(struct usb_xfer *xfer)
void usbd_xfer_set_frames(struct usb_xfer *xfer, usb_frcount_t n)
void usbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
void usbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex, usb_frlength_t len)
struct usb_page_cache * usbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
usb_error_t usbd_transfer_setup(struct usb_device *udev, const uint8_t *ifaces, struct usb_xfer **ppxfer, const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx)
void usbd_transfer_start(struct usb_xfer *xfer)
void usbd_xfer_set_frame_offset(struct usb_xfer *xfer, usb_frlength_t offset, usb_frcount_t frindex)
void * usbd_xfer_softc(struct usb_xfer *xfer)
void usbd_xfer_set_stall(struct usb_xfer *xfer)
void usbd_transfer_stop(struct usb_xfer *xfer)
void usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes, int *nframes)
usb_frlength_t usbd_xfer_max_len(struct usb_xfer *xfer)
void device_set_usb_desc(device_t dev)
#define USB_ST_TRANSFERRED
void usbd_m_copy_in(struct usb_page_cache *cache, usb_frlength_t dst_offset, struct mbuf *m, usb_size_t src_offset, usb_frlength_t src_len)
#define USB_MS_TO_TICKS(ms)
void() usb_callback_t(struct usb_xfer *, usb_error_t)
#define USB_GET_DRIVER_INFO(did)
#define USB_GET_STATE(xfer)