PERFORCE change 89190 for review
Warner Losh
imp at FreeBSD.org
Wed Jan 4 17:54:42 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=89190
Change 89190 by imp at imp_Speedy on 2006/01/05 01:54:31
Write a stop routine.
Start an init routine.
Write a tick routine.
Affected files ...
.. //depot/projects/arm/src/sys/arm/at91/if_ate.c#5 edit
Differences ...
==== //depot/projects/arm/src/sys/arm/at91/if_ate.c#5 (text+ko) ====
@@ -57,21 +57,25 @@
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
+#include <arm/at91/if_atereg.h>
#include "miibus_if.h"
struct ate_softc
{
- struct ifnet *ifp;
- struct mtx sc_mtx;
- device_t dev;
- device_t miibus;
- void *intrhand;
- struct resource *irq_res;
- struct resource *mem_res;
+ struct ifnet *ifp; /* ifnet pointer */
+ struct mtx sc_mtx; /* basically a perimeter lock */
+ device_t dev; /* Myself */
+ device_t miibus; /* My child miibus */
+ void *intrhand; /* Interrupt handle */
+ struct resource *irq_res; /* IRQ resource */
+ struct resource *mem_res; /* Memory resource */
+ struct callout tick_ch; /* Tick callout */
// XXX bogus
int intr;
+
+ struct ifmib_iso_8802_3 mibdata; /* stuff for network mgmt */
};
static inline uint32_t
@@ -148,6 +152,8 @@
/* calling atestop before ifp is set is OK */
atestop(sc);
ATE_LOCK_INIT(sc);
+ callout_init_mtx(&sc->tick_ch, &sc->sc_mtx, 0);
+
sc->ifp = ifp = if_alloc(IFT_ETHER);
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
@@ -162,6 +168,9 @@
ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
IFQ_SET_READY(&ifp->if_snd);
ifp->if_timer = 0;
+ ifp->if_linkmib = &sc->mibdata;
+ ifp->if_linkmiblen = sizeof(sc->mibdata);
+ sc->mibdata.dot3Compliance = DOT3COMPLIANCE_COLLS;
ether_ifattach(ifp, eaddr);
@@ -219,6 +228,9 @@
if (sc->intrhand)
bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
sc->intrhand = 0;
+ bus_generic_detach(sc->dev);
+ if (sc->miibus)
+ device_delete_child(sc->dev, sc->miibus);
if (sc->mem_res)
bus_release_resource(dev, SYS_RES_IOPORT,
rman_get_rid(sc->mem_res), sc->mem_res);
@@ -231,6 +243,42 @@
}
static void
+ate_tick(void *xsc)
+{
+ struct ate_softc *sc = xsc;
+ struct mii_data *mii;
+ int active;
+
+ ATE_ASSERT_LOCKED(sc);
+ if (sc->miibus != NULL) {
+ mii = device_get_softc(sc->miibus);
+ active = mii->mii_media_active;
+ mii_tick(mii);
+ if (mii->mii_media_status & IFM_ACTIVE &&
+ active != mii->mii_media_active) {
+ /*
+ * The speed and full/half-duplex state needs
+ * to be reflected in the ETH_CFG register, it
+ * seems.
+ */
+ if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T)
+ WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) &
+ ~ETH_CFG_SPD);
+ else
+ WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) |
+ ETH_CFG_SPD);
+ if (mii->mii_media_active & IFM_FDX)
+ WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) |
+ ETH_CFG_FD);
+ else
+ WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) &
+ ~ETH_CFG_FD);
+ }
+ }
+}
+
+
+static void
ate_intr(void *xsc)
{
struct ate_softc *sc = xsc;
@@ -245,13 +293,45 @@
ateinit_locked(void *xsc)
{
struct ate_softc *sc = xsc;
-// struct ifnet *ifp = sc->ifp;
+ struct ifnet *ifp = sc->ifp;
ATE_ASSERT_LOCKED(sc);
-// XXX don't forget RMII vs MII
- /* Insert code here */
- sc->intr++;
+ /*
+ * XXX we need to turn on the EMAC clock in the pmc. With the
+ * default boot loader, this is already turned on. However, we
+ * need to think about how best to turn it on/off as the interface
+ * is brought up/down, as well as dealing with the mii bus...
+ *
+ * We also need to multiplex the pins correctly.
+ */
+
+ /*
+ * There are two different ways that the mii bus is connected
+ * to this chip. Select the right one based on a compile-time
+ * option.
+ */
+#ifdef ATE_USE_RMII
+ WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_RMII);
+#else
+ WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_RMII);
+#endif
+
+ /* XXX need to setup multicast filters */
+ /* XXX need to setup rx buffers and assoc structures */
+ /* XXX need to enable appropriate interrupt masks */
+ /* XXX need to program station address, or is that
+ * XXX added by upper layers? */
+
+ /*
+ * Set 'running' flag, and clear output active flag
+ * and attempt to start the output
+ */
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ atestart_locked(ifp);
+
+ callout_reset(&sc->tick_ch, hz, ate_tick, sc);
}
/*
@@ -293,6 +373,39 @@
static void
atestop(struct ate_softc *sc)
{
+ callout_stop(&sc->tick_ch);
+
+ /*
+ * Enable some parts of the MAC that are needed always (like the
+ * MII bus. This turns off the RE and TE bits, which will remain
+ * off until atestart() is called to turn them on.
+ */
+ WR4(sc, ETH_CTL, ETH_CTL_MPE);
+
+ /*
+ * Turn off all the configured options and revert to defaults.
+ */
+ WR4(sc, ETH_CFG, ETH_CFG_CLK_32);
+
+ /*
+ * Turn off all the interrupts, and ack any pending ones by reading
+ * the ISR.
+ */
+ WR4(sc, ETH_IDR, 0xffffffff);
+ RD4(sc, ETH_ISR);
+
+ /*
+ * Clear out the Transmit and Receiver Status registers of any
+ * errors they may be reporting
+ */
+ WR4(sc, ETH_TSR, 0xffffffff);
+ WR4(sc, ETH_RSR, 0xffffffff);
+
+ /*
+ * XXX we should power down the EMAC if it isn't in use, after
+ * putting it into loopback mode. This saves about 400uA according
+ * to the datasheet.
+ */
}
static void
More information about the p4-projects
mailing list