[Midnightbsd-cvs] src: if_hme.c: merge
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Wed Nov 26 14:00:33 EST 2008
Log Message:
-----------
merge
Modified Files:
--------------
src/sys/dev/hme:
if_hme.c (r1.2 -> r1.3)
-------------- next part --------------
Index: if_hme.c
===================================================================
RCS file: /home/cvs/src/sys/dev/hme/if_hme.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/hme/if_hme.c -L sys/dev/hme/if_hme.c -u -r1.2 -r1.3
--- sys/dev/hme/if_hme.c
+++ sys/dev/hme/if_hme.c
@@ -34,11 +34,11 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
- * from: NetBSD: hme.c,v 1.29 2002/05/05 03:02:38 thorpej Exp
+ * from: NetBSD: hme.c,v 1.35 2003/02/27 14:58:22 pk Exp
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/hme/if_hme.c,v 1.37.2.7 2006/03/24 00:38:07 yongari Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/hme/if_hme.c,v 1.53 2007/05/01 11:50:11 marius Exp $");
/*
* HME Ethernet module driver.
@@ -104,7 +104,7 @@
static void hme_stop(struct hme_softc *);
static int hme_ioctl(struct ifnet *, u_long, caddr_t);
static void hme_tick(void *);
-static void hme_watchdog(struct ifnet *);
+static int hme_watchdog(struct hme_softc *);
static void hme_init(void *);
static void hme_init_locked(struct hme_softc *);
static int hme_add_rxbuf(struct hme_softc *, unsigned int, int);
@@ -115,6 +115,7 @@
static void hme_setladrf(struct hme_softc *, int);
static int hme_mediachange(struct ifnet *);
+static int hme_mediachange_locked(struct hme_softc *);
static void hme_mediastatus(struct ifnet *, struct ifmediareq *);
static int hme_load_txmbuf(struct hme_softc *, struct mbuf **);
@@ -157,8 +158,8 @@
if (hme_nerr++ < HME_MAXERR) \
device_printf(dev, __VA_ARGS__); \
if (hme_nerr == HME_MAXERR) { \
- device_printf(dev, "too may errors; not reporting any " \
- "more\n"); \
+ device_printf(dev, "too many errors; not reporting " \
+ "any more\n"); \
} \
} while(0)
@@ -213,15 +214,16 @@
*/
size = 4096;
- error = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT,
- BUS_SPACE_MAXADDR, NULL, NULL, size, HME_NTXDESC + HME_NRXDESC + 1,
- BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, &sc->sc_pdmatag);
+ error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size,
+ HME_NTXDESC + HME_NRXDESC + 1, BUS_SPACE_MAXSIZE_32BIT, 0,
+ NULL, NULL, &sc->sc_pdmatag);
if (error)
goto fail_ifnet;
error = bus_dma_tag_create(sc->sc_pdmatag, 2048, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size,
- 1, BUS_SPACE_MAXSIZE_32BIT, BUS_DMA_ALLOCNOW, busdma_lock_mutex,
+ 1, BUS_SPACE_MAXSIZE_32BIT, 0, busdma_lock_mutex,
&sc->sc_lock, &sc->sc_cdmatag);
if (error)
goto fail_ptag;
@@ -289,12 +291,10 @@
ifp->if_softc = sc;
if_initname(ifp, device_get_name(sc->sc_dev),
device_get_unit(sc->sc_dev));
- ifp->if_mtu = ETHERMTU;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_start = hme_start;
ifp->if_ioctl = hme_ioctl;
ifp->if_init = hme_init;
- ifp->if_watchdog = hme_watchdog;
IFQ_SET_MAXLEN(&ifp->if_snd, HME_NTXQ);
ifp->if_snd.ifq_drv_maxlen = HME_NTXQ;
IFQ_SET_READY(&ifp->if_snd);
@@ -310,19 +310,21 @@
/*
* 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.
+ * establish an `MII instance' to `PHY number'
+ * mapping. We'll use this mapping to enable the MII
+ * drivers of the external transceiver according to
+ * the currently selected media.
*/
- for (child = LIST_FIRST(&sc->sc_mii->mii_phys); child != NULL;
- child = LIST_NEXT(child, mii_list)) {
+ sc->sc_phys[0] = sc->sc_phys[1] = -1;
+ LIST_FOREACH(child, &sc->sc_mii->mii_phys, 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) {
+ if ((child->mii_phy != HME_PHYAD_EXTERNAL &&
+ child->mii_phy != HME_PHYAD_INTERNAL) ||
+ child->mii_inst > 1) {
device_printf(sc->sc_dev, "cannot accommodate "
"MII device %s at phy %d, instance %d\n",
device_get_name(child->mii_dev),
@@ -464,6 +466,9 @@
mii_tick(sc->sc_mii);
+ if (hme_watchdog(sc) == EJUSTRETURN)
+ return;
+
callout_reset(&sc->sc_tick_ch, hz, hme_tick, sc);
}
@@ -474,8 +479,12 @@
int n;
callout_stop(&sc->sc_tick_ch);
+ sc->sc_wdog_timer = 0;
sc->sc_ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ /* Mask all interrupts */
+ HME_SEB_WRITE_4(sc, HME_SEBI_IMASK, 0xffffffff);
+
/* Reset transmitter and receiver */
HME_SEB_WRITE_4(sc, HME_SEBI_RESET, HME_SEB_RESET_ETX |
HME_SEB_RESET_ERX);
@@ -729,7 +738,7 @@
HME_MAC_WRITE_4(sc, HME_MACI_TXSIZE, HME_MAX_FRAMESIZE);
/* Load station MAC address */
- ea = IFP2ENADDR(sc->sc_ifp);
+ ea = IF_LLADDR(sc->sc_ifp);
HME_MAC_WRITE_4(sc, HME_MACI_MACADDR0, (ea[0] << 8) | ea[1]);
HME_MAC_WRITE_4(sc, HME_MACI_MACADDR1, (ea[2] << 8) | ea[3]);
HME_MAC_WRITE_4(sc, HME_MACI_MACADDR2, (ea[4] << 8) | ea[5]);
@@ -741,7 +750,6 @@
v = ((ea[4] << 8) | ea[5]) & 0x3fff;
HME_MAC_WRITE_4(sc, HME_MACI_RANDSEED, v);
-
/* Note: Accepting power-on default for other MAC registers here.. */
/* step 5. RX MAC registers & counters */
@@ -833,9 +841,6 @@
/* step 11. XIF Configuration */
v = HME_MAC_READ_4(sc, HME_MACI_XIF);
v |= HME_MAC_XIF_OE;
- /* If an external transceiver is connected, enable its MII drivers */
- if ((HME_MIF_READ_4(sc, HME_MIFI_CFG) & HME_MIF_CFG_MDI1) != 0)
- v |= HME_MAC_XIF_MIIENABLE;
CTR1(KTR_HME, "hme_init: programming XIF to %x", (u_int)v);
HME_MAC_WRITE_4(sc, HME_MACI_XIF, v);
@@ -871,16 +876,14 @@
#endif
/* Set the current media. */
- /*
- * mii_mediachg(sc->sc_mii);
- */
+ hme_mediachange_locked(sc);
/* Start the one second timer. */
+ sc->sc_wdog_timer = 0;
callout_reset(&sc->sc_tick_ch, hz, hme_tick, sc);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_timer = 0;
hme_start_locked(ifp);
}
@@ -936,7 +939,6 @@
hme_load_txmbuf(struct hme_softc *sc, struct mbuf **m0)
{
struct hme_txdesc *htx;
- struct mbuf *m, *n;
caddr_t txd;
int i, pci, si, ri, nseg;
u_int32_t flags, cflags = 0;
@@ -944,31 +946,30 @@
if ((htx = STAILQ_FIRST(&sc->sc_rb.rb_txfreeq)) == NULL)
return (-1);
- m = *m0;
- if ((m->m_pkthdr.csum_flags & sc->sc_csum_features) != 0)
- hme_txcksum(m, &cflags);
error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, htx->htx_dmamap,
- m, sc->sc_rb.rb_txsegs, &nseg, 0);
+ *m0, sc->sc_rb.rb_txsegs, &nseg, 0);
if (error == EFBIG) {
- n = m_defrag(m, M_DONTWAIT);
- if (n == NULL) {
- m_freem(m);
- m = NULL;
+ struct mbuf *m;
+
+ m = m_defrag(*m0, M_DONTWAIT);
+ if (m == NULL) {
+ m_freem(*m0);
+ *m0 = NULL;
return (ENOMEM);
}
- m = n;
+ *m0 = m;
error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, htx->htx_dmamap,
- m, sc->sc_rb.rb_txsegs, &nseg, 0);
+ *m0, sc->sc_rb.rb_txsegs, &nseg, 0);
if (error != 0) {
- m_freem(m);
- m = NULL;
+ m_freem(*m0);
+ *m0 = NULL;
return (error);
}
} else if (error != 0)
return (error);
if (nseg == 0) {
- m_freem(m);
- m = NULL;
+ m_freem(*m0);
+ *m0 = NULL;
return (EIO);
}
if (sc->sc_rb.rb_td_nbusy + nseg >= HME_NTXDESC) {
@@ -976,6 +977,8 @@
/* retry with m_defrag(9)? */
return (-2);
}
+ if (((*m0)->m_pkthdr.csum_flags & sc->sc_csum_features) != 0)
+ hme_txcksum(*m0, &cflags);
bus_dmamap_sync(sc->sc_tdmatag, htx->htx_dmamap, BUS_DMASYNC_PREWRITE);
si = ri = sc->sc_rb.rb_tdhead;
@@ -1017,7 +1020,7 @@
STAILQ_REMOVE_HEAD(&sc->sc_rb.rb_txfreeq, htx_q);
STAILQ_INSERT_TAIL(&sc->sc_rb.rb_txbusyq, htx, htx_q);
- htx->htx_m = m;
+ htx->htx_m = *m0;
/* start the transmission. */
HME_ETX_WRITE_4(sc, HME_ETXI_PENDING, HME_ETX_TP_DMAWAKEUP);
@@ -1112,11 +1115,10 @@
BPF_MTAP(ifp, m);
}
- /* Set watchdog timer if a packet was queued */
if (enq > 0) {
bus_dmamap_sync(sc->sc_cdmatag, sc->sc_cdmamap,
BUS_DMASYNC_PREWRITE);
- ifp->if_timer = 5;
+ sc->sc_wdog_timer = 5;
}
}
@@ -1169,8 +1171,7 @@
STAILQ_INSERT_TAIL(&sc->sc_rb.rb_txfreeq, htx, htx_q);
htx = STAILQ_FIRST(&sc->sc_rb.rb_txbusyq);
}
- /* Turn off watchdog if hme(4) transmitted queued packet */
- ifp->if_timer = sc->sc_rb.rb_td_nbusy > 0 ? 5 : 0;
+ sc->sc_wdog_timer = sc->sc_rb.rb_td_nbusy > 0 ? 5 : 0;
/* Update ring */
sc->sc_rb.rb_tdtail = ri;
@@ -1290,7 +1291,11 @@
{
if ((status & HME_SEB_STAT_MIFIRQ) != 0) {
- device_printf(sc->sc_dev, "XXXlink status changed\n");
+ device_printf(sc->sc_dev, "XXXlink status changed: "
+ "cfg=%#x, stat=%#x, sm=%#x\n",
+ HME_MIF_READ_4(sc, HME_MIFI_CFG),
+ HME_MIF_READ_4(sc, HME_MIFI_STAT),
+ HME_MIF_READ_4(sc, HME_MIFI_SM));
return;
}
@@ -1322,25 +1327,27 @@
HME_UNLOCK(sc);
}
-
-static void
-hme_watchdog(struct ifnet *ifp)
+static int
+hme_watchdog(struct hme_softc *sc)
{
- struct hme_softc *sc = ifp->if_softc;
#ifdef HMEDEBUG
u_int32_t status;
#endif
- HME_LOCK(sc);
+ HME_LOCK_ASSERT(sc, MA_OWNED);
#ifdef HMEDEBUG
status = HME_SEB_READ_4(sc, HME_SEBI_STAT);
CTR1(KTR_HME, "hme_watchdog: status %x", (u_int)status);
#endif
+
+ if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0)
+ return (0);
+
device_printf(sc->sc_dev, "device timeout\n");
- ++ifp->if_oerrors;
+ ++sc->sc_ifp->if_oerrors;
hme_init_locked(sc);
- HME_UNLOCK(sc);
+ return (EJUSTRETURN);
}
/*
@@ -1351,10 +1358,26 @@
{
u_int32_t v;
- /* Configure the MIF in frame mode */
- v = HME_MIF_READ_4(sc, HME_MIFI_CFG);
- v &= ~HME_MIF_CFG_BBMODE;
- HME_MIF_WRITE_4(sc, HME_MIFI_CFG, v);
+ /*
+ * Configure the MIF in frame mode, polling disabled, internal PHY
+ * selected.
+ */
+ HME_MIF_WRITE_4(sc, HME_MIFI_CFG, 0);
+
+ /*
+ * If the currently selected media uses the external transceiver,
+ * enable its MII drivers (which basically isolates the internal
+ * one and vice versa). In case the current media hasn't been set,
+ * yet, we default to the internal transceiver.
+ */
+ v = HME_MAC_READ_4(sc, HME_MACI_XIF);
+ if (sc->sc_mii != NULL && sc->sc_mii->mii_media.ifm_cur != NULL &&
+ sc->sc_phys[IFM_INST(sc->sc_mii->mii_media.ifm_cur->ifm_media)] ==
+ HME_PHYAD_EXTERNAL)
+ v |= HME_MAC_XIF_MIIENABLE;
+ else
+ v &= ~HME_MAC_XIF_MIIENABLE;
+ HME_MAC_WRITE_4(sc, HME_MACI_XIF, v);
}
/*
@@ -1363,17 +1386,21 @@
int
hme_mii_readreg(device_t dev, int phy, int reg)
{
- struct hme_softc *sc = device_get_softc(dev);
+ struct hme_softc *sc;
int n;
u_int32_t v;
+ /* We can at most have two PHYs. */
+ if (phy != HME_PHYAD_EXTERNAL && phy != HME_PHYAD_INTERNAL)
+ return (0);
+
+ sc = device_get_softc(dev);
/* Select the desired PHY in the MIF configuration register */
v = HME_MIF_READ_4(sc, 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;
+ else
+ v &= ~HME_MIF_CFG_PHY;
HME_MIF_WRITE_4(sc, HME_MIFI_CFG, v);
/* Construct the frame command */
@@ -1387,9 +1414,8 @@
for (n = 0; n < 100; n++) {
DELAY(1);
v = HME_MIF_READ_4(sc, HME_MIFI_FO);
- if (v & HME_MIF_FO_TALSB) {
+ if (v & HME_MIF_FO_TALSB)
return (v & HME_MIF_FO_DATA);
- }
}
device_printf(sc->sc_dev, "mii_read timeout\n");
@@ -1399,17 +1425,21 @@
int
hme_mii_writereg(device_t dev, int phy, int reg, int val)
{
- struct hme_softc *sc = device_get_softc(dev);
+ struct hme_softc *sc;
int n;
u_int32_t v;
+ /* We can at most have two PHYs. */
+ if (phy != HME_PHYAD_EXTERNAL && phy != HME_PHYAD_INTERNAL)
+ return (0);
+
+ sc = device_get_softc(dev);
/* Select the desired PHY in the MIF configuration register */
v = HME_MIF_READ_4(sc, 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;
+ else
+ v &= ~HME_MIF_CFG_PHY;
HME_MIF_WRITE_4(sc, HME_MIFI_CFG, v);
/* Construct the frame command */
@@ -1435,25 +1465,16 @@
void
hme_mii_statchg(device_t dev)
{
- struct hme_softc *sc = device_get_softc(dev);
- int instance;
- int phy;
+ struct hme_softc *sc;
u_int32_t v;
- instance = IFM_INST(sc->sc_mii->mii_media.ifm_cur->ifm_media);
- phy = sc->sc_phys[instance];
+ sc = device_get_softc(dev);
+
#ifdef HMEDEBUG
if (sc->sc_debug)
- printf("hme_mii_statchg: status change: phy = %d\n", phy);
+ device_printf(sc->sc_dev, "hme_mii_statchg: status change\n");
#endif
- /* Select the current PHY in the MIF configuration register */
- v = HME_MIF_READ_4(sc, HME_MIFI_CFG);
- v &= ~HME_MIF_CFG_PHY;
- if (phy == HME_PHYAD_EXTERNAL)
- v |= HME_MIF_CFG_PHY;
- HME_MIF_WRITE_4(sc, HME_MIFI_CFG, v);
-
/* Set the MAC Full Duplex bit appropriately */
v = HME_MAC_READ_4(sc, HME_MACI_TXCFG);
if (!hme_mac_bitflip(sc, HME_MACI_TXCFG, v, HME_MAC_TXCFG_ENABLE, 0))
@@ -1474,11 +1495,39 @@
int error;
HME_LOCK(sc);
- error = mii_mediachg(sc->sc_mii);
+ error = hme_mediachange_locked(sc);
HME_UNLOCK(sc);
return (error);
}
+static int
+hme_mediachange_locked(struct hme_softc *sc)
+{
+ struct mii_softc *child;
+
+ HME_LOCK_ASSERT(sc, MA_OWNED);
+#ifdef HMEDEBUG
+ if (sc->sc_debug)
+ device_printf(sc->sc_dev, "hme_mediachange_locked");
+#endif
+
+ hme_mifinit(sc);
+
+ /*
+ * If both PHYs are present reset them. This is required for
+ * unisolating the previously isolated PHY when switching PHYs.
+ * As the above hme_mifinit() call will set the MII drivers in
+ * the XIF configuration register accoring to the currently
+ * selected media, there should be no window during which the
+ * data paths of both transceivers are open at the same time,
+ * even if the PHY device drivers use MIIF_NOISOLATE.
+ */
+ if (sc->sc_phys[0] != -1 && sc->sc_phys[1] != -1)
+ LIST_FOREACH(child, &sc->sc_mii->mii_phys, mii_list)
+ mii_phy_reset(child);
+ return (mii_mediachg(sc->sc_mii));
+}
+
static void
hme_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
{
More information about the Midnightbsd-cvs
mailing list