From 0007a7cd31fd28476f545cee27d99593cdbb0d62 Mon Sep 17 00:00:00 2001 From: Jason Wright Date: Fri, 28 Aug 1998 19:06:53 +0000 Subject: o added link negotiation o sun4c support (XXX: will be revised) --- sys/arch/sparc/dev/be.c | 86 ++++++++++++++++++++++++++++++++++++++-------- sys/arch/sparc/dev/bereg.h | 8 +++-- sys/arch/sparc/dev/bevar.h | 3 +- 3 files changed, 79 insertions(+), 18 deletions(-) diff --git a/sys/arch/sparc/dev/be.c b/sys/arch/sparc/dev/be.c index 83aaa8453f1..6a592033dce 100644 --- a/sys/arch/sparc/dev/be.c +++ b/sys/arch/sparc/dev/be.c @@ -1,4 +1,4 @@ -/* $OpenBSD: be.c,v 1.6 1998/08/26 05:00:51 jason Exp $ */ +/* $OpenBSD: be.c,v 1.7 1998/08/28 19:06:46 jason Exp $ */ /* * Copyright (c) 1998 Theo de Raadt and Jason L. Wright. @@ -29,10 +29,12 @@ #include #include -#include -#include +#include +#include #include +#include #include +#include #include #include @@ -95,6 +97,8 @@ int be_tcvr_read_bit1 __P((struct besoftc *sc)); int be_tcvr_read_bit2 __P((struct besoftc *sc)); int be_tcvr_read __P((struct besoftc *sc, u_int8_t reg)); +void be_negotiate_watchdog __P((void *)); + struct cfdriver be_cd = { NULL, "be", DV_IFNET }; @@ -230,7 +234,7 @@ bestart(ifp) (len & BE_TXD_LENGTH); sc->sc_cr->ctrl = BE_CR_CTRL_TWAKEUP; - if (++bix == BE_TX_RING_SIZE) + if (++bix == BE_TX_RING_MAXSIZE) bix = 0; if (++sc->sc_no_td == BE_TX_RING_SIZE) { @@ -461,7 +465,7 @@ betint(sc) ifp->if_flags &= ~IFF_OACTIVE; ifp->if_opackets++; - if (++bix == BE_TX_RING_SIZE) + if (++bix == BE_TX_RING_MAXSIZE) bix = 0; --sc->sc_no_td; @@ -505,7 +509,7 @@ berint(sc) bcopy(&rxd, &sc->sc_desc->be_rxd[bix], sizeof(rxd)); - if (++bix == BE_RX_RING_SIZE) + if (++bix == BE_RX_RING_MAXSIZE) bix = 0; } @@ -631,6 +635,9 @@ beinit(sc) int s = splimp(); int i; + untimeout(be_negotiate_watchdog, sc); + sc->sc_nticks = 0; + qec_reset(sc->sc_qec); /* @@ -658,14 +665,14 @@ beinit(sc) sc->sc_bufs_dva = (struct be_bufs *) dvma_malloc( sizeof(struct be_bufs), &sc->sc_bufs, M_NOWAIT); - for (i = 0; i < BE_TX_RING_SIZE; i++) { + for (i = 0; i < BE_TX_RING_MAXSIZE; i++) { sc->sc_desc->be_txd[i].tx_addr = - (u_int32_t) &sc->sc_bufs_dva->tx_buf[i][0]; + (u_int32_t) &sc->sc_bufs_dva->tx_buf[i % BE_TX_RING_SIZE][0]; sc->sc_desc->be_txd[i].tx_flags = 0; } - for (i = 0; i < BE_RX_RING_SIZE; i++) { + for (i = 0; i < BE_RX_RING_MAXSIZE; i++) { sc->sc_desc->be_rxd[i].rx_addr = - (u_int32_t) &sc->sc_bufs_dva->rx_buf[i][0]; + (u_int32_t) &sc->sc_bufs_dva->rx_buf[i % BE_RX_RING_SIZE][0]; sc->sc_desc->be_rxd[i].rx_flags = BE_RXD_OWN | (BE_PKT_BUF_SZ & BE_RXD_LENGTH); @@ -745,10 +752,32 @@ void be_tcvr_setspeed(sc) struct besoftc *sc; { - int x; + int x, tries, i; + + be_tcvr_write(sc, PHY_BMCR, + PHY_BMCR_LOOPBACK | PHY_BMCR_PDOWN | PHY_BMCR_ISOLATE); + be_tcvr_write(sc, PHY_BMCR, PHY_BMCR_RESET); + + for (tries = 0; tries < 16; i++) { + x = be_tcvr_read(sc, PHY_BMCR); + if ((x & PHY_BMCR_RESET) == 0) + break; + DELAY(20); + } + + x = be_tcvr_read(sc, PHY_BMCR); + be_tcvr_write(sc, PHY_BMCR, x & (~PHY_BMCR_ISOLATE)); + + for (tries = 0; tries < 32; i++) { + x = be_tcvr_read(sc, PHY_BMCR); + if ((x & PHY_BMCR_ISOLATE) == 0) + break; + DELAY(20); + } - be_tcvr_write(sc, PHY_BMCR, 0); x = be_tcvr_read(sc, PHY_BMSR); + if ((x & PHY_BMSR_LINKSTATUS) == 0) + timeout(be_negotiate_watchdog, sc, (12 * hz)/10); } /* @@ -1014,7 +1043,8 @@ be_put(sc, idx, m) MFREE(m, n); continue; } - bcopy(mtod(m, caddr_t), &sc->sc_bufs->tx_buf[idx][boff], len); + bcopy(mtod(m, caddr_t), + ((char *)sc->sc_desc->be_txd[idx].tx_addr) + boff, len); boff += len; tlen += len; MFREE(m, n); @@ -1112,7 +1142,8 @@ be_get(sc, idx, totlen) len = MCLBYTES; } m->m_len = len = min(totlen, len); - bcopy(&sc->sc_bufs->rx_buf[idx][boff], mtod(m, caddr_t), len); + bcopy(((char *)sc->sc_desc->be_rxd[idx].rx_addr) + boff, + mtod(m, caddr_t), len); boff += len; totlen -= len; *mp = m; @@ -1121,3 +1152,30 @@ be_get(sc, idx, totlen) return (top); } + +void +be_negotiate_watchdog(v) + void *v; +{ + struct besoftc *sc = (struct besoftc *)v; + int x; + + if (sc->sc_nticks == BE_NEGOTIATE_MAXTICKS) { + sc->sc_nticks = 0; + be_tcvr_setspeed(sc); + return; + } + sc->sc_nticks++; + + x = be_tcvr_read(sc, PHY_BMSR); + if ((x & PHY_BMSR_LINKSTATUS) == 0) { + timeout(be_negotiate_watchdog, sc, (12 * hz)/10); + return; + } + + x = be_tcvr_read(sc, PHY_BMCR); + printf("%s: %d Mb/s %s duplex, link up.\n", + sc->sc_dev.dv_xname, + (x & PHY_BMCR_SPEED) ? 100 : 10, + (x & PHY_BMCR_DUPLEX) ? "full" : "half"); +} diff --git a/sys/arch/sparc/dev/bereg.h b/sys/arch/sparc/dev/bereg.h index 8097d808bd6..d2656cde912 100644 --- a/sys/arch/sparc/dev/bereg.h +++ b/sys/arch/sparc/dev/bereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bereg.h,v 1.3 1998/08/26 05:00:53 jason Exp $ */ +/* $OpenBSD: bereg.h,v 1.4 1998/08/28 19:06:48 jason Exp $ */ /* * Copyright (c) 1998 Theo de Raadt and Jason L. Wright. @@ -241,8 +241,8 @@ struct be_txd { /* Buffer and Ring sizes: fixed ring size */ #define BE_TX_RING_MAXSIZE 256 /* maximum tx ring size */ #define BE_RX_RING_MAXSIZE 256 /* maximum rx ring size */ -#define BE_TX_RING_SIZE BE_TX_RING_MAXSIZE -#define BE_RX_RING_SIZE BE_RX_RING_MAXSIZE +#define BE_TX_RING_SIZE 16 +#define BE_RX_RING_SIZE 16 #define BE_PKT_BUF_SZ 2048 /* @@ -272,6 +272,8 @@ struct be_bufs { #define BE_TCVR_READ_INVALID 0xff000000 +#define BE_NEGOTIATE_MAXTICKS 16 + #define PHY_BMCR 0x00 /* Basic Mode Control Register */ #define PHY_BMSR 0x01 /* Basic Mode Status Register */ diff --git a/sys/arch/sparc/dev/bevar.h b/sys/arch/sparc/dev/bevar.h index 572b642ffba..2f1b6793ae0 100644 --- a/sys/arch/sparc/dev/bevar.h +++ b/sys/arch/sparc/dev/bevar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bevar.h,v 1.5 1998/08/26 05:00:54 jason Exp $ */ +/* $OpenBSD: bevar.h,v 1.6 1998/08/28 19:06:52 jason Exp $ */ /* * Copyright (c) 1998 Theo de Raadt and Jason L. Wright. @@ -47,6 +47,7 @@ struct besoftc { int sc_promisc; int sc_burst; int sc_tcvr_type; + int sc_nticks; /* negotiation ticks */ struct be_bufs *sc_bufs, *sc_bufs_dva; struct be_desc *sc_desc, *sc_desc_dva; -- cgit v1.2.3