Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 08 Jul 2009 15:49:08 -0700
From:      Sean Bruno <sean.bruno@dsl-only.net>
To:        Julian Stecklina <js@alien8.de>
Cc:        freebsd-firewire@freebsd.org
Subject:   Re: 8-CURRENT Firewire
Message-ID:  <1247093348.2552.4.camel@Lappy>
In-Reply-To: <87bpnwszf9.fsf@tabernacle.lan>
References:  <1246316092.3981.11.camel@Lappy> <87hbxxp5ot.fsf@tabernacle.lan> <1246483794.3443.6.camel@Lappy> <87fxdguj4a.fsf@tabernacle.lan> <878wj2r3t1.fsf@tabernacle.lan> <1246894876.2966.8.camel@Lappy> <87k52kt505.fsf@tabernacle.lan>  <87bpnwszf9.fsf@tabernacle.lan>

next in thread | previous in thread | raw e-mail | index | archive | help

--=-Z1PMy3ujl2uNspxmxomY
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

> >> Hrm ... I think that fwohci() or firewire() is getting stuck.
> >>
> >> Can you turn up debug and re-run your boot up sequence just like the
> >> above dmesg?
> >>
> >> firewire_debug=3
> >> sbp_debug=3
> >
> > I think I am too stupid to set these variables. I tried
> > debug.firewire_debug=3 in loader.conf, but it doesn't work. After
> > loading the modules they are always set to zero. Setting via sysctl
> > doesn't work either, since they don't exist before loading
> > firewire/sbp. So how do I set these?
> 
> Okay, I hardcoded them in the source... 
> 
> http://os.inf.tu-dresden.de/~jsteckli/fbsd/fw-log.txt
> 
> Regards,

For fun, please try to apply this diff and retest.

Sean

--=-Z1PMy3ujl2uNspxmxomY
Content-Disposition: attachment; filename="fwohci.c.diff"
Content-Type: text/x-patch; name="fwohci.c.diff"; charset="UTF-8"
Content-Transfer-Encoding: 7bit

Index: fwohci.c
===================================================================
--- fwohci.c	(revision 195344)
+++ fwohci.c	(working copy)
@@ -280,7 +280,8 @@
 
 	fun = (PHYDEV_WRCMD | (addr << PHYDEV_REGADDR) | (data << PHYDEV_WRDATA));
 	OWRITE(sc, OHCI_PHYACCESS, fun);
-	DELAY(100);
+	bus_space_barrier(sc->bst, sc->bsh, OHCI_PHYACCESS,
+				4, BUS_SPACE_BARRIER_WRITE);
 
 	return(fwphy_rddata( sc, addr));
 }
@@ -316,43 +317,65 @@
 fwphy_rddata(struct fwohci_softc *sc,  u_int addr)
 {
 	uint32_t fun, stat;
-	u_int i, retry = 0;
+	int retry = 0;
 
 	addr &= 0xf;
-#define MAX_RETRY 100
-again:
+
+
+	/*
+ 	 * Read requested data from OHCI PHY
+ 	 * If we generate an INT_REG_FAIL error
+ 	 * from our request, most likely SCLK has
+ 	 * not been started yet.  pause() and retry.
+ 	 * Mechanics of RDCMD and RDDONE are in 
+ 	 * ohci 1.1 Table 5-19
+ 	 */
+
+	/* Clear error register */
+	stat = OREAD(sc, FWOHCI_INTSTAT);
+	stat &= ~OHCI_INT_REG_FAIL;
 	OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL);
+
+	/* Issue requested command to PHY */
 	fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR);
 	OWRITE(sc, OHCI_PHYACCESS, fun);
-	for ( i = 0 ; i < MAX_RETRY ; i ++ ){
-		fun = OREAD(sc, OHCI_PHYACCESS);
-		if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0)
-			break;
-		DELAY(100);
-	}
-	if(i >= MAX_RETRY) {
-		if (firewire_debug)
-			device_printf(sc->fc.dev, "%s: failed(1).\n", __func__);
-		if (++retry < MAX_RETRY) {
-			DELAY(100);
-			goto again;
-		}
-	}
-	/* Make sure that SCLK is started */
-	stat = OREAD(sc, FWOHCI_INTSTAT);
-	if ((stat & OHCI_INT_REG_FAIL) != 0 ||
+	bus_space_barrier(sc->bst, sc->bsh, OHCI_PHYACCESS,
+				4, BUS_SPACE_BARRIER_WRITE);
+#define MAX_RETRY 5
+	for ( retry = 0 ; retry < MAX_RETRY ; retry++ ){
+		/* Check for error, sleep if error reg set */
+		stat = OREAD(sc, FWOHCI_INTSTAT);
+		if ((stat & OHCI_INT_REG_FAIL) != 0 ||
 			((fun >> PHYDEV_REGADDR) & 0xf) != addr) {
-		if (firewire_debug)
-			device_printf(sc->fc.dev, "%s: failed(2).\n", __func__);
-		if (++retry < MAX_RETRY) {
-			DELAY(100);
-			goto again;
+			if (firewire_debug)
+				device_printf(sc->fc.dev, "%s: "
+					"OHCI_INT_REG_FAIL.\n", __func__);
+			/* Clear error register */
+			stat = OREAD(sc, FWOHCI_INTSTAT);
+			stat &= ~OHCI_INT_REG_FAIL;
+			OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_REG_FAIL);
+			pause("fwphyr", (50 * hz + 999) / 1000);
+			/* Issue requested command to PHY */
+			fun = PHYDEV_RDCMD | (addr << PHYDEV_REGADDR);
+			OWRITE(sc, OHCI_PHYACCESS, fun);
+			bus_space_barrier(sc->bst, sc->bsh, OHCI_PHYACCESS,
+					4, BUS_SPACE_BARRIER_WRITE);
+		} else { /* no error, check for command completion */
+			fun = OREAD(sc, OHCI_PHYACCESS);
+			bus_space_barrier(sc->bst, sc->bsh, OHCI_PHYACCESS,
+						4, BUS_SPACE_BARRIER_READ);
+			if ((fun & PHYDEV_RDCMD) == 0 && (fun & PHYDEV_RDDONE) != 0) {
+				retry = MAX_RETRY; /* exit loop. command complete */
+			} else { /* pause for 100 usec to allow command completion */
+				pause("fwphyr", hz/10);
+			}
 		}
+			
 	}
-	if (firewire_debug > 1 || retry >= MAX_RETRY)
+	if (firewire_debug > 1 || retry > MAX_RETRY)
 		device_printf(sc->fc.dev, 
-		    "%s:: 0x%x loop=%d, retry=%d\n",
-			__func__, addr, i, retry);
+		    "%s:: 0x%x, retry=%d\n",
+			__func__, addr, retry);
 #undef MAX_RETRY
 	return((fun >> PHYDEV_RDDATA )& 0xff);
 }
@@ -426,20 +449,45 @@
 static int
 fwohci_probe_phy(struct fwohci_softc *sc, device_t dev)
 {
-	uint32_t reg, reg2;
+	uint32_t lps, reg, reg2;
+	int lps_counter = 0;
 	int e1394a = 1;
-/*
- * probe PHY parameters
- * 0. to prove PHY version, whether compliance of 1394a.
- * 1. to probe maximum speed supported by the PHY and 
- *    number of port supported by core-logic.
- *    It is not actually available port on your PC .
- */
+
+	/*
+	 * Enable LPS(Link Power Status as per 
+	 * section 5.7 of OHCI v1.1
+	 * This allows PHY communication after
+	 * a hard/soft reset
+	 *
+	 * Some users report that the code
+	 * will crash without the pause due
+	 * to the lps bit being set and the 
+	 * PHY not being up.  Implement pause
+	 * here to work around this error.
+	 */
 	OWRITE(sc, OHCI_HCCCTL, OHCI_HCC_LPS);
-	DELAY(500);
-
+	bus_space_barrier(sc->bst, sc->bsh, OHCI_HCCCTL, 4, BUS_SPACE_BARRIER_WRITE);
+	for (lps = 0, lps_counter = 0; !lps && lps_counter < 3; lps_counter++) {
+		pause("fwlps", (50 * hz + 999) / 1000);
+		lps = (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_LPS);
+	}
+	/*
+ 	* probe PHY parameters
+ 	* 0. to prove PHY version, whether compliance of 1394a.
+ 	* 1. to probe maximum speed supported by the PHY and 
+ 	*    number of port supported by core-logic.
+ 	*    It is not actually available port on your PC .
+ 	*/
 	reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
 
+	/*
+	 * ref 1394-2000 table 5B-1
+	 * ref 1394-1995 table J.12
+	 * If Extended is not set
+	 * Assume 1394-1995
+	 * If Extended is set
+	 * Assume 1394-2000(1394a)
+	 */
 	if((reg >> 5) != 7 ){
 		sc->fc.mode &= ~FWPHYASYST;
 		sc->fc.nport = reg & FW_PHY_NP;
@@ -453,12 +501,12 @@
 			"Phy 1394 only %s, %d ports.\n",
 			linkspeed[sc->fc.speed], sc->fc.nport);
 	}else{
-		reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG);
 		sc->fc.mode |= FWPHYASYST;
 		sc->fc.nport = reg & FW_PHY_NP;
+		reg2 = fwphy_rddata(sc, FW_PHY_ESPD_REG);
 		sc->fc.speed = (reg2 & FW_PHY_ESPD) >> 5;
 		if (sc->fc.speed > MAX_SPEED) {
-			device_printf(dev, "invalid speed %d (fixed to %d).\n",
+			device_printf(dev, "invalid extended speed %d (fixed to %d).\n",
 				sc->fc.speed, MAX_SPEED);
 			sc->fc.speed = MAX_SPEED;
 		}
@@ -468,11 +516,7 @@
 
 		/* check programPhyEnable */
 		reg2 = fwphy_rddata(sc, 5);
-#if 0
-		if (e1394a && (OREAD(sc, OHCI_HCCCTL) & OHCI_HCC_PRPHY)) {
-#else	/* XXX force to enable 1394a */
 		if (e1394a) {
-#endif
 			if (firewire_debug)
 				device_printf(dev,
 					"Enable 1394a Enhancements\n");
@@ -488,6 +532,13 @@
 		reg2 = fwphy_wrdata(sc, 5, reg2);
 	}
 
+	/*
+	 * Re-read and check for extended 1394a
+	 * PHY Register map.
+	 * Then set the Contender bit on.
+	 * This makes us a possible bus or isoc
+	 * resource manager. (ieee 1394a-2000, 5B.1)
+	 */
 	reg = fwphy_rddata(sc, FW_PHY_SPD_REG);
 	if((reg >> 5) == 7 ){
 		reg = fwphy_rddata(sc, 4);

--=-Z1PMy3ujl2uNspxmxomY--




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