- add one more missing RXC_EN.

- handle link speed change.
- fix genmask0() bit mask generation error.
This commit is contained in:
nisimura 2020-03-21 08:16:19 +00:00
parent ab427befe9
commit 84a92abc7d

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ave.c,v 1.6 2020/03/21 07:16:16 nisimura Exp $ */
/* $NetBSD: if_ave.c,v 1.7 2020/03/21 08:16:19 nisimura Exp $ */
/*-
* Copyright (c) 2020 The NetBSD Foundation, Inc.
@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_ave.c,v 1.6 2020/03/21 07:16:16 nisimura Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_ave.c,v 1.7 2020/03/21 08:16:19 nisimura Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@ -122,7 +122,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_ave.c,v 1.6 2020/03/21 07:16:16 nisimura Exp $");
#define AVEAFMSKB 0x0d00 /* byte mask base */
#define MSKBYTE0 0xfffffff3f /* zeros in 7:6 */
#define MSKBYTE1 0x003ffffff /* ones in 25:0 */
#define genmask0(x) (MSKBYTE0 & (~0U << (32-(x))))
#define genmask0(x) (MSKBYTE0 & (~0U << (x)))
#define AVEAFMSKV 0x0e00 /* bit mask base */
#define AVEAFRING 0x0f00 /* entry ring number selector */
#define AVEAFEN 0x0ffc /* entry enable bit vector */
@ -132,6 +132,11 @@ __KERNEL_RCSID(0, "$NetBSD: if_ave.c,v 1.6 2020/03/21 07:16:16 nisimura Exp $");
#define AVE32TDB 0x1000 /* 32bit Tx store base, upto 256 */
#define AVE32RDB 0x1800 /* 32bit Rx store base, upto 2048 */
#define AVERMIIC 0x8028 /* RMII control */
#define RMIIC_RST (1U<<16) /* reset */
#define AVELINKSEL 0x8034 /* link speed selection */
#define LINKSEL_SPD100 (1U<<0) /* RMII speed 100Mbps */
/*
* descriptor size is 12 bytes when 64bit paddr design, 8 bytes otherwise.
*/
@ -635,17 +640,19 @@ mii_statchg(struct ifnet *ifp)
{
struct ave_softc *sc = ifp->if_softc;
struct mii_data *mii = &sc->sc_mii;
uint32_t txcr, rxcr;
struct ifmedia * const ifm = &mii->mii_media;
uint32_t txcr, rxcr, csr;
/* Get flow control negotiation result. */
/* get flow control negotiation result */
if (IFM_SUBTYPE(mii->mii_media.ifm_cur->ifm_media) == IFM_AUTO &&
(mii->mii_media_active & IFM_ETH_FMASK) != sc->sc_flowflags)
sc->sc_flowflags = mii->mii_media_active & IFM_ETH_FMASK;
/* Adjust PAUSE flow control. */
txcr = CSR_READ(sc, AVETXC);
rxcr = CSR_READ(sc, AVERXC);
CSR_WRITE(sc, AVERXC, rxcr &~ RXC_EN); /* stop Rx first */
/* adjust 802.3x PAUSE flow control */
if ((mii->mii_media_active & IFM_FDX)
&& (sc->sc_flowflags & IFM_ETH_TXPAUSE))
txcr |= TXC_FCE;
@ -656,9 +663,28 @@ mii_statchg(struct ifnet *ifp)
rxcr |= RXC_FCE;
else
rxcr &= ~RXC_FCE;
/* HW does not handle auto speed adjustment */
txcr &= ~(TXC_SPD1000 | TXC_SPD100);
if ((sc->sc_phymode & CFG_MII) == 0 /* RGMII model */
&& IFM_SUBTYPE(ifm->ifm_cur->ifm_media) == IFM_100_TX)
txcr |= TXC_SPD1000;
else if (IFM_SUBTYPE(ifm->ifm_cur->ifm_media) == IFM_100_TX)
txcr |= TXC_SPD100;
/* adjust LINKSEL when MII/RMII too */
if (sc->sc_phymode & CFG_MII) {
csr = CSR_READ(sc, AVELINKSEL);
if (IFM_SUBTYPE(ifm->ifm_cur->ifm_media) == IFM_100_TX)
csr |= LINKSEL_SPD100;
else
csr &= ~LINKSEL_SPD100;
CSR_WRITE(sc, AVELINKSEL, csr);
}
sc->sc_rxc = rxcr;
CSR_WRITE(sc, AVETXC, txcr);
CSR_WRITE(sc, AVERXC, rxcr);
CSR_WRITE(sc, AVERXC, rxcr | RXC_EN);
printf("%ctxfe, %crxfe\n",
(txcr & TXC_FCE) ? '+' : '-', (rxcr & RXC_FCE) ? '+' : '-');
@ -776,22 +802,25 @@ ave_ioctl(struct ifnet *ifp, u_long cmd, void *data)
static void
ave_write_filt(struct ave_softc *sc, int i, const uint8_t *en)
{
uint32_t n, macl, mach;
uint32_t macl, mach, n, mskbyte0;
/* pick v4mcast or v6mcast length */
n = (en[0] == 0x01) ? 3 : (en[0] == 0x33) ? 2 : ETHER_ADDR_LEN;
macl = mach = 0;
macl |= (en[3]<<24) | (en[2]<<16)| (en[1]<<8) | en[0];
mach |= (en[5]<<8) | en[4];
/* pick v4mcast or v6mcast length */
n = (en[0] == 0x01) ? 3 : (en[0] == 0x33) ? 2 : ETHER_ADDR_LEN;
/* entry 0 is reserved for promisc mode */
mskbyte0 = (i > 0) ? genmask0(n) : MSKBYTE0;
/* set frame address first */
CSR_WRITE(sc, AVEAFB + (i * 0x40) + 0, macl);
CSR_WRITE(sc, AVEAFB + (i * 0x40) + 4, mach);
/* set byte mask according to mask length, any of 6, 3, or 2 */
CSR_WRITE(sc, AVEAFMSKB + (i * 8) + 0, genmask0(n));
CSR_WRITE(sc, AVEAFMSKB + (i * 8) + 0, mskbyte0);
CSR_WRITE(sc, AVEAFMSKB + (i * 8) + 4, MSKBYTE1);
/* set bit vector mask */
CSR_WRITE(sc, AVEAFMSKV + (i * 4), 0xffff);
/* use Rx ring 0 for any entry */
/* use Rx ring 0 anyway */
CSR_WRITE(sc, AVEAFRING + (i * 4), 0);
/* filter entry enable bit vector */
CSR_WRITE(sc, AVEAFEN, CSR_READ(sc, AVEAFEN) | 1U << i);