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
> 

Reply via email to