Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Jan 2006 01:54:38 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 89190 for review
Message-ID:  <200601050154.k051scKP052959@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=89190

Change 89190 by imp@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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200601050154.k051scKP052959>