84#include <sys/condvar.h>
85#include <sys/endian.h>
86#include <sys/kernel.h>
88#include <sys/malloc.h>
90#include <sys/module.h>
92#include <sys/socket.h>
93#include <sys/sockio.h>
94#include <sys/sysctl.h>
98#include <net/if_var.h>
99#include <net/ethernet.h>
100#include <net/if_types.h>
101#include <net/if_media.h>
102#include <net/if_vlan_var.h>
104#include <dev/mii/mii.h>
105#include <dev/mii/miivar.h>
112#define USB_DEBUG_VAR axe_debug
119#include "miibus_if.h"
134#define AXE_178_MAX_FRAME_BURST 1
136#define AXE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP)
139static int axe_debug = 0;
141static SYSCTL_NODE(_hw_usb, OID_AUTO, axe, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
151#define AXE_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
163 AXE_DEV(BILLIONTON, USB2AR, 0),
165 AXE_DEV(COREGA, FETHER_USB2_TX, 0),
184 AXE_DEV(SYSTEMTALKS, SGCX2UL, 0),
217static int axe_ioctl(
struct ifnet *, u_long, caddr_t);
229 .bufsize = 16 * MCLBYTES,
230 .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
240 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
247 { 0x8000, 0x8001, 2048 },
248 { 0x8100, 0x8147, 4096},
249 { 0x8200, 0x81EB, 6144},
250 { 0x8300, 0x83D7, 8192},
251 { 0x8400, 0x851E, 16384},
252 { 0x8500, 0x8666, 20480},
253 { 0x8600, 0x87AE, 24576},
254 { 0x8700, 0x8A3D, 32768}
329 locked = mtx_owned(&sc->
sc_mtx);
360 locked = mtx_owned(&sc->
sc_mtx);
377 struct mii_data *mii =
GET_MII(sc);
382 locked = mtx_owned(&sc->
sc_mtx);
387 if (mii == NULL || ifp == NULL ||
388 (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
392 if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
393 (IFM_ACTIVE | IFM_AVALID)) {
394 switch (IFM_SUBTYPE(mii->mii_media_active)) {
414 if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
417 if ((IFM_OPTIONS(mii->mii_media_active) &
418 IFM_ETH_TXPAUSE) != 0)
420 if ((IFM_OPTIONS(mii->mii_media_active) &
421 IFM_ETH_RXPAUSE) != 0)
429 switch (IFM_SUBTYPE(mii->mii_media_active)) {
443 device_printf(
dev,
"media change failed, error %d\n", err);
456 struct mii_data *mii =
GET_MII(sc);
457 struct mii_softc *miisc;
462 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
464 error = mii_mediachg(mii);
475 struct mii_data *mii =
GET_MII(sc);
479 ifmr->ifm_active = mii->mii_media_active;
480 ifmr->ifm_status = mii->mii_media_status;
487 uint8_t *hashtbl = arg;
490 h = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26;
491 hashtbl[h / 8] |= 1 << (h % 8);
502 uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
507 rxmode = le16toh(rxmode);
509 if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
514 rxmode &= ~AXE_RXCMD_ALLMULTI;
546#define AXE_GPIO_WRITE(x, y) do { \
547 axe_cmd(sc, AXE_CMD_WRITE_GPIO, 0, (x), NULL); \
548 uether_pause(ue, (y)); \
555 int gpio0, ledmode, phymode;
556 uint16_t eeprom,
val;
562 eeprom = le16toh(eeprom);
566 if (eeprom == 0xffff) {
571 phymode = eeprom & 0x7f;
572 gpio0 = (eeprom & 0x80) ? 0 : 1;
573 ledmode = eeprom >> 8;
578 "EEPROM data : 0x%04x, phymode : 0x%02x\n", eeprom,
768 sc->
sc_pwrcfg = le16toh(eeprom) & 0xFF00;
776 for (i = 0; i < ETHER_ADDR_LEN / 2; i++) {
779 eeprom = le16toh(eeprom);
780 *eaddr++ = (uint8_t)(eeprom & 0xFF);
781 *eaddr++ = (uint8_t)((eeprom >> 8) & 0xFF);
802 DPRINTF(
"reset failed (ignored)\n");
828 device_printf(sc->
sc_ue.
ue_dev,
"PHYADDR 0x%02x:0x%02x\n",
835 "no valid PHY address found, assuming PHY address 0\n");
876 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
880 IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
881 ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
882 IFQ_SET_READY(&ifp->if_snd);
885 ifp->if_capabilities |= IFCAP_VLAN_MTU;
887 ifp->if_capabilities |= IFCAP_TXCSUM | IFCAP_RXCSUM;
899 ifp->if_capenable = ifp->if_capabilities;
901 adv_pause = MIIF_DOPAUSE;
907 BMSR_DEFCAPMASK, sc->
sc_phyno, MII_OFFSET_ANY, adv_pause);
948 mtx_init(&sc->
sc_mtx, device_get_nameunit(
dev), NULL, MTX_DEF);
954 device_printf(
dev,
"allocating USB transfers failed\n");
966 device_printf(
dev,
"could not attach interface\n");
989#if (AXE_BULK_BUF_SIZE >= 0x10000)
990#error "Please update axe_bulk_read_callback()!"
1041 while (pos < actlen) {
1042 if ((
int)(pos +
sizeof(hdr)) > actlen) {
1056 if (pos +
len > actlen) {
1065 while (pos < actlen) {
1066 if ((
int)(pos +
sizeof(csum_hdr)) > actlen) {
1073 csum_hdr.
len = le16toh(csum_hdr.
len);
1074 csum_hdr.
ilen = le16toh(csum_hdr.
ilen);
1090 if (pos +
len > actlen) {
1095 axe_rxeof(ue, pc, pos +
sizeof(csum_hdr),
1103 if_inc_counter(ue->
ue_ifp, IFCOUNTER_IERRORS, 1);
1111 struct ifnet *ifp = ue->
ue_ifp;
1114 if (len < ETHER_HDR_LEN || len > MCLBYTES - ETHER_ALIGN) {
1115 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
1119 m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1121 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
1124 m->m_len = m->m_pkthdr.len = MCLBYTES;
1125 m_adj(m, ETHER_ALIGN);
1129 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
1130 m->m_pkthdr.rcvif = ifp;
1131 m->m_pkthdr.len = m->m_len =
len;
1136 m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED |
1142 m->m_pkthdr.csum_flags |=
1143 CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
1144 m->m_pkthdr.csum_data = 0xffff;
1149 (void)mbufq_enqueue(&ue->
ue_rxq, m);
1153#if ((AXE_BULK_BUF_SIZE >= 0x10000) || (AXE_BULK_BUF_SIZE < (MCLBYTES+4)))
1154#error "Please update axe_bulk_write_callback()!"
1169 DPRINTFN(11,
"transfer complete\n");
1170 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1175 (ifp->if_drv_flags & IFF_DRV_OACTIVE) != 0) {
1183 for (nframes = 0; nframes < 16 &&
1184 !IFQ_DRV_IS_EMPTY(&ifp->if_snd); nframes++) {
1185 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1193 hdr.
len = htole16(m->m_pkthdr.len);
1194 hdr.
ilen = ~hdr.len;
1201 if (ifp->if_capabilities & IFCAP_TXCSUM) {
1202 if ((m->m_pkthdr.csum_flags &
1213 pos += m->m_pkthdr.len;
1214 if ((pos % 512) == 0) {
1223 pos += m->m_pkthdr.len;
1235 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
1251 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1256 DPRINTFN(11,
"transfer error, %s\n",
1259 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1260 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1275 struct mii_data *mii =
GET_MII(sc);
1304 uint16_t csum1, csum2;
1313 if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
1319 if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
1336 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
1359 (ifp->if_capenable & IFCAP_RXCSUM) != 0) {
1393 if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
1407 if (ifp->if_flags & IFF_PROMISC)
1410 if (ifp->if_flags & IFF_BROADCAST)
1420 ifp->if_drv_flags |= IFF_DRV_RUNNING;
1434 rxmode = le16toh(rxmode);
1436 if (ifp->if_flags & IFF_PROMISC) {
1439 rxmode &= ~AXE_RXCMD_PROMISC;
1455 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1471 int error, mask, reinit;
1474 ifr = (
struct ifreq *)
data;
1477 if (cmd == SIOCSIFCAP) {
1479 mask = ifr->ifr_reqcap ^ ifp->if_capenable;
1480 if ((mask & IFCAP_TXCSUM) != 0 &&
1481 (ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
1482 ifp->if_capenable ^= IFCAP_TXCSUM;
1483 if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
1486 ifp->if_hwassist &= ~AXE_CSUM_FEATURES;
1489 if ((mask & IFCAP_RXCSUM) != 0 &&
1490 (ifp->if_capabilities & IFCAP_RXCSUM) != 0) {
1491 ifp->if_capenable ^= IFCAP_RXCSUM;
1494 if (reinit > 0 && ifp->if_drv_flags & IFF_DRV_RUNNING)
1495 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
static SYSCTL_NODE(_hw_usb, OID_AUTO, dwc_otg, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "USB DWC OTG")
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+")
static uether_fn_t axe_attach_post
static int axe_get_phyno(struct axe_softc *, int)
static void axe_ax88772a_init(struct axe_softc *)
static miibus_statchg_t axe_miibus_statchg
static u_int axe_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
static int axe_cmd(struct axe_softc *, int, int, int, void *)
static device_probe_t axe_probe
static const STRUCT_USB_HOST_ID axe_devs[]
static uether_fn_t axe_stop
static uether_fn_t axe_start
static int axe_rx_frame(struct usb_ether *, struct usb_page_cache *, int)
static void axe_ax88772_init(struct axe_softc *)
static usb_callback_t axe_bulk_read_callback
static usb_callback_t axe_bulk_write_callback
static void axe_ax88772b_init(struct axe_softc *)
#define AXE_CSUM_FEATURES
static const struct usb_ether_methods axe_ue_methods
static int axe_attach_post_sub(struct usb_ether *)
DRIVER_MODULE(axe, uhub, axe_driver, axe_devclass, NULL, 0)
static void axe_ax88772_phywake(struct axe_softc *)
MODULE_DEPEND(axe, uether, 1, 1, 1)
static device_method_t axe_methods[]
static void axe_reset(struct axe_softc *sc)
static int axe_ioctl(struct ifnet *, u_long, caddr_t)
static void axe_ax88178_init(struct axe_softc *)
static devclass_t axe_devclass
static int axe_rxeof(struct usb_ether *, struct usb_page_cache *, unsigned int offset, unsigned int, struct axe_csum_hdr *)
static device_detach_t axe_detach
static void axe_ifmedia_sts(struct ifnet *, struct ifmediareq *)
static const struct usb_config axe_config[AXE_N_TRANSFER]
static const struct ax88772b_mfb ax88772b_mfb_table[]
static uether_fn_t axe_setpromisc
static uether_fn_t axe_tick
static miibus_readreg_t axe_miibus_readreg
#define AXE_GPIO_WRITE(x, y)
static driver_t axe_driver
static device_attach_t axe_attach
static uether_fn_t axe_init
static uether_fn_t axe_setmulti
static int axe_ifmedia_upd(struct ifnet *)
static void axe_csum_cfg(struct usb_ether *)
USB_PNP_HOST_INFO(axe_devs)
static miibus_writereg_t axe_miibus_writereg
#define AXE_178_CMD_WRITE_NODEID
#define AXE_772B_CMD_WRITE_RXCSUM
#define AXE_CSUM_HDR_L4_CSUM_ERR
#define AXE_PHY_MODE_REALTEK_8211CL
#define AXE_178_MEDIA_RX_EN
#define AXE_CSUM_HDR_L3_TYPE_IPV4
#define AXE_SW_PHY_SELECT_EXT
#define AXE_CMD_MII_READ_REG
#define AXE_178_MEDIA_GMII
#define AXE_178_MEDIA_TXFLOW_CONTROL_EN
#define AXE_CMD_RXCTL_WRITE
#define AXE_CMD_MII_OPMODE_SW
#define AXE_TX_CSUM_PSEUDO_HDR
#define AXE_SW_RESET_IPRL
#define AXE_172_CMD_WRITE_IPG2
#define AXE_PHY_MODE_REALTEK_8251CL
#define AXE_PHY_MODE_CICADA_V2
#define AXE_EEPROM_772B_NODE_ID
#define AXE_PHY_MODE_CICADA_V2_ASIX
#define AXE_LOCK_ASSERT(_sc, t)
#define AXE_CMD_SROM_READ
#define AXE_CMD_SW_RESET_REG
#define AXE_CSUM_HDR_L4_TYPE_UDP
#define AXE_CMD_READ_PHYID
#define AXE_CMD_MII_WRITE_REG
#define AXE_172_CMD_WRITE_IPG1
#define AXE_772B_RXCMD_HDR_TYPE_1
#define AXE_178_MEDIA_100TX
#define AXE_SW_RESET_IPPD
#define AXE_772B_CMD_WRITE_TXCSUM
#define AXE_178_RXCMD_MFB_16384
#define AXE_CMD_READ_IPG012
#define AXE_RXCMD_ALLMULTI
#define AXE_172_CMD_WRITE_IPG0
#define AXE_CMD_SW_PHY_SELECT
#define AXE_178_MEDIA_RXFLOW_CONTROL_EN
#define AXE_SW_PHY_SELECT_SS_ENB
#define AXE_CMD_WRITE_MCAST
#define AXE_PHY_MODE_CICADA
#define AXE_CSUM_HDR_L4_TYPE_TCP
#define AXE_RXCMD_MULTICAST
#define AXE_SW_PHY_SELECT_SS_MII
#define AXE_FLAG_CSUM_FRAME
#define AXE_EEPROM_772B_PHY_PWRCFG
#define AXE_772_PHY_NO_EPHY
#define AXE_SW_RESET_CLEAR
#define AXE_178_CMD_READ_NODEID
#define AXE_CMD_WRITE_MEDIA
#define AXE_772B_CMD_RXCTL_WRITE_CFG
#define AXE_GPIO_RELOAD_EEPROM
#define AXE_CSUM_HDR_L4_TYPE_MASK
#define AXE_178_MEDIA_ENCK
#define AXE_178_RESET_MAGIC
#define AXE_RXCMD_PROMISC
#define AXE_CSUM_HDR_LEN_MASK
#define AXE_PHY_MODE_REALTEK_8211BN
#define AXE_CSUM_RXBYTES(x)
#define AXE_FLAG_STD_FRAME
#define AXE_CMD_MII_OPMODE_HW
#define AXE_178_CMD_WRITE_IPG012
#define AXE_172_CMD_READ_NODEID
#define AXE_CMD_SROM_WR_DISABLE
#define AXE_CSUM_HDR_L3_CSUM_ERR
#define AXE_IS_178_FAMILY(sc)
#define AXE_178_MEDIA_MAGIC
#define AXE_CMD_WRITE_GPIO
#define AXE_RXCMD_BROADCAST
#define AXE_CMD_RXCTL_READ
#define AXE_172_CMD_WRITE_NODEID
#define AXE_MEDIA_FULL_DUPLEX
#define PHY_TYPE_100_HOME
#define AXE_CMD_SROM_WR_ENABLE
#define AXE_PHY_MODE_AGERE
#define AXE_PHY_MODE_MARVELL
#define AXE_772B_RXCMD_IPHDR_ALIGN
#define AXE_SW_PHY_SELECT_EMBEDDED
#define AXE_172_RXCMD_UNICAST
#define AXE_CMD_IS_WRITE(x)
struct usb_xfer * sc_xfer[AXE_N_TRANSFER]
enum usb_hc_mode usb_mode
struct usbd_lookup_info info
struct usb_device * device
uByte bConfigurationValue
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)
const char * usbd_errstr(usb_error_t err)
void uether_rxflush(struct usb_ether *ue)
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_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 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)
void() usb_callback_t(struct usb_xfer *, usb_error_t)
#define STRUCT_USB_HOST_ID
#define USB_GET_DRIVER_INFO(did)
#define USB_GET_STATE(xfer)