sxie(4): is this work on pcDuino v1?

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

sxie(4): is this work on pcDuino v1?

SASANO Takayoshi
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?
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) <[hidden email]>

Reply | Threaded
Open this post in threaded view
|

Re: sxie(4): is this work on pcDuino v1?

Artturi Alm
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) <[hidden email]>
>



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 | Threaded
Open this post in threaded view
|

Re: sxie(4): is this work on pcDuino v1?

SASANO Takayoshi
On Thu, 22 Mar 2018 08:59:55 +0900,
Artturi Alm wrote:
> 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

Hello,

"nemesis" is a packet generator that we can use by ports/net/nemesis.
It is easy to send test packet so I used it.

I applied your sxie.c patch but the problem is not solved, same as
not patched... corrupt packet is still sent.

And none packets are received, the log of tcpdump -i sxie0 shows nothing.

Artturi, you use Miniand Hackberry board and does the U-boot for this board
support sxie ethernet? My pcDuino's U-boot does not.

I think something (not MAC controller but others) is not setup correctly
so I want to check, what should I start from?
--
SASANO Takayoshi (JG1UAA) <[hidden email]>

Reply | Threaded
Open this post in threaded view
|

Re: sxie(4): is this work on pcDuino v1?

Mark Kettenis
> Date: Sat, 24 Mar 2018 22:18:03 +0900
> From: SASANO Takayoshi <[hidden email]>
>
> On Thu, 22 Mar 2018 08:59:55 +0900,
> Artturi Alm wrote:
> > 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
>
> Hello,
>
> "nemesis" is a packet generator that we can use by ports/net/nemesis.
> It is easy to send test packet so I used it.
>
> I applied your sxie.c patch but the problem is not solved, same as
> not patched... corrupt packet is still sent.
>
> And none packets are received, the log of tcpdump -i sxie0 shows nothing.
>
> Artturi, you use Miniand Hackberry board and does the U-boot for this board
> support sxie ethernet? My pcDuino's U-boot does not.
>
> I think something (not MAC controller but others) is not setup correctly
> so I want to check, what should I start from?

I believe the sunxi EMAC uses SRAM and that the current sxie(4) driver
expects that SRAM to be properly initialized and set up by U-Boot.

In sunxi_emac_board_setup() U-Boot does:

        /* Map SRAM to EMAC */
        setbits_le32(&sram->ctrl1, 0x5 << 2);

Not sure if that is all that is needed.  Doing that from inside the
sxie(4) driver code is a bit hard; this would probably require adding
a driver for the sram-controller ("allwinner,sun4i-a10-sram-controller").

Cheers,

Mark



Reply | Threaded
Open this post in threaded view
|

Re: sxie(4): is this work on pcDuino v1?

SASANO Takayoshi
Hello,

On Sat, 24 Mar 2018 22:38:42 +0900,
Mark Kettenis wrote:

> I believe the sunxi EMAC uses SRAM and that the current sxie(4) driver
> expects that SRAM to be properly initialized and set up by U-Boot.
>
> In sunxi_emac_board_setup() U-Boot does:
>
>         /* Map SRAM to EMAC */
>         setbits_le32(&sram->ctrl1, 0x5 << 2);
>
> Not sure if that is all that is needed.  Doing that from inside the
> sxie(4) driver code is a bit hard; this would probably require adding
> a driver for the sram-controller ("allwinner,sun4i-a10-sram-controller").

I checked the compiled object of U-boot (from
/usr/ports/pobj/u-boot-arm-2017.09-arm/u-boot-2017.09/build), there is no
EMAC driver for not only Linksprite_pcDuino but also many A10 based board.

It is the best that initializing SRAM controller in OpenBSD, but
it is curious why EMAC controller is disabled in U-boot...

Regards,
--
SASANO Takayoshi (JG1UAA) <[hidden email]>

Reply | Threaded
Open this post in threaded view
|

Re: sxie(4): is this work on pcDuino v1?

Artturi Alm
On Sat, Mar 24, 2018 at 11:31:36PM +0900, SASANO Takayoshi wrote:

> Hello,
>
> On Sat, 24 Mar 2018 22:38:42 +0900,
> Mark Kettenis wrote:
> > I believe the sunxi EMAC uses SRAM and that the current sxie(4) driver
> > expects that SRAM to be properly initialized and set up by U-Boot.
> >
> > In sunxi_emac_board_setup() U-Boot does:
> >
> >         /* Map SRAM to EMAC */
> >         setbits_le32(&sram->ctrl1, 0x5 << 2);
> >
> > Not sure if that is all that is needed.  Doing that from inside the
> > sxie(4) driver code is a bit hard; this would probably require adding
> > a driver for the sram-controller ("allwinner,sun4i-a10-sram-controller").
>
> I checked the compiled object of U-boot (from
> /usr/ports/pobj/u-boot-arm-2017.09-arm/u-boot-2017.09/build), there is no
> EMAC driver for not only Linksprite_pcDuino but also many A10 based board.
>

fixed in 2017.11:
http://git.denx.de/?p=u-boot.git;a=commit;h=e286fada9d434cd211b56fa7a4b5ef8965577e7f

you should really update.

> It is the best that initializing SRAM controller in OpenBSD, but
> it is curious why EMAC controller is disabled in U-boot...

Commit msg from above url does explain, just a 'bug' due err in maintenance
within U-Boot.
i agree with Mark, this should be handled in a driver for the sram-controller.

-Artturi

>
> Regards,
> --
> SASANO Takayoshi (JG1UAA) <[hidden email]>

Reply | Threaded
Open this post in threaded view
|

Re: sxie(4): is this work on pcDuino v1?

SASANO Takayoshi
On Sun, 25 Mar 2018 00:45:14 +0900,
Artturi Alm wrote:

>
> On Sat, Mar 24, 2018 at 11:31:36PM +0900, SASANO Takayoshi wrote:
> > Hello,
> >
> > On Sat, 24 Mar 2018 22:38:42 +0900,
> > Mark Kettenis wrote:
> > > I believe the sunxi EMAC uses SRAM and that the current sxie(4) driver
> > > expects that SRAM to be properly initialized and set up by U-Boot.
> > >
> > > In sunxi_emac_board_setup() U-Boot does:
> > >
> > >         /* Map SRAM to EMAC */
> > >         setbits_le32(&sram->ctrl1, 0x5 << 2);
> > >
> > > Not sure if that is all that is needed.  Doing that from inside the
> > > sxie(4) driver code is a bit hard; this would probably require adding
> > > a driver for the sram-controller ("allwinner,sun4i-a10-sram-controller").
> >
> > I checked the compiled object of U-boot (from
> > /usr/ports/pobj/u-boot-arm-2017.09-arm/u-boot-2017.09/build), there is no
> > EMAC driver for not only Linksprite_pcDuino but also many A10 based board.
> >
>
> fixed in 2017.11:
> http://git.denx.de/?p=u-boot.git;a=commit;h=e286fada9d434cd211b56fa7a4b5ef8965577e7f
>
> you should really update.
>

I upgraded U-boot from 2017.09 to 2018.03 in -current ports and
checked that sxie.c (with/without patch) is work with new U-boot.

Thanks to Artturi and Mark.
Regards,

--
SASANO Takayoshi (JG1UAA) <[hidden email]>