From f95724bd6b39acfe614b8ba069e0c50ba4ded753 Mon Sep 17 00:00:00 2001 From: scw Date: Tue, 29 Apr 2003 08:47:29 +0000 Subject: [PATCH] Add support for the SMC91C111 chip, with its internal PHY. --- sys/dev/ic/smc91cxx.c | 69 ++++++++++++++++++++++++++++++++++------ sys/dev/ic/smc91cxxreg.h | 28 ++++++++++++++-- sys/dev/ic/smc91cxxvar.h | 3 +- 3 files changed, 88 insertions(+), 12 deletions(-) diff --git a/sys/dev/ic/smc91cxx.c b/sys/dev/ic/smc91cxx.c index 4a3c989a7a5c..b03965d59be5 100644 --- a/sys/dev/ic/smc91cxx.c +++ b/sys/dev/ic/smc91cxx.c @@ -1,4 +1,4 @@ -/* $NetBSD: smc91cxx.c,v 1.44 2002/10/22 00:01:57 fair Exp $ */ +/* $NetBSD: smc91cxx.c,v 1.45 2003/04/29 08:47:29 scw Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -78,7 +78,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: smc91cxx.c,v 1.44 2002/10/22 00:01:57 fair Exp $"); +__KERNEL_RCSID(0, "$NetBSD: smc91cxx.c,v 1.45 2003/04/29 08:47:29 scw Exp $"); #include "opt_inet.h" #include "opt_ccitt.h" @@ -165,7 +165,7 @@ const char *smc91cxx_idstrs[] = { NULL, /* 6 */ "SMC91C100", /* 7 */ "SMC91C100FD", /* 8 */ - NULL, /* 9 */ + "SMC91C111", /* 9 */ NULL, /* 10 */ NULL, /* 11 */ NULL, /* 12 */ @@ -245,7 +245,7 @@ smc91cxx_attach(sc, myea) u_int32_t miicapabilities; u_int16_t tmp; u_int8_t enaddr[ETHER_ADDR_LEN]; - int i, aui, mult, memsize; + int i, aui, mult, scale, memsize; char pbuf[9]; /* Make sure the chip is stopped. */ @@ -268,10 +268,19 @@ smc91cxx_attach(sc, myea) printf("revision %d, ", RR_REV(tmp)); SMC_SELECT_BANK(sc, 0); - mult = MCR_MEM_MULT(bus_space_read_2(bst, bsh, MEM_CFG_REG_W)); + switch (sc->sc_chipid) { + default: + mult = MCR_MEM_MULT(bus_space_read_2(bst, bsh, MEM_CFG_REG_W)); + scale = MIR_SCALE_91C9x; + break; + + case CHIP_91C111: + mult = MIR_MULT_91C111; + scale = MIR_SCALE_91C111; + } memsize = bus_space_read_2(bst, bsh, MEM_INFO_REG_W) & MIR_TOTAL_MASK; if (memsize == 255) memsize++; - memsize *= 256 * mult; + memsize *= scale * mult; format_bytes(pbuf, sizeof(pbuf), memsize); printf("buffer size: %s\n", pbuf); @@ -325,8 +334,15 @@ smc91cxx_attach(sc, myea) */ miicapabilities &= ~(BMSR_100TXFDX | BMSR_10TFDX); case CHIP_91100FD: + case CHIP_91C111: if (tmp & CR_MII_SELECT) { - printf("default media MII\n"); + printf("default media MII"); + if (sc->sc_chipid == CHIP_91C111) { + printf(" (%s PHY)\n", (tmp & CR_AUI_SELECT) ? + "external" : "internal"); + sc->sc_internal_phy = !(tmp & CR_AUI_SELECT); + } else + printf("\n"); mii_attach(&sc->sc_dev, &sc->sc_mii, miicapabilities, MII_PHY_ANY, MII_OFFSET_ANY, 0); if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { @@ -340,6 +356,14 @@ smc91cxx_attach(sc, myea) } sc->sc_flags |= SMC_FLAGS_HAS_MII; break; + } else + if (sc->sc_chipid == CHIP_91C111) { + /* + * XXX: Should bring it out of low-power mode + */ + printf("EPH interface in low power mode\n"); + sc->sc_internal_phy = 0; + return; } /*FALLTHROUGH*/ default: @@ -510,6 +534,19 @@ smc91cxx_init(sc) */ bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0); + /* + * On the 91c111, enable auto-negotiation, and set the LED + * status pins to something sane. + * XXX: Should be some way for MD code to decide the latter. + */ + SMC_SELECT_BANK(sc, 0); + if (sc->sc_chipid == CHIP_91C111) { + bus_space_write_2(bst, bsh, RX_PHY_CONTROL_REG_W, + RPC_ANEG | + (RPC_LS_LINK_DETECT << RPC_LSA_SHIFT) | + (RPC_LS_TXRX << RPC_LSB_SHIFT)); + } + /* * Set current media. */ @@ -551,8 +588,14 @@ smc91cxx_init(sc) */ SMC_SELECT_BANK(sc, 2); - bus_space_write_1(bst, bsh, INTR_MASK_REG_B, - IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT); + if (sc->sc_chipid == CHIP_91C111 && sc->sc_internal_phy) { + bus_space_write_1(bst, bsh, INTR_MASK_REG_B, + IM_EPH_INT | IM_RX_OVRN_INT | + IM_RCV_INT | IM_TX_INT | IM_MD_INT); + } else { + bus_space_write_1(bst, bsh, INTR_MASK_REG_B, + IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT); + } /* Interface is now running, with no output active. */ ifp->if_flags |= IFF_RUNNING; @@ -996,6 +1039,14 @@ smc91cxx_intr(arg) ifp->if_timer = 0; } + if (sc->sc_chipid == CHIP_91C111 && sc->sc_internal_phy && + (status & IM_MD_INT)) { + /* + * Internal PHY status change + */ + mii_tick(&sc->sc_mii); + } + /* * Other errors. Reset the interface. */ diff --git a/sys/dev/ic/smc91cxxreg.h b/sys/dev/ic/smc91cxxreg.h index eb80341b2f14..86e2ca15b0d6 100644 --- a/sys/dev/ic/smc91cxxreg.h +++ b/sys/dev/ic/smc91cxxreg.h @@ -1,4 +1,4 @@ -/* $NetBSD: smc91cxxreg.h,v 1.4 2001/06/12 15:17:23 wiz Exp $ */ +/* $NetBSD: smc91cxxreg.h,v 1.5 2003/04/29 08:47:30 scw Exp $ */ /* * Copyright (c) 1996 Gardner Buchanan @@ -172,16 +172,38 @@ #define MIR_FREE_MASK 0xff00 /* Free memory pages available */ #define MIR_TOTAL_MASK 0x00ff /* Total memory pages available */ +#define MIR_MULT_91C111 1 +#define MIR_SCALE_91C9x 256 +#define MIR_SCALE_91C111 2048 /* * Memory Configuration */ -#define MEM_CFG_REG_W 0x0a +#define MEM_CFG_REG_W 0x0a #define MCR_MEM_MULT(x) (((x)>>9)&7) /* Memory size multiplier */ #define MCR_TXRSV_MASK 0x001f /* Count of pages reserved for transmit */ +/* + * Receive/PHY Control Register (SM91C111 only) + */ +#define RX_PHY_CONTROL_REG_W 0x0a /* 91C111 only */ + +#define RPC_LSB_SHIFT 2 /* Shift for LED-B select bits */ +#define RPC_LSA_SHIFT 5 /* Shift for LED-A select bits */ +#define RPC_LS_MASK 0x7 /* LED Select mask */ +#define RPC_LS_LINK_DETECT 0x0 /* 10/100 link detected */ +#define RPC_LS_LINK_10MBPS 0x2 /* 10 MBPS link detected */ +#define RPC_LS_FULL_DUPLEX 0x3 /* Full duplex operation */ +#define RPC_LS_TXRX 0x4 /* Tx/Rx packet */ +#define RPC_LS_LINK_100MBPS 0x5 /* 100 MBPS link detected */ +#define RPC_LS_RX 0x6 /* Rx packet */ +#define RPC_LS_TX 0x7 /* Tx packet */ +#define RPC_ANEG 0x0800 /* Autonegotiate enable */ +#define RPC_DPLX 0x1000 /* Duplex select (set = Full) */ +#define RPC_SPEED 0x2000 /* Speed (set = 100mbps) */ + /* * Bank 0, Register 0x0c is unused in the SMC91C92 @@ -346,6 +368,7 @@ #define IM_RX_OVRN_INT 0x10 /* Receiver was overrun */ #define IM_EPH_INT 0x20 /* Misc. EPH conditions (see CONTROL_REG_W) */ #define IM_ERCV_INT 0x40 /* not on SMC9192 */ +#define IM_MD_INT 0x80 /* SMC91C111 Internal PHY status change */ /* @@ -396,6 +419,7 @@ #define CHIP_9195 5 #define CHIP_91100 7 #define CHIP_91100FD 8 +#define CHIP_91C111 9 /* diff --git a/sys/dev/ic/smc91cxxvar.h b/sys/dev/ic/smc91cxxvar.h index d0483fdf1d0c..9527f5c866d4 100644 --- a/sys/dev/ic/smc91cxxvar.h +++ b/sys/dev/ic/smc91cxxvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: smc91cxxvar.h,v 1.10 2002/09/04 14:54:37 scw Exp $ */ +/* $NetBSD: smc91cxxvar.h,v 1.11 2003/04/29 08:47:30 scw Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -63,6 +63,7 @@ struct smc91cxx_softc { #define SMC_FLAGS_32BIT_READ 0x0008 /* reads are always 32-bits */ u_int8_t sc_chipid; + u_int8_t sc_internal_phy; /* 91C111 only */ #if NRND > 0 rndsource_element_t rnd_source;