Subject: fix for mc*
To: None <port-macppc@netbsd.org>
From: Tim Kelly <hockey@dialectronics.com>
List: port-macppc
Date: 12/05/2004 17:35:38
Attached is a patch that will fix the problem with mc*. I could reproduce
it here and now I'm getting over 1Mb/sec with it. It was fairly simple,
actually. The routines for media status and change had a bad API and did
not match the ifnet* stuff. I'm not sure if the am79c950.c routines were
getting picked up or the caller was just bailing. In any event, I recall
that there was a problem on early PCI Macs that the AAUI connector had
priority over the 10BaseT connection, so if either IFM_MANUAL was used or
the media change routine wasn't properly linked, the chip probably
defaulted to AAUI. I made the API match on the two routines and made the
default be 10BaseT. I left the old stuff in and put the new stuff inside
#ifdef IFM, so you can test before and after. I see no difference now
between my sip* card and the mc* card, and from my G4 in MacOS9 and the mc
connection I downloaded (to G4) a 7M file in about six seconds. Previously
I got the same timeout errors before authentication could even occur with
ssh, but now it's quite useable.

tim


Index: if_mc.c
===================================================================
RCS file: /cvsroot/src/sys/arch/macppc/dev/if_mc.c,v
retrieving revision 1.9
diff -d -u -r1.9 if_mc.c
--- if_mc.c	15 Jul 2003 02:43:29 -0000	1.9
+++ if_mc.c	5 Dec 2004 22:19:36 -0000
@@ -61,6 +61,8 @@

 #define MC_BUFSIZE 0x800

+#define IFM
+
 hide int	mc_match __P((struct device *, struct cfdata *, void *));
 hide void	mc_attach __P((struct device *, struct device *, void *));
 hide void	mc_init __P((struct mc_softc *sc));
@@ -70,8 +72,21 @@
 hide void	mc_reset_txdma __P((struct mc_softc *sc));
 hide void	mc_select_utp __P((struct mc_softc *sc));
 hide void	mc_select_aui __P((struct mc_softc *sc));
+
+#ifdef IFM
+static int      mc_setup __P((struct mc_softc *, u_int8_t *));
+static int	      mc_mediachange __P((struct ifnet *));
+static void	mc_mediastatus __P((struct ifnet *, struct ifmediareq *));
+
+extern int      mcioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data));
+extern void     mcstart __P((struct ifnet *ifp));
+extern void     mcwatchdog __P((struct ifnet *));
+
+#else
 hide int	mc_mediachange __P((struct mc_softc *sc));
 hide void	mc_mediastatus __P((struct mc_softc *sc, struct ifmediareq *));
+#endif
+

 int mc_supmedia[] = {
 	IFM_ETHER | IFM_10_T,
@@ -174,9 +189,9 @@
 	dbdma_reset(sc->sc_txdma);

 	/* install interrupt handlers */
-	/*intr_establish(ca->ca_intr[1], IST_LEVEL, IPL_NET, mc_dmaintr, sc);*/
-	intr_establish(ca->ca_intr[2], IST_LEVEL, IPL_NET, mc_dmaintr, sc);
 	intr_establish(ca->ca_intr[0], IST_LEVEL, IPL_NET, mcintr, sc);
+	intr_establish(ca->ca_intr[1], IST_LEVEL, IPL_NET, mc_dmaintr, sc);
+	intr_establish(ca->ca_intr[2], IST_LEVEL, IPL_NET, mc_dmaintr, sc);

 	sc->sc_biucc = XMTSP_64;
 	sc->sc_fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU |
@@ -184,11 +199,21 @@
 	/*sc->sc_plscc = PORTSEL_10BT;*/
 	sc->sc_plscc = PORTSEL_GPSI | ENPLSIO;

+#ifdef IFM
+	/* mc_setup returns 1 if something fails */
+	if (mc_setup(sc, myaddr)) {
+		printf("mcsetup returns non zero\n");
+		return;
+	}
+
+#else
 	/* mcsetup returns 1 if something fails */
 	if (mcsetup(sc, myaddr)) {
 		printf("mcsetup returns non zero\n");
 		return;
 	}
+#endif
+
 #ifdef NOTYET
 	sc->sc_mediachange = mc_mediachange;
 	sc->sc_mediastatus = mc_mediastatus;
@@ -198,6 +223,48 @@
 #endif
 }

+#ifdef IFM
+/*
+ * Interface exists: make available by filling in network interface
+ * record.  System will initialize the interface when it is ready
+ * to accept packets.
+ */
+int
+mc_setup(sc, lladdr)
+        struct mc_softc *sc;
+        u_int8_t *lladdr;
+{
+        struct ifnet *ifp = &sc->sc_if;
+
+        /* reset the chip and disable all interrupts */
+        NIC_PUT(sc, MACE_BIUCC, SWRST);
+        DELAY(100);
+        NIC_PUT(sc, MACE_IMR, ~0);
+
+        bcopy(lladdr, sc->sc_enaddr, ETHER_ADDR_LEN);
+        printf(": address %s\n", ether_sprintf(lladdr));
+
+        bcopy(sc->sc_dev.dv_xname,ifp->if_xname, IFNAMSIZ);
+        ifp->if_softc = sc;
+        ifp->if_ioctl = mcioctl;
+        ifp->if_start = mcstart;
+        ifp->if_flags =
+            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
+        ifp->if_watchdog = mcwatchdog;
+
+        /* initialize ifmedia structures */
+        ifmedia_init(&sc->sc_media, 0, mc_mediachange, mc_mediastatus);
+        ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_T, 0, NULL);
+        ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_10_T);
+
+	if_attach(ifp);
+        ether_ifattach(ifp, lladdr);
+
+        return (0);
+}
+#endif
+
+
 /* Bus-specific initialization */
 hide void
 mc_init(sc)
@@ -206,6 +273,7 @@
 	mc_reset_rxdma(sc);
 	mc_reset_txdma(sc);
 }
+

 hide void
 mc_putpacket(sc, len)
@@ -371,17 +439,29 @@
 }

 int
+#ifdef IFM
+mc_mediachange(ifp)
+	struct ifnet *ifp;
+
+{
+	struct mc_softc *sc = ifp->if_softc;
+
+#else
 mc_mediachange(sc)
 	struct mc_softc *sc;
+
 {
-	struct ifmedia *ifm = &sc->sc_media;
+#endif

+	struct ifmedia *ifm = &sc->sc_media;
+	/* printf("mc_mediachange called\n"); */
 	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
 		return EINVAL;

 	switch (IFM_SUBTYPE(ifm->ifm_media)) {

 	case IFM_10_T:
+	case IFM_MANUAL:
 		mc_select_utp(sc);
 		break;

@@ -397,10 +477,21 @@
 }

 void
+#ifdef IFM
+mc_mediastatus(ifp, ifmr)
+	struct ifnet *ifp;
+	struct ifmediareq *ifmr;
+
+{
+	struct mc_softc *sc = ifp->if_softc;
+
+#else
 mc_mediastatus(sc, ifmr)
 	struct mc_softc *sc;
 	struct ifmediareq *ifmr;
 {
+#endif
+	/* printf("mc_mediastatus called\n"); */
 	if (sc->sc_plscc == PORTSEL_AUI)
 		ifmr->ifm_active = IFM_ETHER | IFM_10_5;
 	else
Index: if_mcvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/macppc/dev/if_mcvar.h,v
retrieving revision 1.7
diff -d -u -r1.7 if_mcvar.h
--- if_mcvar.h	9 Apr 2003 01:54:45 -0000	1.7
+++ if_mcvar.h	5 Dec 2004 22:19:49 -0000
@@ -80,6 +80,8 @@
 	void		(*sc_mediastatus) __P((struct mc_softc *,
 				struct ifmediareq *));

+	u_int		sc_defaultmedia;
+
 	bus_space_tag_t	sc_regt;
 	bus_space_handle_t sc_regh;