Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic Add support for selecting a PHY (i.e. built-in tr...
details: https://anonhg.NetBSD.org/src/rev/ae7b7789cbb2
branches: trunk
changeset: 479695:ae7b7789cbb2
user: pk <pk%NetBSD.org@localhost>
date: Sat Dec 18 14:05:37 1999 +0000
description:
Add support for selecting a PHY (i.e. built-in transceiver vs. external MII
device) by using media/instance parameters.
diffstat:
sys/dev/ic/hme.c | 129 +++++++++++++++++++++++++++++++++++++++++----------
sys/dev/ic/hmevar.h | 3 +-
2 files changed, 104 insertions(+), 28 deletions(-)
diffs (240 lines):
diff -r 6213c7a7492e -r ae7b7789cbb2 sys/dev/ic/hme.c
--- a/sys/dev/ic/hme.c Sat Dec 18 08:01:25 1999 +0000
+++ b/sys/dev/ic/hme.c Sat Dec 18 14:05:37 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hme.c,v 1.4 1999/12/17 14:37:15 pk Exp $ */
+/* $NetBSD: hme.c,v 1.5 1999/12/18 14:05:37 pk Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -43,14 +43,13 @@
#define HMEDEBUG
#include "opt_inet.h"
-#include "opt_ccitt.h"
-#include "opt_llc.h"
#include "opt_ns.h"
#include "bpfilter.h"
#include "rnd.h"
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/syslog.h>
#include <sys/socket.h>
@@ -96,6 +95,7 @@
void hme_start __P((struct ifnet *));
void hme_stop __P((struct hme_softc *));
int hme_ioctl __P((struct ifnet *, u_long, caddr_t));
+void hme_tick __P((void *));
void hme_watchdog __P((struct ifnet *));
void hme_shutdown __P((void *));
void hme_init __P((struct hme_softc *));
@@ -133,6 +133,7 @@
{
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
struct mii_data *mii = &sc->sc_mii;
+ struct mii_softc *child;
bus_dma_segment_t seg;
bus_size_t size;
int rseg, error;
@@ -248,12 +249,38 @@
mii_phy_probe(&sc->sc_dev, mii, 0xffffffff,
MII_PHY_ANY, MII_OFFSET_ANY);
- if (LIST_FIRST(&mii->mii_phys) == NULL) {
+ child = LIST_FIRST(&mii->mii_phys);
+ if (child == NULL) {
/* No PHY attached */
ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
} else {
/*
+ * Walk along the list of attached MII devices and
+ * establish an `MII instance' to `phy number'
+ * mapping. We'll use this mapping in media change
+ * requests to determine which phy to use to program
+ * the MIF configuration register.
+ */
+ for (; child != NULL; child = LIST_NEXT(child, mii_list)) {
+ /*
+ * Note: we support just two PHYs: the built-in
+ * internal device and an external on the MII
+ * connector.
+ */
+ if (child->mii_phy > 1 || child->mii_inst > 1) {
+ printf("%s: cannot accomodate MII device %s"
+ " at phy %d, instance %d\n",
+ sc->sc_dev.dv_xname,
+ child->mii_dev.dv_xname,
+ child->mii_phy, child->mii_inst);
+ continue;
+ }
+
+ sc->sc_phys[child->mii_inst] = child->mii_phy;
+ }
+
+ /*
* XXX - we can really do the following ONLY if the
* phy indeed has the auto negotiation capability!!
*/
@@ -285,6 +312,23 @@
rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
RND_TYPE_NET, 0);
#endif
+
+ /* Start the one second clock */
+ timeout(hme_tick, sc, hz);
+}
+
+void
+hme_tick(arg)
+ void *arg;
+{
+ struct hme_softc *sc = arg;
+ int s;
+
+ s = splnet();
+ mii_tick(&sc->sc_mii);
+ splx(s);
+
+ timeout(hme_tick, sc, hz);
}
void
@@ -306,6 +350,9 @@
bus_space_handle_t seb = sc->sc_seb;
int n;
+ untimeout(hme_tick, sc);
+ mii_down(&sc->sc_mii);
+
/* Reset transmitter and receiver */
bus_space_write_4(t, seb, HME_SEBI_RESET,
(HME_SEB_RESET_ETX | HME_SEB_RESET_ERX));
@@ -985,6 +1032,15 @@
int n;
u_int32_t v;
+ /* Select the desired PHY in the MIF configuration register */
+ v = bus_space_read_4(t, mif, HME_MIFI_CFG);
+ /* Clear PHY select bit */
+ 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);
+
/* Construct the frame command */
v = (MII_COMMAND_START << HME_MIF_FO_ST_SHIFT) |
HME_MIF_FO_TAMSB |
@@ -1015,6 +1071,15 @@
int n;
u_int32_t v;
+ /* Select the desired PHY in the MIF configuration register */
+ v = bus_space_read_4(t, mif, HME_MIFI_CFG);
+ /* Clear PHY select bit */
+ 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);
+
/* Construct the frame command */
v = (MII_COMMAND_START << HME_MIF_FO_ST_SHIFT) |
HME_MIF_FO_TAMSB |
@@ -1038,11 +1103,40 @@
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
- struct hme_softc *sc = (void *)dev;
if (sc->sc_debug)
- printf("hme_mii_statchg: status change\n");
+ printf("hme_mii_statchg: status change: phy = %d\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 */
+ 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;
+ else
+ v &= ~HME_MAC_TXCFG_FULLDPLX;
+ 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
@@ -1050,30 +1144,11 @@
struct ifnet *ifp;
{
struct hme_softc *sc = ifp->if_softc;
- struct ifmedia *ifm = &sc->sc_media;
- int newmedia = ifm->ifm_media;
- bus_space_tag_t t = sc->sc_bustag;
- bus_space_handle_t mac = sc->sc_mac;
- u_int32_t v;
- int error;
- if (IFM_TYPE(newmedia) != IFM_ETHER)
+ if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_ETHER)
return (EINVAL);
- if ((ifp->if_flags & IFF_UP) == 0)
- return (0);
-
- if ((error = mii_mediachg(&sc->sc_mii)) != 0)
- return (error);
-
- 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;
- else
- v &= ~HME_MAC_TXCFG_FULLDPLX;
- bus_space_write_4(t, mac, HME_MACI_TXCFG, v);
-
- return (0);
+ return (mii_mediachg(&sc->sc_mii));
}
void
diff -r 6213c7a7492e -r ae7b7789cbb2 sys/dev/ic/hmevar.h
--- a/sys/dev/ic/hmevar.h Sat Dec 18 08:01:25 1999 +0000
+++ b/sys/dev/ic/hmevar.h Sat Dec 18 14:05:37 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hmevar.h,v 1.1 1999/06/27 12:26:33 pk Exp $ */
+/* $NetBSD: hmevar.h,v 1.2 1999/12/18 14:05:37 pk Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -77,6 +77,7 @@
bus_space_handle_t sc_mac; /* HME MAC registers */
bus_space_handle_t sc_mif; /* HME MIF registers */
int sc_burst; /* DVMA burst size in effect */
+ int sc_phys[2]; /* MII instance -> PHY map */
/* Ring descriptor */
struct hme_ring sc_rb;
Home |
Main Index |
Thread Index |
Old Index