On Wed, Mar 21, 2018 at 12:03:41AM +0900, SASANO Takayoshi wrote:
> Hello,
> 
> Recently I bought pcDuino v1 and trying to run OpenBSD/armv7-current.
> sxie(4) supports Allwinner A10's EMAC ethernet and I think it can drive
> pcDuino's ethernet port but something goes wrong.
> 
> This is a log of tcpdump when I typed "nemesis ethernet -d sxie0 -H
> 01:23:45:67:89:ab -M ff:ff:ff:ff:ff:ff -P /dev/zero -T 1514" on
> pcDuino's console.
> 
>       23:52:22.590734 70:40:5e:ef:70:40 5e:ef:70:40:5e:ef 5eef 1514:
>                                7040 5eef 7040 5eef 7040 5eef 7040 5eef
>                                7040 5eef 7040 5eef 7040 5eef 7040 5eef
>                                7040 5eef 7040 5eef 7040 5eef 7040 5eef
>                                7040 5eef 7040 5eef 7040 5eef 7040 5eef
>                                7040 5eef 7040 5eef 7040 5eef 7040 5eef
>                                7040 5eef 7040 5eef 7040 5eef 7040 5eef
>                                7040 5eef 7040
> 
> When I attach ASIX AX88772 based USB ethernet interface and do same
> thing to axe(4), it looks no problem.
> 
>       23:58:53.261537 01:23:45:67:89:ab Broadcast 05ea 1514:
>                                0000 0000 0000 0000 0000 0000 0000 0000
>                                0000 0000 0000 0000 0000 0000 0000 0000
>                                0000 0000 0000 0000 0000 0000 0000 0000
>                                0000 0000 0000 0000 0000 0000 0000 0000
>                                0000 0000 0000 0000 0000 0000 0000 0000
>                                0000 0000 0000 0000 0000 0000 0000 0000
>                                0000 0000 0000
> 
> Is there any special procedure to work sxie ethernet?

Hi, 

i don't know what "nemesis" is, but you could have a try w/diff below.
or if you're unable to do that, static arp and/or running tcpdump for
IFF_PROMISC might work as a workaround for some bugs the driver has, fwiw..

-Artturi

> I simply use OpenBSD 6.3-beta (GENERIC) #194: Tue Mar 13 00:11:10 MDT 2018
> kernel and U-boot 2017.09 (Oct 02 2017 - 19:04:33 -0600) Allwinner Technology.
> 
> -- 
> SASANO Takayoshi (JG1UAA) <[email protected]>
> 



diff --git sys/arch/armv7/sunxi/sxie.c sys/arch/armv7/sunxi/sxie.c
index 249cd2a2478..a6174f36e6d 100644
--- sys/arch/armv7/sunxi/sxie.c
+++ sys/arch/armv7/sunxi/sxie.c
@@ -54,103 +54,175 @@
 #include <dev/ofw/ofw_regulator.h>
 #include <dev/ofw/fdt.h>
 
-/* configuration registers */
-#define        SXIE_CR                 0x0000
+#if defined(DEBUG) || defined(DIAGNOSTIC)
+#define        SXIE_CD         (ifp->if_flags & IFF_DEBUG)
+#define        SXIEDBG(x)      do { if (SXIE_CD) printf((x)); } while (0)
+#else
+#define        SXIE_CD         (0)
+#define        SXIEDBG(x)      do { } while (0)
+#endif
+
+/* control registers */
+#define        SXIE_CMDR               0x0000
 #define        SXIE_TXMODE             0x0004
-#define        SXIE_TXFLOW             0x0008
+#define        SXIE_TXFLOW             0x0008  /* unused */
 #define        SXIE_TXCR0              0x000c
 #define        SXIE_TXCR1              0x0010
 #define        SXIE_TXINS              0x0014
+/*
+ * XXX was wondering, what if these TXPKTLEN registers
+ * are actually part of memory mapped tx 'fake' descriptors,
+ * something like w/DMA but only via register map or something?
+ * should add some dbg and try to figure out:)
+ */
 #define        SXIE_TXPKTLEN0          0x0018
 #define        SXIE_TXPKTLEN1          0x001c
-#define        SXIE_TXSR               0x0020
+#define        SXIE_TXSR               0x0020  /* unused */
 #define        SXIE_TXIO0              0x0024
-#define        SXIE_TXIO1              0x0028
-#define        SXIE_TXTSVL0            0x002c
-#define        SXIE_TXTSVH0            0x0030
-#define        SXIE_TXTSVL1            0x0034
-#define        SXIE_TXTSVH1            0x0038
-#define        SXIE_RXCR               0x003c
+#define        SXIE_TXIO1              0x0028  /* unused */
+#define        SXIE_TXTSVL0            0x002c  /* unused */
+#define        SXIE_TXTSVH0            0x0030  /* unused */
+#define        SXIE_TXTSVL1            0x0034  /* unused */
+#define        SXIE_TXTSVH1            0x0038  /* unused */
+
+/* receive filter registers */
+#define        SXIE_RXFILTER_CTRL      0x003c
 #define        SXIE_RXHASH0            0x0040
 #define        SXIE_RXHASH1            0x0044
-#define        SXIE_RXSR               0x0048
-#define        SXIE_RXIO               0x004C
+
+/* dunno.. */
+#define        SXIE_RXSR               0x0048  /* unused */
+#define        SXIE_RXIO               0x004c
 #define        SXIE_RXFBC              0x0050
+
+/* module control registers */
 #define        SXIE_INTCR              0x0054
 #define        SXIE_INTSR              0x0058
-#define        SXIE_MACCR0             0x005C
-#define        SXIE_MACCR1             0x0060
-#define        SXIE_MACIPGT            0x0064
-#define        SXIE_MACIPGR            0x0068
-#define        SXIE_MACCLRT            0x006C
-#define        SXIE_MACMFL             0x0070
-#define        SXIE_MACSUPP            0x0074
-#define        SXIE_MACTEST            0x0078
-#define        SXIE_MACMCFG            0x007C
-#define        SXIE_MACMCMD            0x0080
-#define        SXIE_MACMADR            0x0084
-#define        SXIE_MACMWTD            0x0088
-#define        SXIE_MACMRDD            0x008C
-#define        SXIE_MACMIND            0x0090
-#define        SXIE_MACSSRR            0x0094
-#define        SXIE_MACA0              0x0098
-#define        SXIE_MACA1              0x009c
-#define        SXIE_MACA2              0x00a0
 
-/* i once spent hours on pretty defines, cvs up ate 'em. these shall do */
-#define SXIE_INTR_ENABLE               0x010f
-#define SXIE_INTR_DISABLE      0x0000
-#define SXIE_INTR_CLEAR                0x0000
+/* ethernet MAC registers */
+#define        SXIE_MAC0               0x005c
+#define        SXIE_MAC1               0x0060
+#define        SXIE_MAC_IPGT           0x0064
+#define        SXIE_MAC_IPGR           0x0068
+#define        SXIE_MAC_CLRT           0x006c
+#define        SXIE_MAC_MAXF           0x0070
+#define        SXIE_MAC_SUPP           0x0074
+#define        SXIE_MAC_TEST           0x0078  /* unused */
+#define        SXIE_MAC_MCFG           0x007c
+#define        SXIE_MAC_MCMD           0x0080
+#define        SXIE_MAC_MADR           0x0084
+#define        SXIE_MAC_MWTD           0x0088
+#define        SXIE_MAC_MRDD           0x008c
+#define        SXIE_MAC_MIND           0x0090
+#define        SXIE_MACSSRR            0x0094  /* unused */
+#define        SXIE_MAC_SA0            0x0098
+#define        SXIE_MAC_SA1            0x009c
+#define        SXIE_MACA2              0x00a0  /* unused */
 
-#define SXIE_TX_FIFO0          0x0001
-#define SXIE_TX_FIFO1          0x0002
+/* i once spent hours on pretty defines, cvs up ate 'em. these shall do */
+#define        SXIE_INTR_ENABLE        0x010f
+#define        SXIE_INTR_DISABLE       0x0000
+#define        SXIE_INTR_CLEAR         0x0000
 
 #define        SXIE_RX_ENABLE          0x0004
 #define        SXIE_TX_ENABLE          0x0003
-#define        SXIE_RXTX_ENABLE                0x0007
+#define        SXIE_RXTX_ENABLE        0x0007
 
 #define        SXIE_RXDRQM             0x0002
 #define        SXIE_RXTM               0x0004
-#define        SXIE_RXFLUSH            0x0008
-#define        SXIE_RXPA               0x0010
-#define        SXIE_RXPCF              0x0020
-#define        SXIE_RXPCRCE            0x0040
-#define        SXIE_RXPLE              0x0080
-#define        SXIE_RXPOR              0x0100
-#define        SXIE_RXUCAD             0x10000
-#define        SXIE_RXDAF              0x20000
-#define        SXIE_RXMCO              0x100000
-#define        SXIE_RXMHF              0x200000
-#define        SXIE_RXBCO              0x400000
-#define        SXIE_RXSAF              0x1000000
-#define        SXIE_RXSAIF             0x2000000
-
-#define        SXIE_MACRXFC            0x0004
-#define        SXIE_MACTXFC            0x0008
-#define SXIE_MACSOFTRESET      0x8000
-
-#define        SXIE_MACDUPLEX          0x0001  /* full = 1 */
-#define        SXIE_MACFLC             0x0002
-#define        SXIE_MACHF              0x0004
-#define        SXIE_MACDCRC            0x0008
-#define        SXIE_MACCRC             0x0010
-#define        SXIE_MACPC              0x0020
-#define        SXIE_MACVC              0x0040
-#define        SXIE_MACADP             0x0080
-#define        SXIE_MACPRE             0x0100
-#define        SXIE_MACLPE             0x0200
-#define        SXIE_MACNB              0x1000
-#define        SXIE_MACBNB             0x2000
-#define        SXIE_MACED              0x4000
-
-#define        SXIE_RX_ERRLENOOR       0x0040
-#define        SXIE_RX_ERRLENCHK       0x0020
-#define        SXIE_RX_ERRCRC          0x0010
-#define        SXIE_RX_ERRRCV          0x0008 /* XXX receive code violation ? 
*/
+                                       /* 0x00 */
+#define        SXIE_CMDR_RXENABLE              (1 << 0)
+#define        SXIE_CMDR_TXENABLE              (1 << 1)
+#define        SXIE_CMDR_REGRESET              (1 << 3)
+#define        SXIE_CMDR_TXRESET               (1 << 4)
+#define        SXIE_CMDR_RXRESET               (1 << 5)
+#define        SXIE_CMDR_PASSRUNTFRAME         (1 << 6)
+#define        SXIE_CMDR_PASSRXFILTER          (1 << 7)
+#define        SXIE_CMDR_TXFLOWCTL             (1 << 8)
+#define        SXIE_CMDR_RMII                  (1 << 9)
+#define        SXIE_CMDR_FULLDUPLEX            (1 << 10)
+                                       /* 0x3c */
+#define        SXIE_RXFILTER_PROMISC           (1 << 4)
+#define        SXIE_RXFILTER_CONTROLFRAMES     (1 << 5)
+#define        SXIE_RXFILTER_FRAMECRCERR       (1 << 6)
+#define        SXIE_RXFILTER_FRAMELENERR       (1 << 7)
+#define        SXIE_RXFILTER_FRAMELENOOR       (1 << 8)
+#define        SXIE_RXFILTER_UNICAST           (1 << 16)
+#define        SXIE_RXFILTER_DAFILTER          (1 << 17)
+#define        SXIE_RXFILTER_MULTICAST         (1 << 20)
+#define        SXIE_RXFILTER_MHASHFILTER       (1 << 21)
+#define        SXIE_RXFILTER_BROADCAST         (1 << 22)
+#define        SXIE_RXFILTER_SAFILTER          (1 << 24)
+#define        SXIE_RXFILTER_SAINVFILTER       (1 << 25)
+                                       /* 0x5c */
+#define        SXIE_MAC0_RXENABLE              (1 << 0)
+#define        SXIE_MAC0_PASSALL               (1 << 1)
+#define        SXIE_MAC0_RXFLOWCTRL            (1 << 2)
+#define        SXIE_MAC0_TXFLOWCTRL            (1 << 3)
+#define        SXIE_MAC0_LOOPBACK              (1 << 4)
+#define        SXIE_MAC0_RESETTX               (1 << 8)
+#define        SXIE_MAC0_RESETMCSTX            (1 << 9)
+#define        SXIE_MAC0_RESETRX               (1 << 10)
+#define        SXIE_MAC0_RESETMCSRX            (1 << 11)
+#define        SXIE_MAC0_SOFTRESET             (1 << 15)
+                                       /* 0x60 */
+#define        SXIE_MAC1_FULLDUPLEX            (1 << 0)
+#define        SXIE_MAC1_FRAMELENCHECK         (1 << 1)
+#define        SXIE_MAC1_HUGEFRAME             (1 << 2)
+#define        SXIE_MAC1_DELAYEDCRC            (1 << 3)
+#define        SXIE_MAC1_CRC                   (1 << 4)
+#define        SXIE_MAC1_PADCRC                (1 << 5)
+#define        SXIE_MAC1_VLANPAD               (1 << 6)
+#define        SXIE_MAC1_AUTOPAD               (1 << 7)
+#define        SXIE_MAC1_PUREPREAMBLE          (1 << 8)
+#define        SXIE_MAC1_LONGPREAMBLE          (1 << 9)
+#define        SXIE_MAC1_NOBACKOFF             (1 << 12)
+#define        SXIE_MAC1_BACKPRESSURE          (1 << 13)
+#define        SXIE_MAC1_EXCESSDEFER           (1 << 14)
+                                       /* 0x64 */
+#define        SXIE_MAC_BTB_IPG(x)             ((x) & 0x7f)
+                                       /* 0x68 */
+#define        SXIE_MAC_NBTB_IGP_P2(x)         ((x) & 0x7f)
+#define        SXIE_MAC_NBTB_IGP_P1(x)         (((x) & 0x7f) << 8)
+                                       /* 0x6c */
+#define        SXIE_MAC_CLRT_RETRANSMAX        0x0f
+#define        SXIE_MAC_CLRT_COLLWIND(x)       (((x) & 0x3f) << 8)
+                                       /* 0x70 */
+#define        SXIE_MAC_MAXF_MAXFRAMELENMASK   0xffff
+                                       /* 0x74 */
+#define        SXIE_MAC_SUPP_SPEED             (1 << 8)
+                                       /* 0x78 */
+#define        SXIE_MAC_TEST_SHORTCPAUSEQUANTA (1 << 0)
+#define        SXIE_MAC_TEST_TESTPAUSE         (1 << 1)
+#define        SXIE_MAC_TEST_TESTBACKPRESSURE  (1 << 2)
+                                       /* 0x7c */
+#define        SXIE_MAC_MCFG_SCANINCR          (1 << 0)
+#define        SXIE_MAC_MCFG_SUPPREAMBLE       (1 << 1)
+#define        SXIE_MAC_MCFG_CLKSEL(_n)        (((_n) & 0xf) << 2)
+#define        SXIE_MAC_MCFG_RESET_MII         (1 << 15)
+                                       /* 0x80 */
+#define        SXIE_MAC_MCMD_READ              (1 << 0)
+#define        SXIE_MAC_MCMD_WRITE             (0 << 0)
+#define        SXIE_MAC_MCMD_SCAN              (1 << 1)
+                                       /* 0x90 */
+#define        SXIE_MAC_MIND_BUSY              (1 << 0)
+#define        SXIE_MAC_MIND_SCANNING          (1 << 1)
+#define        SXIE_MAC_MIND_INVALID           (1 << 2)
+#define        SXIE_MAC_MIND_MIIFAIL           (1 << 3)
+
+#define        SXIE_TX_FIFO0           0x0001
+#define        SXIE_TX_FIFO1           0x0002
+#define        SXIE_TX_FIFOS           (SXIE_TX_FIFO0 | SXIE_TX_FIFO1)
+
+#define        SXIE_SRST_RX            (1 << 0)
+#define        SXIE_SRST_TX            (1 << 1)
+#define        SXIE_SRST_FULL          (1 << 2)
+
 #define        SXIE_RX_ERRMASK         0x0070
 
 #define        SXIE_MII_TIMEOUT        100
 #define SXIE_MAX_RXD           8
+#define SXIE_MAX_TXD           2
 #define SXIE_MAX_PKT_SIZE      ETHER_MAX_DIX_LEN
 
 #define SXIE_ROUNDUP(size, unit) (((size) + (unit) - 1) & ~((unit) - 1))
@@ -159,20 +231,22 @@ struct sxie_softc {
        struct device                   sc_dev;
        struct arpcom                   sc_ac;
        struct mii_data                 sc_mii;
+       int                             sc_node;
+       int                             sc_dmanode;
        int                             sc_phyno;
        bus_space_tag_t                 sc_iot;
        bus_space_handle_t              sc_ioh;
-       bus_space_handle_t              sc_sid_ioh;
+       bus_dma_tag_t                   sc_dmat;
        void                            *sc_ih; /* Interrupt handler */
-       uint32_t                        intr_status; /* soft interrupt status */
-       uint32_t                        pauseframe;
-       uint32_t                        txf_inuse;
+       uint32_t                        sc_pauseframe;
+       uint32_t                        sc_tx_timer;
+       uint32_t                        sc_tx_inuse;
 };
 
-struct sxie_softc *sxie_sc;
-
 int    sxie_match(struct device *, void *, void *);
 void   sxie_attach(struct device *, struct device *, void *);
+void   sxie_get_lladdr(struct sxie_softc *);
+void   sxie_set_lladdr(struct sxie_softc *);
 void   sxie_setup_interface(struct sxie_softc *, struct device *);
 void   sxie_socware_init(struct sxie_softc *);
 int    sxie_ioctl(struct ifnet *, u_long, caddr_t);
@@ -180,8 +254,7 @@ void        sxie_start(struct ifnet *);
 void   sxie_watchdog(struct ifnet *);
 void   sxie_init(struct sxie_softc *);
 void   sxie_stop(struct sxie_softc *);
-void   sxie_reset(struct sxie_softc *);
-void   sxie_iff(struct sxie_softc *, struct ifnet *);
+void   sxie_iff(struct sxie_softc *);
 int    sxie_intr(void *);
 void   sxie_recv(struct sxie_softc *);
 int    sxie_miibus_readreg(struct device *, int, int);
@@ -190,6 +263,9 @@ void        sxie_miibus_statchg(struct device *);
 int    sxie_ifm_change(struct ifnet *);
 void   sxie_ifm_status(struct ifnet *, struct ifmediareq *);
 
+static inline void
+       sxie_softreset(struct sxie_softc *, uint32_t);
+
 struct cfattach sxie_ca = {
        sizeof (struct sxie_softc), sxie_match, sxie_attach
 };
@@ -211,8 +287,8 @@ sxie_attach(struct device *parent, struct device *self, 
void *aux)
 {
        struct sxie_softc *sc = (struct sxie_softc *) self;
        struct fdt_attach_args *faa = aux;
-       struct mii_data *mii;
-       struct ifnet *ifp;
+       struct mii_data *mii = &sc->sc_mii;
+       struct ifnet *ifp = &sc->sc_ac.ac_if;
        int node, phy_supply, phy = MII_PHY_ANY;
        int s;
 
@@ -222,13 +298,15 @@ sxie_attach(struct device *parent, struct device *self, 
void *aux)
        pinctrl_byname(faa->fa_node, "default");
 
        sc->sc_iot = faa->fa_iot;
+       sc->sc_dmat = faa->fa_dmat;
+       sc->sc_node = faa->fa_node;
 
        if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
-           faa->fa_reg[0].size, 0, &sc->sc_ioh))
-               panic("sxie_attach: bus_space_map ioh failed!");
-
-       if (bus_space_map(sc->sc_iot, SID_ADDR, SID_SIZE, 0, &sc->sc_sid_ioh))
-               panic("sxie_attach: bus_space_map sid_ioh failed!");
+           faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
+               printf("%s: bus_space_map ioh failed!\n",
+                   sc->sc_dev.dv_xname);
+               return;
+       }
 
        clock_enable_all(faa->fa_node);
 
@@ -244,37 +322,43 @@ sxie_attach(struct device *parent, struct device *self, 
void *aux)
        }
        sc->sc_phyno = phy == MII_PHY_ANY ? 1 : phy;
 
-       sxie_socware_init(sc);
-       sc->txf_inuse = 0;
-
        sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_NET,
            sxie_intr, sc, sc->sc_dev.dv_xname);
+       if (sc->sc_ih == NULL)
+               goto failout;
 
-       s = splnet();
+       /*
+        * try to get&set lladdr in order:
+        * a) devicetree
+        * b) current
+        * c) better than random (from SID rootkey registers)
+        * d) ether_fakeaddr
+        */
+       sxie_get_lladdr(sc);
 
        printf(", address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr));
 
-       /* XXX verify flags & capabilities */
-       ifp = &sc->sc_ac.ac_if;
+       s = splnet();
        ifp->if_softc = sc;
        strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        ifp->if_ioctl = sxie_ioctl;
        ifp->if_start = sxie_start;
        ifp->if_watchdog = sxie_watchdog;
+                       /* XXX can do CRC too */
        ifp->if_capabilities = IFCAP_VLAN_MTU; /* XXX status check in recv? */
 
        IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
 
        /* Initialize MII/media info. */
-       mii = &sc->sc_mii;
        mii->mii_ifp = ifp;
        mii->mii_readreg = sxie_miibus_readreg;
        mii->mii_writereg = sxie_miibus_writereg;
        mii->mii_statchg = sxie_miibus_statchg;
 
        ifmedia_init(&mii->mii_media, 0, sxie_ifm_change, sxie_ifm_status);
-       mii_attach(self, mii, 0xffffffff, phy, MII_OFFSET_ANY, 0);
+       mii_attach(self, mii, 0xffffffff, phy, MII_OFFSET_ANY,
+           0/* XXX could do MIIF_DOPAUSE */);
 
        if (LIST_FIRST(&mii->mii_phys) == NULL) {
                ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
@@ -286,54 +370,120 @@ sxie_attach(struct device *parent, struct device *self, 
void *aux)
        ether_ifattach(ifp);
        splx(s);
 
-       sxie_sc = sc;
+       return;
+failout:
+       if (phy_supply)
+               regulator_disable(phy_supply);
+       clock_disable_all(faa->fa_node);
+       bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
 }
 
 void
-sxie_socware_init(struct sxie_softc *sc)
+sxie_softreset(struct sxie_softc *sc, uint32_t rx_tx_full)
 {
-       int have_mac = 0;
-       uint32_t reg;
-
-       /* MII clock cfg */
-       SXICMS4(sc, SXIE_MACMCFG, 15 << 2, 13 << 2);
+       uint32_t mac0_clr, mac0_set;
+       uint32_t cmdr_clr, cmdr_set;
+
+       rx_tx_full &= 0x07;
+       switch (rx_tx_full) {
+       case SXIE_SRST_RX:
+               mac0_clr = SXIE_MAC0_RXENABLE;
+               mac0_set = SXIE_MAC0_RESETMCSRX;
+               cmdr_clr = SXIE_CMDR_RXENABLE;
+               cmdr_set = SXIE_CMDR_RXRESET;
+               break;
+       case SXIE_SRST_TX:
+               mac0_clr = /* XXX txflowcontrol? */0;
+               mac0_set = SXIE_MAC0_RESETMCSTX;
+               cmdr_clr = SXIE_CMDR_TXENABLE;
+               cmdr_set = SXIE_CMDR_TXRESET;
+               break;
+       default:
+       case SXIE_SRST_FULL:
+               mac0_clr = SXIE_MAC0_RXENABLE;
+               mac0_set = SXIE_MAC0_SOFTRESET;
+               cmdr_clr = SXIE_CMDR_RXENABLE|SXIE_CMDR_TXENABLE;
+               cmdr_set = SXIE_CMDR_REGRESET;
+               break;
+       }
 
-       SXIWRITE4(sc, SXIE_INTCR, SXIE_INTR_DISABLE);
-       SXISET4(sc, SXIE_INTSR, SXIE_INTR_CLEAR);
+       /* disable, flush(reset), enable */
+       SXICLR4(sc, SXIE_MAC0, mac0_clr);
+       SXICLR4(sc, SXIE_CMDR, cmdr_clr);
+       SXISET4(sc, SXIE_MAC0, mac0_set);
+       SXISET4(sc, SXIE_CMDR, cmdr_set);
+       while (SXIREAD4(sc, SXIE_CMDR) & cmdr_set)
+               delay(10);
 
-       /*
-        * If u-boot doesn't set emac, use the Security ID area
-        * to generate a consistent MAC address of.
-        */
-       reg = SXIREAD4(sc, SXIE_MACA0);
-       if (reg != 0) {
-               sc->sc_ac.ac_enaddr[3] = reg >> 16 & 0xff;
-               sc->sc_ac.ac_enaddr[4] = reg >> 8 & 0xff;
-               sc->sc_ac.ac_enaddr[5] = reg & 0xff;
-               reg = SXIREAD4(sc, SXIE_MACA1);
-               sc->sc_ac.ac_enaddr[0] = reg >> 16 & 0xff;
-               sc->sc_ac.ac_enaddr[1] = reg >> 8 & 0xff;
-               sc->sc_ac.ac_enaddr[2] = reg & 0xff;
-
-               have_mac = 1;
+       if (rx_tx_full != SXIE_SRST_FULL) {
+               SXICLR4(sc, SXIE_MAC0, mac0_set);
+               SXISET4(sc, SXIE_CMDR, cmdr_clr);
+               SXISET4(sc, SXIE_MAC0, mac0_clr);
+       } else {
+#if 0
+               sxie_setup_interface(sc);
+               SXICLR4(sc, SXIE_MAC0, mac0_set);
+#else
+               return;
+#endif
        }
+}
 
-       reg = bus_space_read_4(sc->sc_iot, sc->sc_sid_ioh, 0x0);
-
-       if (!have_mac && reg != 0) {
-               sc->sc_ac.ac_enaddr[0] = 0x02;
-               sc->sc_ac.ac_enaddr[1] = reg & 0xff;
-               reg = bus_space_read_4(sc->sc_iot, sc->sc_sid_ioh, 0x0c);
-               sc->sc_ac.ac_enaddr[2] = reg >> 24 & 0xff;
-               sc->sc_ac.ac_enaddr[3] = reg >> 16 & 0xff;
-               sc->sc_ac.ac_enaddr[4] = reg >> 8 & 0xff;
-               sc->sc_ac.ac_enaddr[5] = reg & 0xff;
+void
+sxie_get_lladdr(struct sxie_softc *sc)
+{
+       uint8_t *enaddr = &sc->sc_ac.ac_enaddr[0];
+       bus_space_handle_t sid_ioh;
+       uint32_t reg;
+       int eaplen;
 
-               have_mac = 1;
+       eaplen = OF_getproplen(sc->sc_node, "local-mac-address");
+       if (eaplen == ETHER_ADDR_LEN) {
+               OF_getprop(sc->sc_node, "local-mac-address", enaddr, eaplen);
+               return;
+       } else if ((reg = SXIREAD4(sc, SXIE_MAC_SA0)) != 0) {
+               enaddr[3] = reg >> 16 & 0xff;
+               enaddr[4] = reg >> 8 & 0xff;
+               enaddr[5] = reg & 0xff;
+               reg = SXIREAD4(sc, SXIE_MAC_SA1);
+               enaddr[0] = reg >> 16 & 0xff;
+               enaddr[1] = reg >> 8 & 0xff;
+               enaddr[2] = reg & 0xff;
+               return;
+       } else
+       if (bus_space_map(sc->sc_iot, SID_ADDR, SID_SIZE, 0, &sid_ioh) != 0) {
+               if ((reg = bus_space_read_4(sc->sc_iot, sid_ioh, 0x0)) != 0) {
+                       /*
+                        * If U-Boot doesn't set MAC, use the Security ID
+                        * area to generate a consistent MAC address of.
+                        */
+                       enaddr[0] = 0x02;
+                       enaddr[1] = reg & 0xff;
+                       reg = bus_space_read_4(sc->sc_iot, sid_ioh, 0x0c);
+                       enaddr[2] = reg >> 24 & 0xff;
+                       enaddr[3] = reg >> 16 & 0xff;
+                       enaddr[4] = reg >> 8 & 0xff;
+                       enaddr[5] = reg & 0xff;
+               }
+               bus_space_unmap(sc->sc_iot, sid_ioh, SID_SIZE);
+               if (reg != 0)
+                       return;
        }
+       ether_fakeaddr(&sc->sc_ac.ac_if);
+}
 
-       if (!have_mac)
-               ether_fakeaddr(&sc->sc_ac.ac_if);
+void
+sxie_set_lladdr(struct sxie_softc *sc)
+{
+       /* set lladdr */
+       SXIWRITE4(sc, SXIE_MAC_SA0,
+           sc->sc_ac.ac_enaddr[3] << 16 |
+           sc->sc_ac.ac_enaddr[4] << 8 |
+           sc->sc_ac.ac_enaddr[5]);
+       SXIWRITE4(sc, SXIE_MAC_SA1,
+           sc->sc_ac.ac_enaddr[0] << 16 |
+           sc->sc_ac.ac_enaddr[1] << 8 |
+           sc->sc_ac.ac_enaddr[2]);
 }
 
 void
@@ -341,47 +491,46 @@ sxie_setup_interface(struct sxie_softc *sc, struct device 
*dev)
 {
        uint32_t clr_m, set_m;
 
+       /* MII host clock div */
+       SXICMS4(sc, SXIE_MAC_MCFG,
+           SXIE_MAC_MCFG_CLKSEL(15), SXIE_MAC_MCFG_CLKSEL(13));
+
        /* configure TX */
        SXICMS4(sc, SXIE_TXMODE, 3, 1); /* cpu mode */
 
-       /* configure RX */
-       clr_m = SXIE_RXDRQM | SXIE_RXTM | SXIE_RXPA | SXIE_RXPCF |
-           SXIE_RXPCRCE | SXIE_RXPLE | SXIE_RXMHF | SXIE_RXSAF |
-           SXIE_RXSAIF;
-       set_m = SXIE_RXPOR | SXIE_RXUCAD | SXIE_RXDAF | SXIE_RXBCO;
-       SXICMS4(sc, SXIE_RXCR, clr_m, set_m);
+       /* configure RX filtering */
+       clr_m = SXIE_RXDRQM | SXIE_RXTM |
+           SXIE_RXFILTER_PROMISC | SXIE_RXFILTER_CONTROLFRAMES |
+           SXIE_RXFILTER_FRAMECRCERR | SXIE_RXFILTER_FRAMELENERR |
+           SXIE_RXFILTER_MHASHFILTER | SXIE_RXFILTER_SAFILTER |
+           SXIE_RXFILTER_SAINVFILTER;
+       set_m = SXIE_RXFILTER_FRAMELENOOR | SXIE_RXFILTER_DAFILTER |
+           SXIE_RXFILTER_BROADCAST;
+       SXICMS4(sc, SXIE_RXFILTER_CTRL, clr_m, set_m);
 
        /* configure MAC */
-       SXISET4(sc, SXIE_MACCR0, SXIE_MACTXFC | SXIE_MACRXFC);
-       clr_m = SXIE_MACHF | SXIE_MACDCRC | SXIE_MACVC | SXIE_MACADP |
-           SXIE_MACPRE | SXIE_MACLPE | SXIE_MACNB | SXIE_MACBNB |
-           SXIE_MACED;
-       set_m = SXIE_MACFLC | SXIE_MACCRC | SXIE_MACPC;
+       SXISET4(sc, SXIE_MAC0, SXIE_MAC0_RXFLOWCTRL | SXIE_MAC0_TXFLOWCTRL);
+       clr_m = SXIE_MAC0_LOOPBACK | SXIE_MAC1_DELAYEDCRC |
+           SXIE_MAC1_VLANPAD | SXIE_MAC1_AUTOPAD |
+           SXIE_MAC1_PUREPREAMBLE | SXIE_MAC1_LONGPREAMBLE |
+           SXIE_MAC1_NOBACKOFF | SXIE_MAC1_BACKPRESSURE |
+           SXIE_MAC1_EXCESSDEFER;
+       set_m = SXIE_MAC1_FRAMELENCHECK | SXIE_MAC1_CRC | SXIE_MAC1_PADCRC;
        set_m |= sxie_miibus_readreg(dev, sc->sc_phyno, 0) >> 8 & 1;
-       SXICMS4(sc, SXIE_MACCR1, clr_m, set_m);
+       SXICMS4(sc, SXIE_MAC1, clr_m, set_m);
 
        /* XXX */
-       SXIWRITE4(sc, SXIE_MACIPGT, 0x0015);
-       SXIWRITE4(sc, SXIE_MACIPGR, 0x0c12);
+       SXIWRITE4(sc, SXIE_MAC_IPGT, 0x0015);
+       SXIWRITE4(sc, SXIE_MAC_IPGR, 0x0c12);
 
        /* XXX set collision window */
-       SXIWRITE4(sc, SXIE_MACCLRT, 0x370f);
+       SXIWRITE4(sc, SXIE_MAC_CLRT, 0x370f);
 
        /* set max frame length */
-       SXIWRITE4(sc, SXIE_MACMFL, SXIE_MAX_PKT_SIZE);
+       SXIWRITE4(sc, SXIE_MAC_MAXF, SXIE_MAX_PKT_SIZE);
 
        /* set lladdr */
-       SXIWRITE4(sc, SXIE_MACA0,
-           sc->sc_ac.ac_enaddr[3] << 16 |
-           sc->sc_ac.ac_enaddr[4] << 8 |
-           sc->sc_ac.ac_enaddr[5]);
-       SXIWRITE4(sc, SXIE_MACA1,
-           sc->sc_ac.ac_enaddr[0] << 16 |
-           sc->sc_ac.ac_enaddr[1] << 8 |
-           sc->sc_ac.ac_enaddr[2]);
-
-       sxie_reset(sc);
-       /* XXX possibly missing delay in here. */
+       sxie_set_lladdr(sc);
 }
 
 void
@@ -390,41 +539,44 @@ sxie_init(struct sxie_softc *sc)
        struct ifnet *ifp = &sc->sc_ac.ac_if;
        struct device *dev = (struct device *)sc;
        int phyreg;
-       
-       sxie_reset(sc);
 
-       SXIWRITE4(sc, SXIE_INTCR, SXIE_INTR_DISABLE);
+       sxie_softreset(sc, SXIE_SRST_FULL);
 
+       SXIWRITE4(sc, SXIE_INTCR, SXIE_INTR_DISABLE);
        SXISET4(sc, SXIE_INTSR, SXIE_INTR_CLEAR);
 
-       SXISET4(sc, SXIE_RXCR, SXIE_RXFLUSH);
-
-       /* soft reset */
-       SXICLR4(sc, SXIE_MACCR0, SXIE_MACSOFTRESET);
-
-       /* zero rx counter */
-       SXIWRITE4(sc, SXIE_RXFBC, 0);
-
        sxie_setup_interface(sc, dev);
 
+       /* release from softreset */
+       SXICLR4(sc, SXIE_MAC0, SXIE_MAC0_SOFTRESET);
+
        /* power up PHY */
        sxie_miibus_writereg(dev, sc->sc_phyno, 0,
            sxie_miibus_readreg(dev, sc->sc_phyno, 0) & ~(1 << 11));
        delay(1000);
        phyreg = sxie_miibus_readreg(dev, sc->sc_phyno, 0);
 
+       sxie_iff(sc);
+
        /* set duplex */
-       SXICMS4(sc, SXIE_MACCR1, 1, phyreg >> 8 & 1);
+       SXICMS4(sc, SXIE_MAC1, 1, phyreg >> 8 & 1);
 
        /* set speed */
-       SXICMS4(sc, SXIE_MACSUPP, 1 << 8, (phyreg >> 13 & 1) << 8);
+       SXICMS4(sc, SXIE_MAC_SUPP, 1 << 8, (phyreg >> 13 & 1) << 8);
+
+       sc->sc_pauseframe = 0;
+       sc->sc_tx_timer = 0;
+       sc->sc_tx_inuse = 0;
 
-       SXISET4(sc, SXIE_CR, SXIE_RXTX_ENABLE);
+       SXISET4(sc, SXIE_CMDR, SXIE_RXTX_ENABLE);
 
        /* Indicate we are up and running. */
        ifp->if_flags |= IFF_RUNNING;
        ifq_clr_oactive(&ifp->if_snd);
 
+       SXIWRITE4(sc, SXIE_INTCR, SXIE_INTR_DISABLE);
+       SXISET4(sc, SXIE_INTSR, SXIE_INTR_CLEAR);
+
        SXISET4(sc, SXIE_INTCR, SXIE_INTR_ENABLE);
 
        sxie_start(ifp);
@@ -451,11 +603,9 @@ sxie_intr(void *arg)
        }
 
        if (pending & (SXIE_TX_FIFO0 | SXIE_TX_FIFO1)) {
-               sc->txf_inuse &= ~pending;
-               if (sc->txf_inuse == 0)
-                       ifp->if_timer = 0;
-               else
-                       ifp->if_timer = 5;
+               sc->sc_tx_inuse &= ~(pending & SXIE_TX_FIFOS);
+               ifp->if_timer = (sc->sc_tx_inuse == 0) ? 0 : 1;
+               sc->sc_tx_timer = ifp->if_timer ? 5 : 0;
 
                if (ifq_is_oactive(&ifp->if_snd))
                        ifq_restart(&ifp->if_snd);
@@ -466,6 +616,48 @@ sxie_intr(void *arg)
        return 1;
 }
 
+void
+sxie_tx_mbuf_cpu(struct sxie_softc *sc, uint32_t fifo, struct mbuf *m)
+{
+       uint32_t txbuf[SXIE_MAX_PKT_SIZE / sizeof(uint32_t)];
+
+       /* copy the actual packet to fifo XXX through 'align buffer' */
+       m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)&txbuf[0]);
+       bus_space_write_multi_4(sc->sc_iot, sc->sc_ioh,
+           SXIE_TXIO0, (uint32_t *)&txbuf[0],
+           SXIE_ROUNDUP(m->m_pkthdr.len, 4) >> 2);
+
+       /* transmit to PHY from fifo */
+       SXISET4(sc, SXIE_TXCR0 + (fifo * 4), 1);
+}
+
+void
+sxie_tx_mbuf_dma(struct sxie_softc *sc, uint32_t fifo, struct mbuf *m)
+{
+       /* XXX not yet */
+       sxie_tx_mbuf_cpu(sc, fifo, m);
+}
+
+void
+sxie_tx_mbuf(struct sxie_softc *sc, struct mbuf *m)
+{
+       uint32_t fifo = 1;
+
+       /* select fifo */
+       fifo <<= sc->sc_tx_inuse & SXIE_TX_FIFO0 ? 1 : 0;
+       sc->sc_tx_inuse |= fifo--;
+       SXIWRITE4(sc, SXIE_TXINS, fifo);
+
+       /* set packet length */
+       SXIWRITE4(sc, SXIE_TXPKTLEN0 + (fifo * 4), m->m_pkthdr.len);
+
+       /* transfer to fifo */
+       if (sc->sc_dmanode)
+               sxie_tx_mbuf_dma(sc, fifo, m);
+       else
+               sxie_tx_mbuf_cpu(sc, fifo, m);
+}
+
 /*
  * XXX there's secondary tx fifo to be used.
  */
@@ -474,30 +666,16 @@ sxie_start(struct ifnet *ifp)
 {
        struct sxie_softc *sc = ifp->if_softc;
        struct mbuf *m;
-       struct mbuf *head;
-       uint8_t *td;
-       uint32_t fifo;
-       uint32_t txbuf[SXIE_MAX_PKT_SIZE / sizeof(uint32_t)]; /* XXX !!! */
 
        if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
                return;
 
-
-       td = (uint8_t *)&txbuf[0];
-       m = NULL;
-       head = NULL;
-
-       for (;;) {
-               if (sc->txf_inuse == (SXIE_TX_FIFO0 | SXIE_TX_FIFO1)) {
-                       ifq_set_oactive(&ifp->if_snd);
-                       break;
-               }
-
-               m = ifq_dequeue(&ifp->if_snd);
-               if (m == NULL)
-                       break;
+       for (; sc->sc_tx_inuse < SXIE_MAX_TXD; m_freem(m)) {
+               if ((m = ifq_dequeue(&ifp->if_snd)) == NULL)
+                       return;
 
                if (m->m_pkthdr.len > SXIE_MAX_PKT_SIZE) {
+                       SXIEDBG(("sxie_start: packet too big\n"));
                        m_freem(m);
                        continue;
                }
@@ -506,32 +684,12 @@ sxie_start(struct ifnet *ifp)
                if (ifp->if_bpf)
                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
 #endif
-
-               /* select fifo */
-               if (sc->txf_inuse & SXIE_TX_FIFO0) {
-                       sc->txf_inuse |= SXIE_TX_FIFO1;
-                       fifo = 1;
-               } else {
-                       sc->txf_inuse |= SXIE_TX_FIFO0;
-                       fifo = 0;
-               }
-               SXIWRITE4(sc, SXIE_TXINS, fifo);
-
-               /* set packet length */
-               SXIWRITE4(sc, SXIE_TXPKTLEN0 + (fifo * 4), m->m_pkthdr.len);
-
-               /* copy the actual packet to fifo XXX through 'align buffer' */
-               m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)td);
-               bus_space_write_multi_4(sc->sc_iot, sc->sc_ioh,
-                   SXIE_TXIO0,
-                   (uint32_t *)td, SXIE_ROUNDUP(m->m_pkthdr.len, 4) >> 2);
-
-               /* transmit to PHY from fifo */
-               SXISET4(sc, SXIE_TXCR0 + (fifo * 4), 1);
-               ifp->if_timer = 5;
-
-               m_freem(m);
+               sxie_tx_mbuf(sc, m);
+               sc->sc_tx_timer = 5;
+               ifp->if_timer = 1;
        }
+
+       ifq_set_oactive(&ifp->if_snd);
 }
 
 void
@@ -539,35 +697,41 @@ sxie_stop(struct sxie_softc *sc)
 {
        struct ifnet *ifp = &sc->sc_ac.ac_if;
 
-       sxie_reset(sc);
+       SXICLR4(sc, SXIE_CMDR, SXIE_CMDR_RXENABLE | SXIE_CMDR_TXENABLE);
+
+       sc->sc_pauseframe = 0;
+       sc->sc_tx_timer = 0;
+       sc->sc_tx_inuse = 0;
 
        ifp->if_flags &= ~IFF_RUNNING;
        ifp->if_timer = 0;
        ifq_clr_oactive(&ifp->if_snd);
-}
 
-void
-sxie_reset(struct sxie_softc *sc)
-{
-       /* reset the controller */
-       SXIWRITE4(sc, SXIE_CR, 0);
-       delay(200);
-       SXIWRITE4(sc, SXIE_CR, 1);
-       delay(200);
+       mii_down(&sc->sc_mii);
 }
 
 void
 sxie_watchdog(struct ifnet *ifp)
 {
        struct sxie_softc *sc = ifp->if_softc;
-       if (sc->pauseframe) {
-               ifp->if_timer = 5;
+
+       if (sc->sc_pauseframe) {
+               ifp->if_timer = 1;
                return;
        }
-       printf("%s: watchdog tx timeout\n", sc->sc_dev.dv_xname);
-       ifp->if_oerrors++;
-       sxie_init(sc);
-       sxie_start(ifp);
+
+       if (sc->sc_tx_timer > 0) {
+               if (--sc->sc_tx_timer == 0) {
+                       if (ifp->if_flags & IFF_DEBUG)
+                               printf("%s: watchdog tx timeout\n",
+                                   sc->sc_dev.dv_xname);
+                       ifp->if_oerrors++;
+                       sxie_init(sc);
+                       sxie_start(ifp);
+                       return;
+               }
+               ifp->if_timer = 1;
+       }
 }
 
 /*
@@ -582,8 +746,7 @@ sxie_recv(struct sxie_softc *sc)
        struct mbuf *m;
        uint16_t pktstat;
        int16_t pktlen;
-       int rlen;
-       char rxbuf[SXIE_MAX_PKT_SIZE]; /* XXX !!! */
+       char rxbuf[SXIE_MAX_PKT_SIZE];
 trynext:
        fbc = SXIREAD4(sc, SXIE_RXFBC);
        if (!fbc)
@@ -595,12 +758,7 @@ trynext:
         */
        reg = SXIREAD4(sc, SXIE_RXIO);
        if (reg != 0x0143414d) {        /* invalid packet */
-               /* disable, flush, enable */
-               SXICLR4(sc, SXIE_CR, SXIE_RX_ENABLE);
-               SXISET4(sc, SXIE_RXCR, SXIE_RXFLUSH);
-               while (SXIREAD4(sc, SXIE_RXCR) & SXIE_RXFLUSH);
-               SXISET4(sc, SXIE_CR, SXIE_RX_ENABLE);
-
+               sxie_softreset(sc, SXIE_SRST_RX);
                goto err_out;
        }
        
@@ -608,26 +766,20 @@ trynext:
        pktstat = (uint16_t)reg >> 16;
        pktlen = (int16_t)reg; /* length of useful data */
 
-       if (pktstat & SXIE_RX_ERRMASK || pktlen < ETHER_MIN_LEN) {
+       if (pktstat & SXIE_RX_ERRMASK || pktlen < ETHER_MIN_LEN ||
+           pktlen > SXIE_MAX_PKT_SIZE) {
                ifp->if_ierrors++;
                goto trynext;
        }
-       if (pktlen > SXIE_MAX_PKT_SIZE)
-               pktlen = SXIE_MAX_PKT_SIZE; /* XXX is truncating ok? */
 
        /* read the actual packet from fifo XXX through 'align buffer'.. */
-       if (pktlen & 3)
-               rlen = SXIE_ROUNDUP(pktlen, 4);
-       else
-               rlen = pktlen;
        bus_space_read_multi_4(sc->sc_iot, sc->sc_ioh,
-           SXIE_RXIO, (uint32_t *)&rxbuf[0], rlen >> 2);
+           SXIE_RXIO, (uint32_t *)&rxbuf[0],
+           (pktlen & 3 ? SXIE_ROUNDUP(pktlen, 4) : pktlen) >> 2);
 
        m = m_devget(&rxbuf[0], pktlen, ETHER_ALIGN);
-       if (m == NULL) {
-               ifp->if_ierrors++;
+       if (m == NULL)
                goto err_out;
-       }
 
        ml_enqueue(&ml, m);
        goto trynext;
@@ -671,7 +823,7 @@ sxie_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
        }
        if (error == ENETRESET) {
                if (ifp->if_flags & IFF_RUNNING)
-                       sxie_iff(sc, ifp);
+                       sxie_iff(sc);
                error = 0;
        }
 
@@ -680,9 +832,43 @@ sxie_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 }
 
 void
-sxie_iff(struct sxie_softc *sc, struct ifnet *ifp)
+sxie_iff(struct sxie_softc *sc)
 {
-       /* XXX set interface features */
+       struct arpcom *ac = &sc->sc_ac;
+       struct ifnet *ifp = &sc->sc_ac.ac_if;
+       struct ether_multi *enm;
+       struct ether_multistep step;
+       uint64_t rxfhash = 0;
+       uint32_t h;
+       uint32_t rxfilt;
+
+       rxfilt = SXIREAD4(sc, SXIE_RXFILTER_CTRL);
+       ifp->if_flags &= ~IFF_ALLMULTI;
+       if ((ifp->if_flags & IFF_PROMISC) || ac->ac_multirangecnt > 0) {
+               ifp->if_flags |= IFF_ALLMULTI;
+               rxfhash = 0xffffffffffffffffLLU;
+       } else {
+               ETHER_FIRST_MULTI(step, ac, enm);
+               while (enm != NULL) {
+                       h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
+
+                       rxfhash |= 1LLU << (((uint8_t *)&h)[3] >> 2);
+
+                       ETHER_NEXT_MULTI(step, enm);
+               }
+       }
+       SXIWRITE4(sc, SXIE_RXHASH0, (uint32_t)rxfhash);
+       SXIWRITE4(sc, SXIE_RXHASH1, (uint32_t)(rxfhash >> 32));
+
+       rxfilt |= SXIE_RXFILTER_UNICAST | SXIE_RXFILTER_DAFILTER |
+           SXIE_RXFILTER_MULTICAST;
+       if (ifp->if_flags & IFF_ALLMULTI)
+               rxfilt |= SXIE_RXFILTER_MHASHFILTER;
+       if (ifp->if_flags & IFF_BROADCAST)
+               rxfilt |= SXIE_RXFILTER_BROADCAST;
+       if (ifp->if_flags & IFF_PROMISC)
+               rxfilt |= SXIE_RXFILTER_PROMISC;
+       SXIWRITE4(sc, SXIE_RXFILTER_CTRL, rxfilt);
 }
 
 /*
@@ -693,21 +879,20 @@ sxie_miibus_readreg(struct device *dev, int phy, int reg)
 {
        struct sxie_softc *sc = (struct sxie_softc *)dev;
        int timo = SXIE_MII_TIMEOUT;
+       int rv;
 
-       SXIWRITE4(sc, SXIE_MACMADR, phy << 8 | reg);
-
-       SXIWRITE4(sc, SXIE_MACMCMD, 1);
-       while (SXIREAD4(sc, SXIE_MACMIND) & 1 && --timo)
+       SXIWRITE4(sc, SXIE_MAC_MADR, phy << 8 | reg);
+       SXIWRITE4(sc, SXIE_MAC_MCMD, 1);
+       while (SXIREAD4(sc, SXIE_MAC_MIND) & 1 && --timo)
                delay(10);
 #ifdef DIAGNOSTIC
        if (!timo)
-               printf("%s: sxie_miibus_readreg timeout.\n",
-                   sc->sc_dev.dv_xname);
+               printf("%s: %s timeout.\n", sc->sc_dev.dv_xname, __func__);
 #endif
 
-       SXIWRITE4(sc, SXIE_MACMCMD, 0);
-       
-       return SXIREAD4(sc, SXIE_MACMRDD) & 0xffff;
+       SXIWRITE4(sc, SXIE_MAC_MCMD, 0);
+       rv = SXIREAD4(sc, SXIE_MAC_MRDD) & 0xffff;
+       return rv;
 }
 
 void
@@ -716,38 +901,49 @@ sxie_miibus_writereg(struct device *dev, int phy, int 
reg, int val)
        struct sxie_softc *sc = (struct sxie_softc *)dev;
        int timo = SXIE_MII_TIMEOUT;
 
-       SXIWRITE4(sc, SXIE_MACMADR, phy << 8 | reg);
-
-       SXIWRITE4(sc, SXIE_MACMCMD, 1);
-       while (SXIREAD4(sc, SXIE_MACMIND) & 1 && --timo)
+       SXIWRITE4(sc, SXIE_MAC_MADR, phy << 8 | reg);
+       SXIWRITE4(sc, SXIE_MAC_MCMD, 1);
+       while (SXIREAD4(sc, SXIE_MAC_MIND) & 1 && --timo)
                delay(10);
 #ifdef DIAGNOSTIC
        if (!timo)
-               printf("%s: sxie_miibus_readreg timeout.\n",
-                   sc->sc_dev.dv_xname);
+               printf("%s: %s timeout.\n", sc->sc_dev.dv_xname, __func__);
 #endif
 
-       SXIWRITE4(sc, SXIE_MACMCMD, 0);
-
-       SXIWRITE4(sc, SXIE_MACMWTD, val);
+       SXIWRITE4(sc, SXIE_MAC_MCMD, 0);
+       SXIWRITE4(sc, SXIE_MAC_MWTD, val);
 }
 
 void
 sxie_miibus_statchg(struct device *dev)
 {
-       /* XXX */
-#if 0
        struct sxie_softc *sc = (struct sxie_softc *)dev;
+       uint64_t mma = sc->sc_mii.mii_media_active;
+       uint64_t _valid = IFM_ACTIVE | IFM_AVALID;
+
+       if ((mma & _valid) != _valid)
+               return;         /* no link */
 
-       switch (IFM_SUBTYPE(sc->sc_mii.mii_media_active)) {
+       switch (IFM_SUBTYPE(mma)) {
        case IFM_10_T:
+               SXICLR4(sc, SXIE_MAC_SUPP, SXIE_MAC_SUPP_SPEED);
+               break;
        case IFM_100_TX:
-       /*case IFM_1000_T: only on GMAC */
+               SXISET4(sc, SXIE_MAC_SUPP, SXIE_MAC_SUPP_SPEED);
                break;
        default:
                break;
        }
-#endif
+
+       if (mma & IFM_FLOW) {
+               SXICMS4(sc, SXIE_MAC0,
+                   SXIE_MAC0_TXFLOWCTRL | SXIE_MAC0_RXFLOWCTRL,
+                   (mma & IFM_ETH_TXPAUSE ? SXIE_MAC0_TXFLOWCTRL : 0) |
+                   (mma & IFM_ETH_RXPAUSE ? SXIE_MAC0_RXFLOWCTRL : 0));
+       } else {
+               SXICLR4(sc, SXIE_MAC0, SXIE_MAC0_TXFLOWCTRL | 
SXIE_MAC0_RXFLOWCTRL);
+       }
+       SXICMS4(sc, SXIE_MAC1, 1, mma & IFM_FDX ? 1 : 0);
 }
 
 int

Reply via email to