Index: sys/dev/usb/usbdevs =================================================================== --- sys/dev/usb/usbdevs (revision 224736) +++ sys/dev/usb/usbdevs (working copy) @@ -1044,6 +1044,7 @@ product ASIX AX88178 0x1780 AX88178 product ASIX AX88772 0x7720 AX88772 product ASIX AX88772A 0x772a AX88772A USB 2.0 10/100 Ethernet +product ASIX AX88772B 0x772b AX88772B USB 2.0 10/100 Ethernet /* ASUS products */ product ASUS2 USBN11 0x0b05 USB-N11 Index: sys/dev/usb/net/if_axereg.h =================================================================== --- sys/dev/usb/net/if_axereg.h (revision 224736) +++ sys/dev/usb/net/if_axereg.h (working copy) @@ -92,6 +92,12 @@ #define AXE_CMD_SW_PHY_STATUS 0x0021 #define AXE_CMD_SW_PHY_SELECT 0x0122 +/* AX88772A and AX88772B only. */ +#define AXE_CMD_READ_VLAN_CTRL 0x4027 +#define AXE_CMD_WRITE_VLAN_CTRL 0x4028 + +#define AXE_772B_CMD_RXCTL_WRITE_CFG 0x012A + #define AXE_SW_RESET_CLEAR 0x00 #define AXE_SW_RESET_RR 0x01 #define AXE_SW_RESET_RT 0x02 @@ -128,12 +134,18 @@ #define AXE_178_RXCMD_KEEP_INVALID_CRC 0x0004 #define AXE_RXCMD_BROADCAST 0x0008 #define AXE_RXCMD_MULTICAST 0x0010 +#define AXE_RXCMD_ACCEPT_RUNT 0x0040 /* AX88772B */ #define AXE_RXCMD_ENABLE 0x0080 #define AXE_178_RXCMD_MFB_MASK 0x0300 #define AXE_178_RXCMD_MFB_2048 0x0000 #define AXE_178_RXCMD_MFB_4096 0x0100 #define AXE_178_RXCMD_MFB_8192 0x0200 #define AXE_178_RXCMD_MFB_16384 0x0300 +#define AXE_772B_RXCMD_HDR_TYPE_0 0x0000 +#define AXE_772B_RXCMD_HDR_TYPE_1 0x0100 +#define AXE_772B_RXCMD_IPHDR_ALIGN 0x0200 +#define AXE_772B_RXCMD_ADD_CHKSUM 0x0400 +#define AXE_RXCMD_LOOPBACK 0x1000 /* AX88772A/AX88772B */ #define AXE_PHY_SEL_PRI 1 #define AXE_PHY_SEL_SEC 0 @@ -172,6 +184,21 @@ #define AXE_PHY_MODE_REALTEK_8251CL 0x0E #define AXE_PHY_MODE_ATTANSIC 0x40 +/* AX88772A/AX88772B only. */ +#define AXE_SW_PHY_SELECT_EXT 0x0000 +#define AXE_SW_PHY_SELECT_EMBEDDED 0x0001 +#define AXE_SW_PHY_SELECT_AUTO 0x0002 +#define AXE_SW_PHY_SELECT_SS_MII 0x0004 +#define AXE_SW_PHY_SELECT_SS_RVRS_MII 0x0008 +#define AXE_SW_PHY_SELECT_SS_RVRS_RMII 0x000C +#define AXE_SW_PHY_SELECT_SS_ENB 0x0010 + +/* AX88772A/AX88772B VLAN control. */ +#define AXE_VLAN_CTRL_ENB 0x00001000 +#define AXE_VLAN_CTRL_STRIP 0x00002000 +#define AXE_VLAN_CTRL_VID1_MASK 0x00000FFF +#define AXE_VLAN_CTRL_VID2_MASK 0x0FFF0000 + #define AXE_BULK_BUF_SIZE 16384 /* bytes */ #define AXE_CTL_READ 0x01 @@ -180,6 +207,24 @@ #define AXE_CONFIG_IDX 0 /* config number 1 */ #define AXE_IFACE_IDX 0 +/* EEPROM Map. */ +#define AXE_EEPROM_772B_NODE_ID 0x04 +#define AXE_EEPROM_772B_PHY_PWRCFG 0x18 + +struct ax88772b_mfb { + int byte_cnt; + int threshold; + int size; +}; +#define AX88772B_MFB_2K 0 +#define AX88772B_MFB_4K 1 +#define AX88772B_MFB_6K 2 +#define AX88772B_MFB_8K 3 +#define AX88772B_MFB_16K 4 +#define AX88772B_MFB_20K 5 +#define AX88772B_MFB_24K 6 +#define AX88772B_MFB_32K 7 + struct axe_sframe_hdr { uint16_t len; uint16_t ilen; @@ -203,12 +248,23 @@ int sc_flags; #define AXE_FLAG_LINK 0x0001 #define AXE_FLAG_772 0x1000 /* AX88772 */ -#define AXE_FLAG_178 0x2000 /* AX88178 */ +#define AXE_FLAG_772A 0x2000 /* AX88772A */ +#define AXE_FLAG_772B 0x4000 /* AX88772B */ +#define AXE_FLAG_178 0x8000 /* AX88178 */ uint8_t sc_ipgs[3]; uint8_t sc_phyaddrs[2]; + uint16_t sc_pwrcfg; + int sc_tx_bufsz; }; +#define AXE_IS_178_FAMILY(sc) \ + ((sc)->sc_flags & (AXE_FLAG_772 | AXE_FLAG_772A | AXE_FLAG_772B | \ + AXE_FLAG_178)) + +#define AXE_IS_772(sc) \ + ((sc)->sc_flags & (AXE_FLAG_772 | AXE_FLAG_772A | AXE_FLAG_772B)) + #define AXE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) #define AXE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) #define AXE_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->sc_mtx, t) Index: sys/dev/usb/net/if_axe.c =================================================================== --- sys/dev/usb/net/if_axe.c (revision 224736) +++ sys/dev/usb/net/if_axe.c (working copy) @@ -84,7 +84,6 @@ #include #include #include -#include #include #include #include @@ -142,11 +141,12 @@ AXE_DEV(ASIX, AX88172, 0), AXE_DEV(ASIX, AX88178, AXE_FLAG_178), AXE_DEV(ASIX, AX88772, AXE_FLAG_772), - AXE_DEV(ASIX, AX88772A, AXE_FLAG_772), + AXE_DEV(ASIX, AX88772A, AXE_FLAG_772A), + AXE_DEV(ASIX, AX88772B, AXE_FLAG_772B), AXE_DEV(ATEN, UC210T, 0), AXE_DEV(BELKIN, F5D5055, AXE_FLAG_178), AXE_DEV(BILLIONTON, USB2AR, 0), - AXE_DEV(CISCOLINKSYS, USB200MV2, AXE_FLAG_772), + AXE_DEV(CISCOLINKSYS, USB200MV2, AXE_FLAG_772A), AXE_DEV(COREGA, FETHER_USB2_TX, 0), AXE_DEV(DLINK, DUBE100, 0), AXE_DEV(DLINK, DUBE100B1, AXE_FLAG_772), @@ -191,6 +191,9 @@ static int axe_cmd(struct axe_softc *, int, int, int, void *); static void axe_ax88178_init(struct axe_softc *); static void axe_ax88772_init(struct axe_softc *); +static void axe_ax88772_phywake(struct axe_softc *); +static void axe_ax88772a_init(struct axe_softc *); +static void axe_ax88772b_init(struct axe_softc *); static int axe_get_phyno(struct axe_softc *, int); static const struct usb_config axe_config[AXE_N_TRANSFER] = { @@ -199,7 +202,8 @@ .type = UE_BULK, .endpoint = UE_ADDR_ANY, .direction = UE_DIR_OUT, - .bufsize = AXE_BULK_BUF_SIZE, + .frames = 16, + .bufsize = 16 * MCLBYTES, .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, .callback = axe_bulk_write_callback, .timeout = 10000, /* 10 seconds */ @@ -216,6 +220,17 @@ }, }; +static const struct ax88772b_mfb ax88772b_mfb_table[] = { + { 0x8000, 0x8001, 2048 }, + { 0x8100, 0x8147, 4096}, + { 0x8200, 0x81EB, 6144}, + { 0x8300, 0x83D7, 8192}, + { 0x8400, 0x851E, 16384}, + { 0x8500, 0x8666, 20480}, + { 0x8600, 0x87AE, 24576}, + { 0x8700, 0x8A3D, 32768} +}; + static device_method_t axe_methods[] = { /* Device interface */ DEVMETHOD(device_probe, axe_probe), @@ -302,7 +317,7 @@ axe_cmd(sc, AXE_CMD_MII_OPMODE_HW, 0, 0, NULL); val = le16toh(val); - if ((sc->sc_flags & AXE_FLAG_772) != 0 && reg == MII_BMSR) { + if (AXE_IS_772(sc) && reg == MII_BMSR) { /* * BMSR of AX88772 indicates that it supports extended * capability but the extended status register is @@ -384,7 +399,7 @@ val = 0; if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) val |= AXE_MEDIA_FULL_DUPLEX; - if (sc->sc_flags & (AXE_FLAG_178 | AXE_FLAG_772)) { + if (AXE_IS_178_FAMILY(sc)) { val |= AXE_178_MEDIA_RX_EN | AXE_178_MEDIA_MAGIC; if ((sc->sc_flags & AXE_FLAG_178) != 0) val |= AXE_178_MEDIA_ENCK; @@ -420,12 +435,12 @@ AXE_LOCK_ASSERT(sc, MA_OWNED); - if (mii->mii_instance) { - struct mii_softc *miisc; + if (mii->mii_instance) { + struct mii_softc *miisc; - LIST_FOREACH(miisc, &mii->mii_phys, mii_list) - mii_phy_reset(miisc); - } + LIST_FOREACH(miisc, &mii->mii_phys, mii_list) + mii_phy_reset(miisc); + } error = mii_mediachg(mii); return (error); } @@ -516,7 +531,7 @@ axe_ax88178_init(struct axe_softc *sc) { struct usb_ether *ue; - int gpio0, phymode; + int gpio0, ledmode, phymode; uint16_t eeprom, val; ue = &sc->sc_ue; @@ -530,14 +545,17 @@ if (eeprom == 0xffff) { phymode = AXE_PHY_MODE_MARVELL; gpio0 = 1; + ledmode = 0; } else { phymode = eeprom & 0x7f; gpio0 = (eeprom & 0x80) ? 0 : 1; + ledmode = eeprom >> 8; } if (bootverbose) - device_printf(sc->sc_ue.ue_dev, "EEPROM data : 0x%04x\n", - eeprom); + device_printf(sc->sc_ue.ue_dev, + "EEPROM data : 0x%04x, phymode : 0x%02x\n", eeprom, + phymode); /* Program GPIOs depending on PHY hardware. */ switch (phymode) { case AXE_PHY_MODE_MARVELL: @@ -549,11 +567,26 @@ AXE_GPIO_WRITE(AXE_GPIO0_EN | AXE_GPIO2_EN, hz / 4); AXE_GPIO_WRITE(AXE_GPIO0_EN | AXE_GPIO2 | AXE_GPIO2_EN, hz / 32); - } else + } else { AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO1 | - AXE_GPIO1_EN, hz / 32); + AXE_GPIO1_EN, hz / 3); + if (ledmode == 1) { + AXE_GPIO_WRITE(AXE_GPIO1_EN, hz / 3); + AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN, + hz / 3); + } else { + AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN | + AXE_GPIO2 | AXE_GPIO2_EN, hz / 32); + AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN | + AXE_GPIO2_EN, hz / 4); + AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN | + AXE_GPIO2 | AXE_GPIO2_EN, hz / 32); + } + } break; case AXE_PHY_MODE_CICADA: + case AXE_PHY_MODE_CICADA_V2: + case AXE_PHY_MODE_CICADA_V2_ASIX: if (gpio0 == 1) AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO0 | AXE_GPIO0_EN, hz / 32); @@ -610,7 +643,6 @@ axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); } -#undef AXE_GPIO_WRITE static void axe_ax88772_init(struct axe_softc *sc) @@ -654,6 +686,91 @@ } static void +axe_ax88772_phywake(struct axe_softc *sc) +{ + struct usb_ether *ue; + + ue = &sc->sc_ue; + if (sc->sc_phyno == AXE_772_PHY_NO_EPHY) { + /* Manually select internal(embedded) PHY - MAC mode. */ + axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, AXE_SW_PHY_SELECT_SS_ENB | + AXE_SW_PHY_SELECT_EMBEDDED | AXE_SW_PHY_SELECT_SS_MII, + NULL); + uether_pause(&sc->sc_ue, hz / 32); + } else { + /* + * Manually select external PHY - MAC mode. + * Reverse MII/RMII is for AX88772A PHY mode. + */ + axe_cmd(sc, AXE_CMD_SW_PHY_SELECT, 0, AXE_SW_PHY_SELECT_SS_ENB | + AXE_SW_PHY_SELECT_EXT | AXE_SW_PHY_SELECT_SS_MII, NULL); + uether_pause(&sc->sc_ue, hz / 32); + } + /* Take PHY out of power down. */ + axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_IPPD | + AXE_SW_RESET_IPRL, NULL); + uether_pause(&sc->sc_ue, hz / 4); + axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_IPRL, NULL); + uether_pause(&sc->sc_ue, hz); + axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_CLEAR, NULL); + uether_pause(&sc->sc_ue, hz / 32); + axe_cmd(sc, AXE_CMD_SW_RESET_REG, 0, AXE_SW_RESET_IPRL, NULL); + uether_pause(&sc->sc_ue, hz / 32); +} + +static void +axe_ax88772a_init(struct axe_softc *sc) +{ + struct usb_ether *ue; + + ue = &sc->sc_ue; + /* Reload EEPROM. */ + AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM, hz / 32); + axe_ax88772_phywake(sc); + /* Stop MAC. */ + axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); +} + +static void +axe_ax88772b_init(struct axe_softc *sc) +{ + struct usb_ether *ue; + uint16_t eeprom; + uint8_t *eaddr; + int i; + + ue = &sc->sc_ue; + /* Reload EEPROM. */ + AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM, hz / 32); + /* + * Save PHY power saving configuration(high byte) and + * clear EEPROM checksum value(low byte). + */ + axe_cmd(sc, AXE_CMD_SROM_READ, 0, AXE_EEPROM_772B_PHY_PWRCFG, &eeprom); + sc->sc_pwrcfg = le16toh(eeprom) & 0xFF00; + + /* + * Auto-loaded default station address from internal ROM is + * 00:00:00:00:00:00 such that an explicit access to EEPROM + * is required to get real station address. + */ + eaddr = ue->ue_eaddr; + for (i = 0; i < ETHER_ADDR_LEN / 2; i++) { + axe_cmd(sc, AXE_CMD_SROM_READ, 0, AXE_EEPROM_772B_NODE_ID + i, + &eeprom); + eeprom = le16toh(eeprom); + *eaddr++ = (uint8_t)(eeprom & 0xFF); + *eaddr++ = (uint8_t)((eeprom >> 8) & 0xFF); + } + /* Wakeup PHY. */ + axe_ax88772_phywake(sc); + /* Stop MAC. */ + axe_cmd(sc, AXE_CMD_RXCTL_WRITE, 0, 0, NULL); +} + +#undef AXE_GPIO_WRITE + +static void axe_reset(struct axe_softc *sc) { struct usb_config_descriptor *cd; @@ -668,6 +785,16 @@ /* Wait a little while for the chip to get its brains in order. */ uether_pause(&sc->sc_ue, hz / 100); + + /* Reinitialize controller to achieve full reset. */ + if (sc->sc_flags & AXE_FLAG_178) + axe_ax88178_init(sc); + else if (sc->sc_flags & AXE_FLAG_772) + axe_ax88772_init(sc); + else if (sc->sc_flags & AXE_FLAG_772A) + axe_ax88772a_init(sc); + else if (sc->sc_flags & AXE_FLAG_772B) + axe_ax88772b_init(sc); } static void @@ -691,23 +818,35 @@ sc->sc_phyno = 0; } - if (sc->sc_flags & AXE_FLAG_178) + /* Initialize controller and get station address. */ + if (sc->sc_flags & AXE_FLAG_178) { axe_ax88178_init(sc); - else if (sc->sc_flags & AXE_FLAG_772) + sc->sc_tx_bufsz = 16 * 1024; + axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, ue->ue_eaddr); + } else if (sc->sc_flags & AXE_FLAG_772) { axe_ax88772_init(sc); - - /* - * Get station address. - */ - if (sc->sc_flags & (AXE_FLAG_178 | AXE_FLAG_772)) + sc->sc_tx_bufsz = 8 * 1024; axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, ue->ue_eaddr); - else + } else if (sc->sc_flags & AXE_FLAG_772A) { + axe_ax88772a_init(sc); + sc->sc_tx_bufsz = 8 * 1024; + axe_cmd(sc, AXE_178_CMD_READ_NODEID, 0, 0, ue->ue_eaddr); + } else if (sc->sc_flags & AXE_FLAG_772B) { + axe_ax88772b_init(sc); + sc->sc_tx_bufsz = 8 * 1024; + } else axe_cmd(sc, AXE_172_CMD_READ_NODEID, 0, 0, ue->ue_eaddr); /* * Fetch IPG values. */ - axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, sc->sc_ipgs); + if (sc->sc_flags & (AXE_FLAG_772A | AXE_FLAG_772B)) { + /* Set IPG values. */ + sc->sc_ipgs[0] = 0x15; + sc->sc_ipgs[1] = 0x16; + sc->sc_ipgs[2] = 0x1A; + } else + axe_cmd(sc, AXE_CMD_READ_IPG012, 0, 0, sc->sc_ipgs); } /* @@ -810,7 +949,7 @@ err = 0; pc = usbd_xfer_get_frame(xfer, 0); - if (sc->sc_flags & (AXE_FLAG_772 | AXE_FLAG_178)) { + if (AXE_IS_178_FAMILY(sc)) { while (pos < actlen) { if ((pos + sizeof(hdr)) > actlen) { /* too little data */ @@ -875,7 +1014,7 @@ struct ifnet *ifp = uether_getifp(&sc->sc_ue); struct usb_page_cache *pc; struct mbuf *m; - int pos; + int nframes, pos; switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: @@ -892,40 +1031,34 @@ */ return; } - pos = 0; - pc = usbd_xfer_get_frame(xfer, 0); - while (1) { - + for (nframes = 0; nframes < 16 && + !IFQ_DRV_IS_EMPTY(&ifp->if_snd); nframes++) { IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - - if (m == NULL) { - if (pos > 0) - break; /* send out data */ - return; - } - if (m->m_pkthdr.len > MCLBYTES) { - m->m_pkthdr.len = MCLBYTES; - } - if (sc->sc_flags & (AXE_FLAG_772 | AXE_FLAG_178)) { - + if (m == NULL) + break; + usbd_xfer_set_frame_offset(xfer, nframes * MCLBYTES, + nframes); + pos = 0; + pc = usbd_xfer_get_frame(xfer, nframes); + if (AXE_IS_178_FAMILY(sc)) { hdr.len = htole16(m->m_pkthdr.len); hdr.ilen = ~hdr.len; - usbd_copy_in(pc, pos, &hdr, sizeof(hdr)); - pos += sizeof(hdr); - - /* - * NOTE: Some drivers force a short packet - * by appending a dummy header with zero - * length at then end of the USB transfer. - * This driver uses the - * USB_FORCE_SHORT_XFER flag instead. - */ + usbd_m_copy_in(pc, pos, m, 0, m->m_pkthdr.len); + pos += m->m_pkthdr.len; + if ((pos % 512) == 0) { + hdr.len = 0; + hdr.ilen = 0xffff; + usbd_copy_in(pc, pos, &hdr, + sizeof(hdr)); + pos += sizeof(hdr); + } + } else { + usbd_m_copy_in(pc, pos, m, 0, m->m_pkthdr.len); + pos += m->m_pkthdr.len; } - usbd_m_copy_in(pc, pos, m, 0, m->m_pkthdr.len); - pos += m->m_pkthdr.len; /* * XXX @@ -946,22 +1079,16 @@ m_freem(m); - if (sc->sc_flags & (AXE_FLAG_772 | AXE_FLAG_178)) { - if (pos > (AXE_BULK_BUF_SIZE - MCLBYTES - sizeof(hdr))) { - /* send out frame(s) */ - break; - } - } else { - /* send out frame */ - break; - } + /* Set frame length. */ + usbd_xfer_set_frame_len(xfer, nframes, pos); } - - usbd_xfer_set_frame_len(xfer, 0, pos); - usbd_transfer_submit(xfer); - ifp->if_drv_flags |= IFF_DRV_OACTIVE; + if (nframes != 0) { + usbd_xfer_set_frames(xfer, nframes); + usbd_transfer_submit(xfer); + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + } return; - + /* NOTREACHED */ default: /* Error */ DPRINTFN(11, "transfer error, %s\n", usbd_errstr(error)); @@ -1016,37 +1143,54 @@ AXE_LOCK_ASSERT(sc, MA_OWNED); + if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) + return; + /* Cancel pending I/O */ axe_stop(ue); + axe_reset(sc); + /* Set MAC address. */ - if (sc->sc_flags & (AXE_FLAG_178 | AXE_FLAG_772)) + if (AXE_IS_178_FAMILY(sc)) axe_cmd(sc, AXE_178_CMD_WRITE_NODEID, 0, 0, IF_LLADDR(ifp)); else axe_cmd(sc, AXE_172_CMD_WRITE_NODEID, 0, 0, IF_LLADDR(ifp)); /* Set transmitter IPG values */ - if (sc->sc_flags & (AXE_FLAG_178 | AXE_FLAG_772)) { + if (AXE_IS_178_FAMILY(sc)) axe_cmd(sc, AXE_178_CMD_WRITE_IPG012, sc->sc_ipgs[2], (sc->sc_ipgs[1] << 8) | (sc->sc_ipgs[0]), NULL); - } else { + else { axe_cmd(sc, AXE_172_CMD_WRITE_IPG0, 0, sc->sc_ipgs[0], NULL); axe_cmd(sc, AXE_172_CMD_WRITE_IPG1, 0, sc->sc_ipgs[1], NULL); axe_cmd(sc, AXE_172_CMD_WRITE_IPG2, 0, sc->sc_ipgs[2], NULL); } - /* Enable receiver, set RX mode */ + /* AX88772B uses different maximum frame burst configuration. */ + if (sc->sc_flags & AXE_FLAG_772B) + axe_cmd(sc, AXE_772B_CMD_RXCTL_WRITE_CFG, + ax88772b_mfb_table[AX88772B_MFB_16K].threshold, + ax88772b_mfb_table[AX88772B_MFB_16K].byte_cnt, NULL); + + /* Enable receiver, set RX mode. */ rxmode = (AXE_RXCMD_MULTICAST | AXE_RXCMD_ENABLE); - if (sc->sc_flags & (AXE_FLAG_178 | AXE_FLAG_772)) { -#if 0 - rxmode |= AXE_178_RXCMD_MFB_2048; /* chip default */ -#else - /* - * Default Rx buffer size is too small to get - * maximum performance. - */ - rxmode |= AXE_178_RXCMD_MFB_16384; -#endif + if (AXE_IS_178_FAMILY(sc)) { + if (sc->sc_flags & AXE_FLAG_772B) { + /* + * Select RX header format type 1. Aligning IP + * header on 4 byte boundary is not needed + * because we always copy the received frame in + * RX handler. + */ + rxmode |= AXE_772B_RXCMD_HDR_TYPE_1; + } else { + /* + * Default Rx buffer size is too small to get + * maximum performance. + */ + rxmode |= AXE_178_RXCMD_MFB_16384; + } } else { rxmode |= AXE_172_RXCMD_UNICAST; } @@ -1066,6 +1210,8 @@ usbd_xfer_set_stall(sc->sc_xfer[AXE_BULK_DT_WR]); ifp->if_drv_flags |= IFF_DRV_RUNNING; + /* Switch to selected media. */ + axe_ifmedia_upd(ifp); axe_start(ue); } @@ -1107,6 +1253,4 @@ */ usbd_transfer_stop(sc->sc_xfer[AXE_BULK_DT_WR]); usbd_transfer_stop(sc->sc_xfer[AXE_BULK_DT_RD]); - - axe_reset(sc); }