On 25/02/19(Mon) 14:52, Nils Frohberg wrote: > Hi, > > as mentioned previously, I'm looking into axen(4). While searching > for the cause of a panic (fixed since, thanks mpi@) I started to > rewrite parts of the driver. References were mainly the FreeBSD and > Linux drivers.
Please try to isolate parts of your diff that fixes issues and cosmetic changes. The simpler it gets the easier it is for us to review it. > I didn't get around to much testing/debugging lately, therefore I > wanted to share the current state (diff below). > > The current state works a lot better than previously (for me). I > used to have a huge amount of ierrs (aprrox. 1 ierr per ipkt) and > often no packets would be transferred at all (or stop being transferred > after some time). Do you know why? What were the problems? > This box hosts backups (rsync and TimeMachine), so it gets its fair > share of traffic. I could reduce the ierrs to ~2100 with 5d uptime, > and the packets keep flowing: > > $ netstat -niI axen0 > Name Mtu Network Address Ipkts Ierrs Opkts Oerrs > Colls > axen0 1500 <Link> 94:c6:91:1f:85:a5 141199356 2099 112289969 0 > 0 > $ uptime > 7:15PM up 5 days, 9:57, 3 users, load averages: 0.11, 0.13, 0.14 > $ > > But there a still a few problems: > > 1) There are still ierrs. These happen when the rx path can't > allocate mbufs (cf. diff below for DPRINTF): > axen0: could not allocate rx mbuf (2 total, 2 remaining) > axen0: could not allocate rx mbuf (3 total, 3 remaining) > axen0: could not allocate rx mbuf (2 total, 2 remaining) > axen0: could not allocate rx mbuf (1 total, 1 remaining) Look at the pools when this happen, what do you see? What is the size of `pkt_len' when this happen? > 2) If the adapter is plugged into a USB 3 port at boot, it will > return 0x42 when aked for AXEN_PHYSICAL_LINK_STATUS, ie. > (AXEN_EPHY_1000|AXEN_USB_HS). The adapter most often then simply > doesn't receive packets. If I plug in the adapter after boot is > complete, 0x44 is returned (AXEN_EPHY_1000|AXEN_USB_SS), as expected. > I'm not sure if I'm still missing something in init (probably) or > if this results from something higher in the stack (xhci?). > (Didn't test USB 2 or lower.) Do you see any difference in 'usbdevs -vv' output during the two cases? > > 3) Transfer speed > > Here's the diff: > > Index: dev/usb/if_axen.c > =================================================================== > RCS file: /cvs/src/sys/dev/usb/if_axen.c,v > retrieving revision 1.26 > diff -u -p -r1.26 if_axen.c > --- dev/usb/if_axen.c 5 Dec 2018 15:54:58 -0000 1.26 > +++ dev/usb/if_axen.c 12 Feb 2019 18:26:48 -0000 > @@ -97,7 +97,7 @@ const struct cfattach axen_ca = { > > int axen_tx_list_init(struct axen_softc *); > int axen_rx_list_init(struct axen_softc *); > -struct mbuf *axen_newbuf(void); > +struct mbuf *axen_newbuf(struct axen_softc *); > int axen_encap(struct axen_softc *, struct mbuf *, int); > void axen_rxeof(struct usbd_xfer *, void *, usbd_status); > void axen_txeof(struct usbd_xfer *, void *, usbd_status); > @@ -121,6 +121,13 @@ void axen_unlock_mii(struct axen_softc * > > void axen_ax88179_init(struct axen_softc *); > > +struct axen_qctrl axen_bulk_size[] = { > + { 7, 0x4f, 0x00, AXEN_BUFSZ_SS, 0xff }, > + { 7, 0x20, 0x03, AXEN_BUFSZ_HS, 0xff }, > + { 7, 0xae, 0x07, AXEN_BUFSZ_LS, 0xff }, > + { 7, 0xcc, 0x4c, AXEN_BUFSZ_LS, 0x08 } > +}; > + > /* Get exclusive access to the MII registers */ > void > axen_lock_mii(struct axen_softc *sc) > @@ -156,7 +163,7 @@ axen_cmd(struct axen_softc *sc, int cmd, > USETW(req.wLength, AXEN_CMD_LEN(cmd)); > > err = usbd_do_request(sc->axen_udev, &req, buf); > - DPRINTFN(5, ("axen_cmd: cmd 0x%04x val 0x%04x len %d\n", > + DPRINTFN(15, ("axen_cmd: cmd 0x%04x val 0x%04x len %d\n", > cmd, val, AXEN_CMD_LEN(cmd))); > > if (err) { > @@ -193,7 +200,7 @@ axen_miibus_readreg(struct device *dev, > } > > ival = UGETW(val); > - DPRINTFN(2,("axen_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n", > + DPRINTFN(12,("axen_miibus_readreg: phy 0x%x reg 0x%x val 0x%x\n", > phy, reg, ival)); > > if (reg == MII_BMSR) { > @@ -220,7 +227,7 @@ axen_miibus_writereg(struct device *dev, > axen_lock_mii(sc); > err = axen_cmd(sc, AXEN_CMD_MII_WRITE_REG, reg, phy, &uval); > axen_unlock_mii(sc); > - DPRINTFN(2, ("axen_miibus_writereg: phy 0x%x reg 0x%x val 0x%0x\n", > + DPRINTFN(12, ("axen_miibus_writereg: phy 0x%x reg 0x%x val 0x%0x\n", > phy, reg, val)); > > if (err) { > @@ -236,13 +243,17 @@ axen_miibus_statchg(struct device *dev) > struct mii_data *mii = GET_MII(sc); > struct ifnet *ifp; > int err; > + uint8_t link_status; > uint16_t val; > uWord wval; > + struct axen_qctrl *qctrl; > + > + axen_lock_mii(sc); > > ifp = GET_IFP(sc); > if (mii == NULL || ifp == NULL || > (ifp->if_flags & IFF_RUNNING) == 0) > - return; > + goto done; > > sc->axen_link = 0; > if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == > @@ -250,10 +261,8 @@ axen_miibus_statchg(struct device *dev) > switch (IFM_SUBTYPE(mii->mii_media_active)) { > case IFM_10_T: > case IFM_100_TX: > - sc->axen_link++; > - break; > case IFM_1000_T: > - sc->axen_link++; > + sc->axen_link = 1; > break; > default: > break; > @@ -261,37 +270,97 @@ axen_miibus_statchg(struct device *dev) > } > > /* Lost link, do nothing. */ > - if (sc->axen_link == 0) > - return; > + if (sc->axen_link == 0) { > + DPRINTF(("%s: %s: lost link\n", sc->axen_dev.dv_xname, > + __func__)); > + goto done; > + } > > - val = 0; > - if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) > - val |= AXEN_MEDIUM_FDX; > + err = axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_PHYSICAL_LINK_STATUS, > + &link_status); > + if (err) > + goto error; > + DPRINTF(("%s: %s: link status: 0x%x\n", sc->axen_dev.dv_xname, > + __func__, link_status)); > + > + /* both freebsd and linux don't define/set AXEN_MEDIUM_ALWAYS_ONE, > + * but 6.2.2.10 of the datasheet (p40) sets it to 1 */ > + val = AXEN_MEDIUM_RECV_EN | AXEN_MEDIUM_ALWAYS_ONE; > > - val |= (AXEN_MEDIUM_RECV_EN | AXEN_MEDIUM_ALWAYS_ONE); > - val |= (AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN); > + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) { > + val |= AXEN_MEDIUM_FDX; > +#if 0 > + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0) > + val |= AXEN_MEDIUM_TXFLOW_CTRL_EN; > + if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0) > + val |= AXEN_MEDIUM_RXFLOW_CTRL_EN; > +#else > + val |= AXEN_MEDIUM_TXFLOW_CTRL_EN | AXEN_MEDIUM_RXFLOW_CTRL_EN; > +#endif > + } > > switch (IFM_SUBTYPE(mii->mii_media_active)) { > case IFM_1000_T: > - val |= AXEN_MEDIUM_GIGA | AXEN_MEDIUM_EN_125MHZ; > + if (!(link_status & AXEN_EPHY_1000)) { > + printf("%s: wrong phy link (want 1000)\n", > + sc->axen_dev.dv_xname); > + } > + val |= AXEN_MEDIUM_GIGA; > + if (link_status & AXEN_USB_SS) > + qctrl = &axen_bulk_size[0]; > + else if (link_status & AXEN_USB_HS) > + qctrl = &axen_bulk_size[1]; > + else > + qctrl = &axen_bulk_size[3]; > break; > case IFM_100_TX: > - val |= AXEN_MEDIUM_PS; > + if (!(link_status & AXEN_EPHY_100)) { > + printf("%s: wrong phy link (want 100)\n", > + sc->axen_dev.dv_xname); > + } > + val |= AXEN_MEDIUM_PORTSPEED_100; > + if (link_status & (AXEN_USB_SS | AXEN_USB_HS)) > + qctrl = &axen_bulk_size[2]; > + else > + qctrl = &axen_bulk_size[3]; > break; > case IFM_10_T: > - /* doesn't need to be handled */ > + if (!(link_status & AXEN_EPHY_10)) { > + printf("%s: wrong phy link (want 10)\n", > + sc->axen_dev.dv_xname); > + } > + qctrl = &axen_bulk_size[3]; > break; > + default: > + printf("%s: unknown uplink bus: 0x%02x\n", > + sc->axen_dev.dv_xname, link_status); > + axen_unlock_mii(sc); > + goto error; > } > + /* XXX change buffer size here */ > + > + /* RX bulk configuration. */ > + DPRINTF(("%s: %s: qtrl bufsize = 0x%x, ifg = 0x%x\n", > + sc->axen_dev.dv_xname, __func__, > + qctrl->bufsize, qctrl->ifg)); > + err = axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL, > + qctrl); > + if (err) > + goto error; > > - DPRINTF(("axen_miibus_statchg: val=0x%x\n", val)); > + DPRINTF(("%s: %s: val=0x%x\n", sc->axen_dev.dv_xname, __func__,val)); > USETW(wval, val); > - axen_lock_mii(sc); > err = axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval); > + if (err) > + goto error; > + > + goto done; > + > +error: > + printf("%s: media change failed (err: 0x%x)\n", sc->axen_dev.dv_xname, > + err); > +done: > axen_unlock_mii(sc); > - if (err) { > - printf("%s: media change failed\n", sc->axen_dev.dv_xname); > - return; > - } > } > > /* > @@ -345,6 +414,8 @@ axen_iff(struct axen_softc *sc) > u_int8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; > uWord wval; > > + DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__)); > + > if (usbd_is_dying(sc->axen_udev)) > return; > > @@ -352,27 +423,27 @@ axen_iff(struct axen_softc *sc) > > /* Enable receiver, set RX mode */ > axen_lock_mii(sc); > - axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval); > - rxmode = UGETW(wval); > - rxmode &= ~(AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST | > - AXEN_RXCTL_PROMISC); > + rxmode = AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_START; > ifp->if_flags &= ~IFF_ALLMULTI; > > /* > - * Always accept broadcast frames. > * Always accept frames destined to our station address. > */ > - rxmode |= AXEN_RXCTL_ACPT_BCAST; > + rxmode |= AXEN_RXCTL_ACPT_PHY_MCAST; > + /* > + * Accept broadcast frames iff interface has IFF_BROADCAST set. > + */ > + if (ifp->if_flags & IFF_BROADCAST) > + rxmode |= AXEN_RXCTL_ACPT_BCAST; > > if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { > ifp->if_flags |= IFF_ALLMULTI; > - rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST; > + rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST; > if (ifp->if_flags & IFF_PROMISC) > rxmode |= AXEN_RXCTL_PROMISC; > } else { > - rxmode |= AXEN_RXCTL_ACPT_ALL_MCAST | AXEN_RXCTL_ACPT_PHY_MCAST; > - > - /* now program new ones */ > + rxmode |= AXEN_RXCTL_ACPT_MCAST; > + /* compute multicast filter array */ > ETHER_FIRST_MULTI(step, ac, enm); > while (enm != NULL) { > h = ether_crc32_be(enm->enm_addrlo, > @@ -382,8 +453,15 @@ axen_iff(struct axen_softc *sc) > } > } > > - axen_cmd(sc, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI, > + DPRINTFN(5,("%s: %s: hashtbl: %x %x %x %x %x %x %x %x\n", > + sc->axen_dev.dv_xname,__func__, > + hashtbl[0], hashtbl[1], hashtbl[2], hashtbl[3], > + hashtbl[4], hashtbl[5], hashtbl[6], hashtbl[7])); > + axen_cmd(sc, AXEN_CMD_MAC_WRITE_FILTER, 8, AXEN_FILTER_MULTI, > (void *)&hashtbl); > + > + DPRINTFN(2,("%s: %s: rxmode: 0x%x\n", > + sc->axen_dev.dv_xname,__func__,rxmode)); > USETW(wval, rxmode); > axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval); > axen_unlock_mii(sc); > @@ -392,13 +470,16 @@ axen_iff(struct axen_softc *sc) > void > axen_reset(struct axen_softc *sc) > { > + DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__)); > + > if (usbd_is_dying(sc->axen_udev)) > return; > - > - axen_ax88179_init(sc); > > /* Wait a little while for the chip to get its brains in order. */ > DELAY(1000); > + > + axen_ax88179_init(sc); > + > return; > } > > @@ -408,7 +489,8 @@ axen_ax88179_init(struct axen_softc *sc) > uWord wval; > uByte val; > u_int16_t ctl, temp; > - struct axen_qctrl qctrl; > + > + DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__)); > > axen_lock_mii(sc); > > @@ -440,6 +522,10 @@ axen_ax88179_init(struct axen_softc *sc) > axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, &val); > usbd_delay_ms(sc->axen_udev, 100); > > + /* RX bulk configuration */ > + axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL, > + &axen_bulk_size[0]); > + > /* set monitor mode (disable) */ > val = AXEN_MONITOR_NONE; > axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val); > @@ -466,60 +552,25 @@ axen_ax88179_init(struct axen_softc *sc) > sc->axen_dev.dv_xname, ctl); > } > > - /* bulkin queue setting */ > - axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_USB_UPLINK, &val); > - switch (val) { > - case AXEN_USB_FS: > - DPRINTF(("uplink: USB1.1\n")); > - qctrl.ctrl = 0x07; > - qctrl.timer_low = 0xcc; > - qctrl.timer_high= 0x4c; > - qctrl.bufsize = AXEN_BUFSZ_LS - 1; > - qctrl.ifg = 0x08; > - break; > - case AXEN_USB_HS: > - DPRINTF(("uplink: USB2.0\n")); > - qctrl.ctrl = 0x07; > - qctrl.timer_low = 0x02; > - qctrl.timer_high= 0xa0; > - qctrl.bufsize = AXEN_BUFSZ_HS - 1; > - qctrl.ifg = 0xff; > - break; > - case AXEN_USB_SS: > - DPRINTF(("uplink: USB3.0\n")); > - qctrl.ctrl = 0x07; > - qctrl.timer_low = 0x4f; > - qctrl.timer_high= 0x00; > - qctrl.bufsize = AXEN_BUFSZ_SS - 1; > - qctrl.ifg = 0xff; > - break; > - default: > - printf("%s: unknown uplink bus:0x%02x\n", > - sc->axen_dev.dv_xname, val); > - axen_unlock_mii(sc); > - return; > - } > - axen_cmd(sc, AXEN_CMD_MAC_SET_RXSR, 5, AXEN_RX_BULKIN_QCTRL, &qctrl); > - > - /* Set MAC address. */ > - axen_cmd(sc, AXEN_CMD_MAC_WRITE_ETHER, ETHER_ADDR_LEN, > - AXEN_CMD_MAC_NODE_ID, &sc->arpcom.ac_enaddr); > - > /* > * set buffer high/low watermark to pause/resume. > * write 2byte will set high/log simultaneous with AXEN_PAUSE_HIGH. > - * XXX: what is the best value? OSX driver uses 0x3c-0x4c as LOW-HIGH > - * watermark parameters. > + * XXX: what is the best value? > + * - defaults (datasheet): 0x24-0x42 as LOW-HIGH watermark parameters. > + * - OSX driver uses 0x3c-0x4c as LOW-HIGH watermark parameters.(?) > + * - FreeBSD driver uses 0x34-0x52 as LOW-HIGH watermark parameters. > + * - Linux driver uses 0x34-0x52 as LOW-HIGH watermark parameters. > */ > - val = 0x34; > + val = 0x24; > axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_LOW_WATERMARK, &val); > - val = 0x52; > + val = 0x42; > axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PAUSE_HIGH_WATERMARK, &val); > > /* Set RX/TX configuration. */ > - /* Offloadng enable */ > #ifdef AXEN_TOE > + /* enable offloading */ > val = AXEN_RXCOE_IPv4 | AXEN_RXCOE_TCPv4 | AXEN_RXCOE_UDPv4 | > + AXEN_RXCOE_ICMP | AXEN_RXCOE_IGMP | > AXEN_RXCOE_TCPv6 | AXEN_RXCOE_UDPv6; > #else > val = AXEN_RXCOE_OFF; > @@ -528,36 +579,36 @@ axen_ax88179_init(struct axen_softc *sc) > > #ifdef AXEN_TOE > val = AXEN_TXCOE_IPv4 | AXEN_TXCOE_TCPv4 | AXEN_TXCOE_UDPv4 | > + AXEN_TXCOE_ICMP | AXEN_TXCOE_IGMP | > AXEN_TXCOE_TCPv6 | AXEN_TXCOE_UDPv6; > #else > val = AXEN_TXCOE_OFF; > #endif > axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_TX_COE, &val); > > - /* Set RX control register */ > - ctl = AXEN_RXCTL_IPE | AXEN_RXCTL_DROPCRCERR | AXEN_RXCTL_AUTOB; > - ctl |= AXEN_RXCTL_ACPT_PHY_MCAST | AXEN_RXCTL_ACPT_ALL_MCAST; > - ctl |= AXEN_RXCTL_START; > - USETW(wval, ctl); > - axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval); > - > - /* set monitor mode (enable) */ > - val = AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP; > + /* set monitor mode (XXX enable) */ > + /* AXEN_MONITOR_PMETYPE | AXEN_MONITOR_PMEPOL | AXEN_MONITOR_RWMP; */ > + val = 0; > axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_MONITOR_MODE, &val); > +#ifdef AXEN_DEBUG > axen_cmd(sc, AXEN_CMD_MAC_READ, 1, AXEN_MONITOR_MODE, &val); > DPRINTF(("axen: Monitor mode = 0x%02x\n", val)); > +#endif > > /* set medium type */ > - ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX | AXEN_MEDIUM_ALWAYS_ONE | > - AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN; > - ctl |= AXEN_MEDIUM_RECV_EN; > + ctl = AXEN_MEDIUM_GIGA | AXEN_MEDIUM_FDX | > + AXEN_MEDIUM_RXFLOW_CTRL_EN | AXEN_MEDIUM_TXFLOW_CTRL_EN | > + AXEN_MEDIUM_RECV_EN; > USETW(wval, ctl); > DPRINTF(("axen: set to medium mode: 0x%04x\n", UGETW(wval))); > axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval); > - usbd_delay_ms(sc->axen_udev, 100); > > +#ifdef AXEN_DEBUG > + usbd_delay_ms(sc->axen_udev, 100); > axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval); > DPRINTF(("axen: current medium mode: 0x%04x\n", UGETW(wval))); > +#endif > + > axen_unlock_mii(sc); > > #if 0 /* XXX: TBD.... */ > @@ -571,7 +622,16 @@ axen_ax88179_init(struct axen_softc *sc) > 0x002c); > #endif > > -#if 1 /* XXX: phy hack ? */ > +#if 1 /* disable eee */ > + axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, > + AXEN_GMII_PHY_PAGE_SELECT, AXEN_GMII_PHY_PGSEL_PAGE3); > + axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, > + AXEN_MII_PHYADDR, 0x3246); > + axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, > + AXEN_GMII_PHY_PAGE_SELECT, AXEN_GMII_PHY_PGSEL_PAGE0); > +#endif > + > +#if 0 /* XXX: phy hack ? */ > axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x1F, 0x0005); > axen_miibus_writereg(&sc->axen_dev, sc->axen_phyno, 0x0C, 0x0000); > val = axen_miibus_readreg(&sc->axen_dev, sc->axen_phyno, 0x0001); > @@ -606,6 +666,8 @@ axen_attach(struct device *parent, struc > struct ifnet *ifp; > int i, s; > > + DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__)); > + > sc->axen_unit = self->dv_unit; /*device_get_unit(self);*/ > sc->axen_udev = uaa->device; > sc->axen_iface = uaa->iface; > @@ -622,22 +684,23 @@ axen_attach(struct device *parent, struc > > id = usbd_get_interface_descriptor(sc->axen_iface); > > - /* decide on what our bufsize will be */ > + /* > + * our bufsize is determined by the usb speed and link speed > + * so set it to the biggest buffer (slowest speed) available > + * this will be updated once the link state changes > + */ > switch (sc->axen_udev->speed) { > case USB_SPEED_FULL: > - sc->axen_bufsz = AXEN_BUFSZ_LS * 1024; > - break; > case USB_SPEED_HIGH: > - sc->axen_bufsz = AXEN_BUFSZ_HS * 1024; > - break; > case USB_SPEED_SUPER: > - sc->axen_bufsz = AXEN_BUFSZ_SS * 1024; > + /* linux adds 2 to the buffer size (why?) */ > + sc->axen_bufsz = (AXEN_BUFSZ_MAX + 2) * 1024; > break; > default: > printf("%s: not supported usb bus type", sc->axen_dev.dv_xname); > return; > } > - > + > /* Find endpoints. */ > for (i = 0; i < id->bNumEndpoints; i++) { > ed = usbd_interface2endpoint_descriptor(sc->axen_iface, i); > @@ -733,6 +796,8 @@ axen_detach(struct device *self, int fla > struct axen_softc *sc = (struct axen_softc *)self; > int s; > struct ifnet *ifp = GET_IFP(sc); > + uWord wval; > + u_int16_t ctl; > > DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__)); > > @@ -760,9 +825,26 @@ axen_detach(struct device *self, int fla > usb_detach_wait(&sc->axen_dev); > } > > - if (ifp->if_flags & IFF_RUNNING) > + if (ifp->if_flags & IFF_RUNNING) { > axen_stop(sc); > > + /* force bulk-in to return a zero-length USB packet */ > + axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_PHYPWR_RSTCTL, &wval); > + ctl = UGETW(wval); > + ctl |= AXEN_PHYPWR_RSTCTL_BZ | AXEN_PHYPWR_RSTCTL_IPRL; > + ctl &= ~AXEN_PHYPWR_RSTCTL_BZ_AUTOCLEAR_DIS; > + USETW(wval, ctl); > + axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_PHYPWR_RSTCTL, &wval); > + > + /* set clock to zero */ > + axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_PHYCLK, 0); > + > + /* disable MAC */ > + ctl = AXEN_RXCTL_STOP; > + USETW(wval, ctl); > + axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval); > + } > + > mii_detach(&sc->axen_mii, MII_PHY_ANY, MII_OFFSET_ANY); > ifmedia_delete_instance(&sc->axen_mii.mii_media, IFM_INST_ANY); > if (ifp->if_softc != NULL) { > @@ -788,16 +870,21 @@ axen_detach(struct device *self, int fla > } > > struct mbuf * > -axen_newbuf(void) > +axen_newbuf(struct axen_softc *sc) > { > struct mbuf *m; > > MGETHDR(m, M_DONTWAIT, MT_DATA); > - if (m == NULL) > + if (m == NULL) { > + printf("%s: could not allocate mbuf\n", > + sc->axen_dev.dv_xname); > return NULL; > + } > > MCLGET(m, M_DONTWAIT); > if (!(m->m_flags & M_EXT)) { > + printf("%s: could not allocate mbuf cluster\n", > + sc->axen_dev.dv_xname); > m_freem(m); > return NULL; > } > @@ -815,7 +902,8 @@ axen_rx_list_init(struct axen_softc *sc) > struct axen_chain *c; > int i; > > - DPRINTF(("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__)); > + DPRINTF(("%s: %s: %d rx list entries of size %u\n", > + sc->axen_dev.dv_xname, __func__,AXEN_RX_LIST_CNT,sc->axen_bufsz)); > > cd = &sc->axen_cdata; > for (i = 0; i < AXEN_RX_LIST_CNT; i++) { > @@ -846,7 +934,8 @@ axen_tx_list_init(struct axen_softc *sc) > struct axen_chain *c; > int i; > > - DPRINTF(("%s: %s: enter\n", sc->axen_dev.dv_xname, __func__)); > + DPRINTF(("%s: %s: %d tx list entries of size %u\n", > + sc->axen_dev.dv_xname, __func__,AXEN_TX_LIST_CNT,sc->axen_bufsz)); > > cd = &sc->axen_cdata; > for (i = 0; i < AXEN_TX_LIST_CNT; i++) { > @@ -885,154 +974,244 @@ axen_rxeof(struct usbd_xfer *xfer, void > struct mbuf *m; > u_int32_t total_len; > u_int32_t rx_hdr, pkt_hdr; > - u_int32_t *hdr_p; > + u_int32_t *hdr_p, *pkt_end, *hdr_end; > u_int16_t hdr_offset, pkt_count; > size_t pkt_len; > - size_t temp; > int s; > +#ifdef AXEN_DEBUG > + u_int16_t total_pkt_count; > +#endif > > DPRINTFN(10,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__)); > > - if (usbd_is_dying(sc->axen_udev)) > + if (usbd_is_dying(sc->axen_udev)) { > + DPRINTFN(15,("%s: %s: usbd_is_dying\n", > + sc->axen_dev.dv_xname,__func__)); > return; > + } > > - if (!(ifp->if_flags & IFF_RUNNING)) > + if (!(ifp->if_flags & IFF_RUNNING)) { > + DPRINTFN(15,("%s: %s: ! IFF_RUNNING\n", > + sc->axen_dev.dv_xname,__func__)); > return; > + } > > if (status != USBD_NORMAL_COMPLETION) { > + DPRINTFN(9,("%s: %s: ! USBD_NORMAL_COMPLETION: 0x%x\n", > + sc->axen_dev.dv_xname,__func__,status)); > if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) > return; > if (usbd_ratecheck(&sc->axen_rx_notice)) { > printf("%s: usb errors on rx: %s\n", > sc->axen_dev.dv_xname, usbd_errstr(status)); > } > - if (status == USBD_STALLED) > - > usbd_clear_endpoint_stall_async(sc->axen_ep[AXEN_ENDPT_RX]); > + if (status == USBD_STALLED) { > + DPRINTFN(9,("%s: %s: USBD_STALLED\n", > + sc->axen_dev.dv_xname,__func__)); > + usbd_clear_endpoint_stall_async( > + sc->axen_ep[AXEN_ENDPT_RX]); > + } > + DPRINTFN(10,("%s: %s: ! USBD_NORMAL_COMPLETION: done\n", > + sc->axen_dev.dv_xname,__func__)); > goto done; > } > > usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); > > - if (total_len < sizeof(pkt_hdr)) { > + if (total_len < sizeof(rx_hdr)) { > + printf("%s: rxeof: too short transfer (len %u)\n", > + sc->axen_dev.dv_xname, total_len); > + ifp->if_ierrors++; > + goto done; > + } > + > + if (total_len > sc->axen_bufsz) { > + printf("%s: rxeof: too large transfer (len %u)\n", > + sc->axen_dev.dv_xname, total_len); > ifp->if_ierrors++; > goto done; > } > > - /* > - * buffer map > - * [packet #0]...[packet #n][pkt hdr#0]..[pkt hdr#n][recv_hdr] > - * each packet has 0xeeee as psuedo header.. > + /* > + * <--------------------- total_len --------------------> > + * [pkt #0]...[pkt #n][pkt_hdr #0]...[pkt_hdr #n][rx_hdr] > + * ^buf ^pkt_end ^hdr_end > + * > + * Each RX frame is aligned on 8 bytes boundary. If RXCTL_IPE > + * bit is set in MAC_RXCTL register, there would be 2 > + * padding bytes and 6 dummy bytes(as the padding also should > + * be aligned on 8 bytes boundary) for each RX frame to align > + * IP header on 32bits boundary. We don't set RXCTL_IPE bit > + * of MAC_RXCTL register, so there should be no padding bytes > + * which simplifies RX logic a lot. > */ > - hdr_p = (u_int32_t *)(buf + total_len - sizeof(u_int32_t)); > - rx_hdr = letoh32(*hdr_p); > + > + hdr_end = (u_int32_t *)(buf + total_len - sizeof(rx_hdr)); > + rx_hdr = le32toh(*hdr_end); > hdr_offset = (u_int16_t)(rx_hdr >> 16); > pkt_count = (u_int16_t)(rx_hdr & 0xffff); > > - if (total_len > sc->axen_bufsz) { > - printf("%s: rxeof: too large transfer\n", > - sc->axen_dev.dv_xname); > - goto done; > - } > +#ifdef AXEN_DEBUG > + total_pkt_count = pkt_count; > +#endif > > /* sanity check */ > - if (hdr_offset > total_len) { > + if (hdr_offset > total_len - sizeof(rx_hdr)) { > + DPRINTFN(7,("%s: %s: hdr_offset (%u) > total_len (%u)" > + " - sizeof(pkt_hdr) (%lu)\n", > + sc->axen_dev.dv_xname,__func__,hdr_offset,total_len, > + sizeof(rx_hdr))); > ifp->if_ierrors++; > goto done; > } > > /* point first packet header */ > - hdr_p = (u_int32_t*)(buf + hdr_offset); > - > - /* > - * ax88179 will pack multiple ip packet to a USB transaction. > - * process all of packets in the buffer > - */ > + hdr_p = pkt_end = (u_int32_t *)(buf + hdr_offset); > > -#if 1 /* XXX: paranoiac check. need to remove later */ > -#define AXEN_MAX_PACKED_PACKET 200 > +#ifdef AXEN_DEBUG > +#define AXEN_MAX_PACKED_PACKET 200 > if (pkt_count > AXEN_MAX_PACKED_PACKET) { > - DPRINTF(("Too many packets (%d) in a transaction, discard.\n", > + DPRINTF(("Too many packets (%d) in a transaction, discard.\n", > pkt_count)); > + ifp->if_ierrors += pkt_count; > goto done; > } > #endif > - > - do { > - if ((buf[0] != 0xee) || (buf[1] != 0xee)){ > - printf("%s: invalid buffer(pkt#%d), continue\n", > - sc->axen_dev.dv_xname, pkt_count); > - ifp->if_ierrors += pkt_count; > - goto done; > + /* > + * ax88179 will pack multiple ip packet to a USB transaction. > + * process all of packets in the buffer > + */ > + DPRINTFN(10,("%s: %s: pkt_count = %u\n", > + sc->axen_dev.dv_xname,__func__,pkt_count)); > + while(pkt_count--) { > + /* verify the header offset */ > + if (hdr_p >= hdr_end) { > + DPRINTF(("%s: %s: end of packet headers(pkt#%d)\n", > + sc->axen_dev.dv_xname,__func__,pkt_count)); > + ifp->if_ierrors += pkt_count + 1; > + goto input; > } > > pkt_hdr = letoh32(*hdr_p); > pkt_len = (pkt_hdr >> 16) & 0x1fff; > > DPRINTFN(10,("rxeof: packet#%d, pkt_hdr 0x%08x, pkt_len %zu\n", > - pkt_count, pkt_hdr, pkt_len)); > + pkt_count, pkt_hdr, pkt_len)); > > - if ((pkt_hdr & AXEN_RXHDR_CRC_ERR) || > - (pkt_hdr & AXEN_RXHDR_DROP_ERR)) { > - ifp->if_ierrors++; > - /* move to next pkt header */ > - DPRINTF(("crc err(pkt#%d)\n", pkt_count)); > - goto nextpkt; > + /* verify the data length */ > + if ((void *)buf + pkt_len > (void *)hdr_p) { > + DPRINTF(("%s: %s: end of packet data(pkt#%d)\n", > + sc->axen_dev.dv_xname,__func__,pkt_count)); > + ifp->if_ierrors += pkt_count + 1; > + goto input; > } > > - /* process each packet */ > - /* allocate mbuf */ > - m = axen_newbuf(); > - if (m == NULL) { > + if (pkt_len > MCLBYTES || pkt_len < ETHER_MIN_LEN) { > + printf("%s: invalid pkt_len %zu\n", > + sc->axen_dev.dv_xname,pkt_len); > ifp->if_ierrors++; > goto nextpkt; > } > > - /* skip pseudo header (2byte) and trailer padding (4Byte) */ > - m->m_pkthdr.len = m->m_len = pkt_len - 6; > + if (AXEN_RXHDR_ERR(pkt_hdr)) { > +#ifdef AXEN_DEBUG > + DPRINTFN(7,("%s: %s: err(pkt#%d) pkt_hdr 0x%08x,", > + sc->axen_dev.dv_xname,__func__,pkt_count,pkt_hdr)); > + if (pkt_hdr & AXEN_RXHDR_DROP_ERR) > + DPRINTFN(7,(" drop")); > + if (pkt_hdr & AXEN_RXHDR_MII_ERR) > + DPRINTFN(7,(" mii")); > + if (pkt_hdr & AXEN_RXHDR_CRC_ERR) > + DPRINTFN(7,(" crc")); > + DPRINTFN(7,("\n")); > +#endif > + ifp->if_ierrors++; > + /* move to next pkt header */ > + goto nextpkt; > + } > > #ifdef AXEN_TOE > /* cheksum err */ > - if ((pkt_hdr & AXEN_RXHDR_L3CSUM_ERR) || > + if ((pkt_hdr & AXEN_RXHDR_L3CSUM_ERR) || > (pkt_hdr & AXEN_RXHDR_L4CSUM_ERR)) { > printf("%s: checksum err (pkt#%d)\n", > sc->axen_dev.dv_xname, pkt_count); > goto nextpkt; > - } else { > - m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; > } > +#endif > > - int l4_type; > - l4_type = (pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >> > - AXEN_RXHDR_L4_TYPE_OFFSET; > + /* process each packet */ > + /* allocate mbuf */ > + m = m_devget(buf, pkt_len, ETHER_ALIGN); /* axen_newbuf(sc) */ > + if (m == NULL) { > +#ifdef AXEN_DEBUG > + DPRINTF(("%s: could not allocate rx mbuf " > + "(%d total, %d remaining)\n", > + sc->axen_dev.dv_xname, > + total_pkt_count, pkt_count + 1)); > +#endif > + ifp->if_ierrors += pkt_count + 1; > + goto input; > + } > + > +#if 0 /* if using axen_newbuf() instead of m_devget() */ > + m->m_pkthdr.len = m->m_len = pkt_len; > +#endif > + > +#if 0 /* ifdef AXEN_TOE */ > + switch ((pkt_hdr & AXEN_RXHDR_L3_TYPE_MASK) >> > + AXEN_RXHDR_L3_TYPE_OFFSET) { > + case AXEN_RXHDR_L3_TYPE_IPV4: > + m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; > + break; > + case AXEN_RXHDR_L3_TYPE_IPV6: > + /* XXX IPV6 equivalent of M_IPV4_CSUM_IN_OK? */ > + break; > + default: > + /* do we need to set something here? */ > + break; > + } > > - if ((l4_type == AXEN_RXHDR_L4_TYPE_TCP) || > - (l4_type == AXEN_RXHDR_L4_TYPE_UDP)) > - m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK | > - M_UDP_CSUM_IN_OK; > + switch ((pkt_hdr & AXEN_RXHDR_L4_TYPE_MASK) >> > + AXEN_RXHDR_L4_TYPE_OFFSET) { > + case AXEN_RXHDR_L4_TYPE_ICMP: > + m->m_pkthdr.csum_flags |= M_ICMP_CSUM_IN_OK; > + break; > + case AXEN_RXHDR_L4_TYPE_UDP: > + m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK; > + break; > + case AXEN_RXHDR_L4_TYPE_TCP: > + m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK; > + break; > + default: > + /* do we need to set something here? */ > + break; > + } > #endif > > - memcpy(mtod(m, char *), buf + 2, pkt_len - 6); > +#if 0 /* if using axen_newbuf() instead of m_devget() */ > + memcpy(mtod(m, char *), buf, pkt_len); > +#endif > > ml_enqueue(&ml, m); > > nextpkt: > /* > - * prepare next packet > + * prepare next packet > * as each packet will be aligned 8byte boundary, > * need to fix up the start point of the buffer. > */ > - temp = ((pkt_len + 7) & 0xfff8); > - buf = buf + temp; > + buf += (pkt_len + 7) & 0xfff8; > hdr_p++; > - pkt_count--; > - } while( pkt_count > 0); > + } > > -done: > - /* push the packet up */ > +input: > + /* push the packets up */ > s = splnet(); > if_input(ifp, &ml); > splx(s); > > +done: > /* clear buffer for next transaction */ > memset(c->axen_buf, 0, sc->axen_bufsz); > > @@ -1043,7 +1222,7 @@ done: > USBD_NO_TIMEOUT, axen_rxeof); > usbd_transfer(xfer); > > - DPRINTFN(10,("%s: %s: start rx\n", sc->axen_dev.dv_xname, __func__)); > + DPRINTFN(10,("%s: %s: end rx\n", sc->axen_dev.dv_xname, __func__)); > } > > /* > @@ -1076,7 +1255,8 @@ axen_txeof(struct usbd_xfer *xfer, void > printf("axen%d: usb error on tx: %s\n", sc->axen_unit, > usbd_errstr(status)); > if (status == USBD_STALLED) > - > usbd_clear_endpoint_stall_async(sc->axen_ep[AXEN_ENDPT_TX]); > + usbd_clear_endpoint_stall_async( > + sc->axen_ep[AXEN_ENDPT_TX]); > splx(s); > return; > } > @@ -1190,6 +1370,8 @@ axen_encap(struct axen_softc *sc, struct > /* Transmit */ > err = usbd_transfer(c->axen_xfer); > if (err != USBD_IN_PROGRESS) { > + DPRINTFN(2,("%s: %s: usbd_transfer err = %d\n", > + sc->axen_dev.dv_xname,__func__, err)); > axen_stop(sc); > return EIO; > } > @@ -1249,21 +1431,33 @@ axen_init(void *xsc) > struct axen_chain *c; > usbd_status err; > int i, s; > - uByte bval; > uWord wval; > uint16_t rxmode; > > + DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__)); > + > s = splnet(); > > /* > * Cancel pending I/O and free all RX/TX buffers. > */ > + axen_stop(sc); > axen_reset(sc); > > - /* XXX: ? */ > - bval = 0x01; > + /* Set MAC address. */ > + axen_cmd(sc, AXEN_CMD_MAC_WRITE_ETHER, ETHER_ADDR_LEN, > + AXEN_CMD_MAC_NODE_ID, &sc->arpcom.ac_enaddr); > + > + /* Program promiscuous mode and multicast filters. */ > + axen_iff(sc); > + > + /* Enable receiver, set RX mode */ > axen_lock_mii(sc); > - axen_cmd(sc, AXEN_CMD_MAC_WRITE, 1, AXEN_UNK_28, &bval); > + axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval); > + rxmode = UGETW(wval); > + rxmode |= AXEN_RXCTL_START; > + USETW(wval, rxmode); > + axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval); > axen_unlock_mii(sc); > > /* Init RX ring. */ > @@ -1280,18 +1474,6 @@ axen_init(void *xsc) > return; > } > > - /* Program promiscuous mode and multicast filters. */ > - axen_iff(sc); > - > - /* Enable receiver, set RX mode */ > - axen_lock_mii(sc); > - axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MAC_RXCTL, &wval); > - rxmode = UGETW(wval); > - rxmode |= AXEN_RXCTL_START; > - USETW(wval, rxmode); > - axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MAC_RXCTL, &wval); > - axen_unlock_mii(sc); > - > /* Open RX and TX pipes. */ > err = usbd_open_pipe(sc->axen_iface, sc->axen_ed[AXEN_ENDPT_RX], > USBD_EXCLUSIVE_USE, &sc->axen_ep[AXEN_ENDPT_RX]); > @@ -1396,7 +1578,7 @@ axen_watchdog(struct ifnet *ifp) > sc = ifp->if_softc; > > ifp->if_oerrors++; > - printf("axen%d: watchdog timeout\n", sc->axen_unit); > + printf("%s: watchdog timeout\n", sc->axen_dev.dv_xname); > > s = splusb(); > c = &sc->axen_cdata.axen_tx_chain[0]; > @@ -1418,8 +1600,10 @@ axen_stop(struct axen_softc *sc) > usbd_status err; > struct ifnet *ifp; > int i; > + u_int16_t ctl; > + uWord wval; > > - axen_reset(sc); > + DPRINTFN(2,("%s: %s: enter\n", sc->axen_dev.dv_xname,__func__)); > > ifp = &sc->arpcom.ac_if; > ifp->if_timer = 0; > @@ -1427,6 +1611,13 @@ axen_stop(struct axen_softc *sc) > ifq_clr_oactive(&ifp->if_snd); > > timeout_del(&sc->axen_stat_ch); > + > + /* disable receive */ > + axen_cmd(sc, AXEN_CMD_MAC_READ2, 2, AXEN_MEDIUM_STATUS, &wval); > + ctl = UGETW(wval); > + ctl &= ~AXEN_MEDIUM_RECV_EN; > + USETW(wval, ctl); > + axen_cmd(sc, AXEN_CMD_MAC_WRITE2, 2, AXEN_MEDIUM_STATUS, &wval); > > /* Stop transfers. */ > if (sc->axen_ep[AXEN_ENDPT_RX] != NULL) { > Index: dev/usb/if_axenreg.h > =================================================================== > RCS file: /cvs/src/sys/dev/usb/if_axenreg.h,v > retrieving revision 1.6 > diff -u -p -r1.6 if_axenreg.h > --- dev/usb/if_axenreg.h 14 Sep 2016 12:41:09 -0000 1.6 > +++ dev/usb/if_axenreg.h 12 Feb 2019 18:26:48 -0000 > @@ -12,9 +12,10 @@ > #define AXEN_PHY_ID 0x0003 > #define AXEN_MCAST_FILTER_SIZE 8 > /* unit: KB */ > -#define AXEN_BUFSZ_LS 8 > -#define AXEN_BUFSZ_HS 16 > -#define AXEN_BUFSZ_SS 24 > +#define AXEN_BUFSZ_LS 0x18 > +#define AXEN_BUFSZ_HS 0x16 > +#define AXEN_BUFSZ_SS 0x12 > +#define AXEN_BUFSZ_MAX AXEN_BUFSZ_LS > > #define AXEN_REV_UA1 0 > #define AXEN_REV_UA2 1 > @@ -26,8 +27,8 @@ > * | | ++-----L3_type (1:ipv4, 0/2:ipv6) > * pkt_len(13) | | ||+ ++-L4_type(0: icmp, 1: UDP, 4: TCP) > * |765|43210 76543210|7654 3210 7654 3210| > - * ||+-crc_err |+-L4_err |+-L4_CSUM_ERR > - * |+-mii_err +--L3_err +--L3_CSUM_ERR > + * ||+-crc_err |+-L4_err |+-L4_CSUM_ERR > + * |+-mii_err +--L3_err +--L3_CSUM_ERR > * +-drop_err > * > * ex) pkt_hdr 0x00680820 > @@ -62,6 +63,10 @@ > #define AXEN_RXHDR_L3CSUM_ERR (1U << 1) > #define AXEN_RXHDR_L4CSUM_ERR (1U << 0) > > +#define AXEN_RXHDR_ERR(x) ((x) & (AXEN_RXHDR_DROP_ERR | \ > + AXEN_RXHDR_MII_ERR | \ > + AXEN_RXHDR_CRC_ERR)) > + > /* L4 packet type (3bit) */ > #define AXEN_RXHDR_L4_TYPE_MASK 0x0000001c > #define AXEN_RXHDR_L4_TYPE_OFFSET 2 > @@ -70,7 +75,7 @@ > #define AXEN_RXHDR_L4_TYPE_TCP 0x4 > > /* L3 packet type (2bit) */ > -#define AXEN_RXHDR_L3_TYPE_MASK 0x00000600 > +#define AXEN_RXHDR_L3_TYPE_MASK 0x00000060 > #define AXEN_RXHDR_L3_TYPE_OFFSET 5 > #define AXEN_RXHDR_L3_TYPE_UNDEF 0x0 > #define AXEN_RXHDR_L3_TYPE_IPV4 0x1 > @@ -88,10 +93,13 @@ > #define AXEN_CMD_MAC_READ 0x1001 > #define AXEN_CMD_MAC_WRITE 0x1101 > > -#define AXEN_USB_UPLINK 0x02 > +#define AXEN_PHYSICAL_LINK_STATUS 0x02 > #define AXEN_USB_FS 0x01 > #define AXEN_USB_HS 0x02 > #define AXEN_USB_SS 0x04 > +#define AXEN_EPHY_10 0x10 > +#define AXEN_EPHY_100 0x20 > +#define AXEN_EPHY_1000 0x40 > #define AXEN_GENERAL_STATUS 0x03 > #define AXEN_GENERAL_STATUS_MASK 0x4 > #define AXEN_REV0 0x0 > @@ -149,9 +157,9 @@ > #define AXEN_RXCTL_STOP 0x0000 > #define AXEN_RXCTL_PROMISC 0x0001 > #define AXEN_RXCTL_ACPT_ALL_MCAST 0x0002 > -#define AXEN_RXCTL_HA8B 0x0004 > -#define AXEN_RXCTL_AUTOB 0x0008 > -#define AXEN_RXCTL_ACPT_BCAST 0x0010 > +#define AXEN_RXCTL_AUTOPAD_BNDRY 0x0004 > +#define AXEN_RXCTL_ACPT_BCAST 0x0008 > +#define AXEN_RXCTL_ACPT_MCAST 0x0010 > #define AXEN_RXCTL_ACPT_PHY_MCAST 0x0020 > #define AXEN_RXCTL_START 0x0080 > #define AXEN_RXCTL_DROPCRCERR 0x0100 > @@ -162,16 +170,27 @@ > #define AXEN_MEDIUM_GIGA 0x0001 > #define AXEN_MEDIUM_FDX 0x0002 > #define AXEN_MEDIUM_ALWAYS_ONE 0x0004 > -#define AXEN_MEDIUM_EN_125MHZ 0x0008 > +#define AXEN_MEDIUM_ALWAYS_ZERO1 0x0008 > #define AXEN_MEDIUM_RXFLOW_CTRL_EN 0x0010 > #define AXEN_MEDIUM_TXFLOW_CTRL_EN 0x0020 > +#define AXEN_MEDIUM_JUMBOFRAME_EN 0x0040 > +#define AXEN_MEDIUM_PAUSEFRAME_LT_ONLY_EN 0x0080 > #define AXEN_MEDIUM_RECV_EN 0x0100 > -#define AXEN_MEDIUM_PS 0x0200 > -#define AXEN_MEDIUM_JUMBO_EN 0x8040 > +#define AXEN_MEDIUM_PORTSPEED_100 0x0200 > +#define AXEN_MEDIUM_ALWAYS_ZERO2 0x0400 > +#define AXEN_MEDIUM_STOP_BACKPRESSURE 0x0800 > +#define AXEN_MEDIUM_SUPERMAC 0x1000 > +#define AXEN_MEDIUM_ALWAYS_ZERO3 0x2000 > +#define AXEN_MEDIUM_ALWAYS_ZERO4 0x4000 > +#define AXEN_MEDIUM_ALWAYS_ZERO5 0x8000 > +#define AXEN_MEDIUM_JUMBO_EN \ > + (AXEN_MEDIUM_JUMBOFRAME_EN | AXEN_MEDIUM_STOP_BACKPRESSURE) > #define AXEN_PHYPWR_RSTCTL 0x26 > +#define AXEN_PHYPWR_RSTCTL_BZ_AUTOCLEAR_DIS 0x0004 > #define AXEN_PHYPWR_RSTCTL_BZ 0x0010 > #define AXEN_PHYPWR_RSTCTL_IPRL 0x0020 > #define AXEN_PHYPWR_RSTCTL_AUTODETACH 0x1000 > +#define AXEN_PHYPWR_RSTCTL_WOL_LOWPOWER 0x8000 > > #define AXEN_CMD_EEPROM_READ 0x2004 > #define AXEN_EEPROM_STAT 0x43 > @@ -212,6 +231,20 @@ > #define AXEN_RX_LIST_CNT 1 > #define AXEN_TX_LIST_CNT 1 > > + > +/* ---GMII--- */ > +#define AXEN_GMII_PHYPAGE 0x1e > +#define AXEN_GMII_PHY_PAGE_SELECT 0x1f > +#define AXEN_GMII_PHY_PGSEL_EXT 0x0007 > +#define AXEN_GMII_PHY_PGSEL_PAGE0 0x0000 > +#define AXEN_GMII_PHY_PGSEL_PAGE3 0x0003 > +#define AXEN_GMII_PHY_PGSEL_PAGE5 0x0005 > +#define AXEN_GMII_PHY_PGSEL_PAGE5 0x0005 > + > +#define AXEN_MII_PHYADDR 0x19 > +#define AXEN_MII_PHYADDR_EEE_DIS 0x3246 > +#define AXEN_MII_PHYADDR_EEE_EN1 0x3247 > +#define AXEN_MII_PHYADDR_EEE_EN2 0x0680 > > /* > * The interrupt endpoint is currently unused >