diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2003-03-05 20:46:27 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2003-03-05 20:46:27 +0000 |
commit | b8fe8f289b94727dad721bf3d4a1f0f9fadfa32d (patch) | |
tree | c29d073f2cf605bd8e7f32305dd94f61caf6e123 /sys/dev/ic/hme.c | |
parent | 03367a2f3a1dc0afb2ccb2a8ac1636d4cae9b1a6 (diff) |
update media handling based on NetBSD: mainly fix setting up of the output
drivers
also, force a preference of the external phy a little earlier: both ports
on the netra T1/105 now work.
Diffstat (limited to 'sys/dev/ic/hme.c')
-rw-r--r-- | sys/dev/ic/hme.c | 149 |
1 files changed, 102 insertions, 47 deletions
diff --git a/sys/dev/ic/hme.c b/sys/dev/ic/hme.c index bf844c13f1a..3c58ffca01d 100644 --- a/sys/dev/ic/hme.c +++ b/sys/dev/ic/hme.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hme.c,v 1.25 2003/02/08 21:42:11 jason Exp $ */ +/* $OpenBSD: hme.c,v 1.26 2003/03/05 20:46:26 jason Exp $ */ /* $NetBSD: hme.c,v 1.21 2001/07/07 15:59:37 thorpej Exp $ */ /*- @@ -248,12 +248,17 @@ hme_config(sc) mii->mii_writereg = hme_mii_writereg; mii->mii_statchg = hme_mii_statchg; - ifmedia_init(&mii->mii_media, 0, hme_mediachange, hme_mediastatus); + ifmedia_init(&mii->mii_media, IFM_IMASK, + hme_mediachange, hme_mediastatus); hme_mifinit(sc); - mii_attach(&sc->sc_dev, mii, 0xffffffff, - MII_PHY_ANY, MII_OFFSET_ANY, 0); + if (sc->sc_tcvr == -1) + mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, + MII_OFFSET_ANY, 0); + else + mii_attach(&sc->sc_dev, mii, 0xffffffff, sc->sc_tcvr, + MII_OFFSET_ANY, 0); child = LIST_FIRST(&mii->mii_phys); if (child == NULL) { @@ -371,6 +376,9 @@ hme_stop(sc) timeout_del(&sc->sc_tick_ch); mii_down(&sc->sc_mii); + /* Mask all interrupts */ + bus_space_write_4(t, seb, HME_SEBI_IMASK, 0xffffffff); + /* Reset transmitter and receiver */ bus_space_write_4(t, seb, HME_SEBI_RESET, (HME_SEB_RESET_ETX | HME_SEB_RESET_ERX)); @@ -475,7 +483,6 @@ hme_init(sc) bus_space_handle_t etx = sc->sc_etx; bus_space_handle_t erx = sc->sc_erx; bus_space_handle_t mac = sc->sc_mac; - bus_space_handle_t mif = sc->sc_mif; u_int8_t *ea; u_int32_t v; @@ -591,12 +598,8 @@ hme_init(sc) /* step 11. XIF Configuration */ v = bus_space_read_4(t, mac, HME_MACI_XIF); v |= HME_MAC_XIF_OE; - /* If an external transceiver is connected, enable its MII drivers */ - if ((bus_space_read_4(t, mif, HME_MIFI_CFG) & HME_MIF_CFG_MDI1) != 0) - v |= HME_MAC_XIF_MIIENABLE; bus_space_write_4(t, mac, HME_MACI_XIF, v); - /* step 12. RX_MAC Configuration Register */ v = bus_space_read_4(t, mac, HME_MACI_RXCFG); v |= HME_MAC_RXCFG_ENABLE; @@ -874,17 +877,31 @@ hme_mifinit(sc) { bus_space_tag_t t = sc->sc_bustag; bus_space_handle_t mif = sc->sc_mif; + bus_space_handle_t mac = sc->sc_mac; + int phy; u_int32_t v; - /* Configure the MIF in frame mode */ v = bus_space_read_4(t, mif, HME_MIFI_CFG); - v &= ~HME_MIF_CFG_BBMODE; - bus_space_write_4(t, mif, HME_MIFI_CFG, v); - + phy = HME_PHYAD_EXTERNAL; if (v & HME_MIF_CFG_MDI1) - sc->sc_tcvr = HME_PHYAD_EXTERNAL; + phy = sc->sc_tcvr = HME_PHYAD_EXTERNAL; else if (v & HME_MIF_CFG_MDI0) - sc->sc_tcvr = HME_PHYAD_INTERNAL; + phy = sc->sc_tcvr = HME_PHYAD_INTERNAL; + else + sc->sc_tcvr = -1; + + /* Configure the MIF in frame mode, no poll, current phy select */ + v = 0; + if (phy == HME_PHYAD_EXTERNAL) + v |= HME_MIF_CFG_PHY; + bus_space_write_4(t, mif, HME_MIFI_CFG, v); + + /* If an external transceiver is selected, enable its MII drivers */ + v = bus_space_read_4(t, mac, HME_MACI_XIF); + v &= ~HME_MAC_XIF_MIIENABLE; + if (phy == HME_PHYAD_EXTERNAL) + v |= HME_MAC_XIF_MIIENABLE; + bus_space_write_4(t, mac, HME_MACI_XIF, v); } /* @@ -898,21 +915,28 @@ hme_mii_readreg(self, phy, reg) struct hme_softc *sc = (struct hme_softc *)self; bus_space_tag_t t = sc->sc_bustag; bus_space_handle_t mif = sc->sc_mif; + bus_space_handle_t mac = sc->sc_mac; + u_int32_t v, xif_cfg, mifi_cfg; int n; - u_int32_t v; - if (sc->sc_tcvr != phy) + if (phy != HME_PHYAD_EXTERNAL && phy != HME_PHYAD_INTERNAL) return (0); /* Select the desired PHY in the MIF configuration register */ - v = bus_space_read_4(t, mif, HME_MIFI_CFG); - /* Clear PHY select bit */ + v = mifi_cfg = bus_space_read_4(t, mif, HME_MIFI_CFG); v &= ~HME_MIF_CFG_PHY; if (phy == HME_PHYAD_EXTERNAL) - /* Set PHY select bit to get at external device */ v |= HME_MIF_CFG_PHY; bus_space_write_4(t, mif, HME_MIFI_CFG, v); + /* Enable MII drivers on external transceiver */ + v = xif_cfg = bus_space_read_4(t, mac, HME_MACI_XIF); + if (phy == HME_PHYAD_EXTERNAL) + v |= HME_MAC_XIF_MIIENABLE; + else + v &= ~HME_MAC_XIF_MIIENABLE; + bus_space_write_4(t, mac, HME_MACI_XIF, v); + /* Construct the frame command */ v = (MII_COMMAND_START << HME_MIF_FO_ST_SHIFT) | HME_MIF_FO_TAMSB | @@ -924,12 +948,21 @@ hme_mii_readreg(self, phy, reg) for (n = 0; n < 100; n++) { DELAY(1); v = bus_space_read_4(t, mif, HME_MIFI_FO); - if (v & HME_MIF_FO_TALSB) - return (v & HME_MIF_FO_DATA); + if (v & HME_MIF_FO_TALSB) { + v &= HME_MIF_FO_DATA; + goto out; + } } + v = 0; printf("%s: mii_read timeout\n", sc->sc_dev.dv_xname); - return (0); + +out: + /* Restore MIFI_CFG register */ + bus_space_write_4(t, mif, HME_MIFI_CFG, mifi_cfg); + /* Restore XIF register */ + bus_space_write_4(t, mac, HME_MACI_XIF, xif_cfg); + return (v); } static void @@ -940,21 +973,29 @@ hme_mii_writereg(self, phy, reg, val) struct hme_softc *sc = (void *)self; bus_space_tag_t t = sc->sc_bustag; bus_space_handle_t mif = sc->sc_mif; + bus_space_handle_t mac = sc->sc_mac; + u_int32_t v, xif_cfg, mifi_cfg; int n; - u_int32_t v; - if (sc->sc_tcvr != phy) + /* We can at most have two PHYs */ + if (phy != HME_PHYAD_EXTERNAL && phy != HME_PHYAD_INTERNAL) return; /* Select the desired PHY in the MIF configuration register */ - v = bus_space_read_4(t, mif, HME_MIFI_CFG); - /* Clear PHY select bit */ + v = mifi_cfg = bus_space_read_4(t, mif, HME_MIFI_CFG); v &= ~HME_MIF_CFG_PHY; if (phy == HME_PHYAD_EXTERNAL) - /* Set PHY select bit to get at external device */ v |= HME_MIF_CFG_PHY; bus_space_write_4(t, mif, HME_MIFI_CFG, v); + /* Enable MII drivers on external transceiver */ + v = xif_cfg = bus_space_read_4(t, mac, HME_MACI_XIF); + if (phy == HME_PHYAD_EXTERNAL) + v |= HME_MAC_XIF_MIIENABLE; + else + v &= ~HME_MAC_XIF_MIIENABLE; + bus_space_write_4(t, mac, HME_MACI_XIF, v); + /* Construct the frame command */ v = (MII_COMMAND_START << HME_MIF_FO_ST_SHIFT) | HME_MIF_FO_TAMSB | @@ -968,10 +1009,15 @@ hme_mii_writereg(self, phy, reg, val) DELAY(1); v = bus_space_read_4(t, mif, HME_MIFI_FO); if (v & HME_MIF_FO_TALSB) - return; + goto out; } printf("%s: mii_write timeout\n", sc->sc_dev.dv_xname); +out: + /* Restore MIFI_CFG register */ + bus_space_write_4(t, mif, HME_MIFI_CFG, mifi_cfg); + /* Restore XIF register */ + bus_space_write_4(t, mac, HME_MACI_XIF, xif_cfg); } static void @@ -979,26 +1025,18 @@ hme_mii_statchg(dev) struct device *dev; { struct hme_softc *sc = (void *)dev; - int instance = IFM_INST(sc->sc_mii.mii_media.ifm_cur->ifm_media); - int phy = sc->sc_phys[instance]; bus_space_tag_t t = sc->sc_bustag; - bus_space_handle_t mif = sc->sc_mif; bus_space_handle_t mac = sc->sc_mac; u_int32_t v; #ifdef HMEDEBUG if (sc->sc_debug) - printf("hme_mii_statchg: status change: phy = %d\n", phy); + printf("hme_mii_statchg: status change\n", phy); #endif - /* Select the current PHY in the MIF configuration register */ - v = bus_space_read_4(t, mif, HME_MIFI_CFG); - v &= ~HME_MIF_CFG_PHY; - if (phy == HME_PHYAD_EXTERNAL) - v |= HME_MIF_CFG_PHY; - bus_space_write_4(t, mif, HME_MIFI_CFG, v); - /* Set the MAC Full Duplex bit appropriately */ + /* Apparently the hme chip is SIMPLE if working in full duplex mode, + but not otherwise. */ v = bus_space_read_4(t, mac, HME_MACI_TXCFG); if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0) { v |= HME_MAC_TXCFG_FULLDPLX; @@ -1008,13 +1046,6 @@ hme_mii_statchg(dev) sc->sc_arpcom.ac_if.if_flags &= ~IFF_SIMPLEX; } bus_space_write_4(t, mac, HME_MACI_TXCFG, v); - - /* If an external transceiver is selected, enable its MII drivers */ - v = bus_space_read_4(t, mac, HME_MACI_XIF); - v &= ~HME_MAC_XIF_MIIENABLE; - if (phy == HME_PHYAD_EXTERNAL) - v |= HME_MAC_XIF_MIIENABLE; - bus_space_write_4(t, mac, HME_MACI_XIF, v); } int @@ -1022,10 +1053,34 @@ hme_mediachange(ifp) struct ifnet *ifp; { struct hme_softc *sc = ifp->if_softc; + bus_space_tag_t t = sc->sc_bustag; + bus_space_handle_t mif = sc->sc_mif; + bus_space_handle_t mac = sc->sc_mac; + int instance = IFM_INST(sc->sc_mii.mii_media.ifm_cur->ifm_media); + int phy = sc->sc_phys[instance]; + u_int32_t v; +#ifdef HMEDEBUG + if (sc->sc_debug) + printf("hme_mediachange: phy = %d\n", phy); +#endif if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_ETHER) return (EINVAL); + /* Select the current PHY in the MIF configuration register */ + v = bus_space_read_4(t, mif, HME_MIFI_CFG); + v &= ~HME_MIF_CFG_PHY; + if (phy == HME_PHYAD_EXTERNAL) + v |= HME_MIF_CFG_PHY; + bus_space_write_4(t, mif, HME_MIFI_CFG, v); + + /* If an external transceiver is selected, enable its MII drivers */ + v = bus_space_read_4(t, mac, HME_MACI_XIF); + v &= ~HME_MAC_XIF_MIIENABLE; + if (phy == HME_PHYAD_EXTERNAL) + v |= HME_MAC_XIF_MIIENABLE; + bus_space_write_4(t, mac, HME_MACI_XIF, v); + return (mii_mediachg(&sc->sc_mii)); } |