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
>