Re: Configuration ROM in firewire stack

Sean Bruno <[email protected]>
Newsgroups gmane.os.freebsd.devel.firewire
Message-ID <[email protected]>
On Fri, 2009-03-13 at 14:42 +0900, Hidetoshi Shimokawa wrote:
> Hi Sean,
> 
> It looks like you broke Configuration ROM build procedure in firewire stack in
> http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/dev/firewire/firewire.c.diff?r1=1.104;r2=1.105
> 
> In this change, you just copy "src" to "fc->config_rom" but it's wrong.
> You have to call crom_load() to get CROM built correctly.
> It is a critical problem for SCSI and dcons(4) target that highly
> depend on CROM.
> I think you can easily check this problem by 'fwcontrol -c [your own node_id]',
> you'll get broken CROM and CRC. If there are anything I can help you to fix this
> bug, let me know.
> 
> Thanks,
> 
> Hidetoshi@AsiaBSDCon2009
> 
> @@ -739,19 +758,19 @@ fw_busreset(struct firewire_comm *fc, ui
>  		free(devlistp, M_TEMP);
>  	}
> 
> -	newrom = malloc(CROMSIZE, M_FW, M_NOWAIT | M_ZERO);
>  	src = &fc->crom_src_buf->src;
> -	crom_load(src, (uint32_t *)newrom, CROMSIZE);
> -	if (bcmp(newrom, fc->config_rom, CROMSIZE) != 0) {
> -		/* bump generation and reload */
> -		src->businfo.generation ++;
> -		/* generation must be between 0x2 and 0xF */
> -		if (src->businfo.generation < 2)
> -			src->businfo.generation ++;
> -		crom_load(src, (uint32_t *)newrom, CROMSIZE);
> -		bcopy(newrom, (void *)fc->config_rom, CROMSIZE);
> -	}
> -	free(newrom, M_FW);
> +	/*
> +	 * If the old config rom needs to be overwritten,
> +	 * bump the businfo.generation indicator to
> +	 * indicate that we need to be reprobed
> +	 */
> +	if (bcmp(src, fc->config_rom, CROMSIZE) != 0) {
> +		/* generation is a 2 bit field */
> +		/* valid values are only from 0 - 3 */
> +		src->businfo.generation = 1;
> +		bcopy(src, (void *)fc->config_rom, CROMSIZE);
> +	} else
> +		src->businfo.generation = 0;
>  }
> 
>  /* Call once after reboot */
> @@ -807,13 +826,7 @@ void fw_init(struct firewire_comm *fc)
> 
> 


Please give this patch at try.  I think this should work.

Sean

_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-firewire
To unsubscribe, send any mail to "[email protected]"
firewire.c.diff (text/x-patch, 4.4 KB)
Index: firewire.c
===================================================================
--- firewire.c	(revision 189646)
+++ firewire.c	(working copy)
@@ -685,7 +685,8 @@
 	src->businfo.cyc_clk_acc = 100;
 	src->businfo.max_rec = fc->maxrec;
 	src->businfo.max_rom = MAXROM_4;
-	src->businfo.generation = 0;
+#define FW_GENERATION_CHANGEABLE 2
+	src->businfo.generation = FW_GENERATION_CHANGEABLE;
 	src->businfo.link_spd = fc->speed;
 
 	src->businfo.eui64.hi = fc->eui.hi;
@@ -734,6 +735,7 @@
 	struct firewire_dev_comm *fdc;
 	struct crom_src *src;
 	device_t *devlistp;
+	uint32_t *newrom;
 	int i, devcnt;
 
 	FW_GLOCK_ASSERT(fc);
@@ -759,18 +761,31 @@
 	}
 
 	src = &fc->crom_src_buf->src;
-	/*
-	 * If the old config rom needs to be overwritten,
-	 * bump the businfo.generation indicator to 
-	 * indicate that we need to be reprobed
-	 */
-	if (bcmp(src, fc->config_rom, CROMSIZE) != 0) {
-		/* generation is a 2 bit field */
-		/* valid values are only from 0 - 3 */
-		src->businfo.generation = 1;
-		bcopy(src, (void *)fc->config_rom, CROMSIZE);
-	} else
-		src->businfo.generation = 0;
+        /*
+         * If the old config rom needs to be overwritten,
+         * bump the businfo.generation indicator to 
+         * indicate that we need to be reprobed
+         * See 1394a-2000 8.3.2.5.4 for more details.
+         * generation starts at 2 and rolls over at 0xF
+         * back to 2.
+         * 
+         * A generation of 0 indicates a device
+         * that is not 1394a-2000 compliant.
+         * A generation of 1 indicates a device that
+         * does not change it's Bus Info Block or 
+         * Configuration ROM.
+         */
+#define FW_MAX_GENERATION 0xF
+	newrom = malloc(CROMSIZE, M_FW, M_NOWAIT | M_ZERO);
+	src = &fc->crom_src_buf->src;
+	crom_load(src, newrom, CROMSIZE);
+	if (bcmp(newrom, fc->config_rom, CROMSIZE) != 0) {
+		if ( src->businfo.generation++ > FW_MAX_GENERATION )
+			src->businfo.generation = FW_GENERATION_CHANGEABLE;
+		bcopy(newrom, (void *)fc->config_rom, CROMSIZE);
+	}
+	free(newrom, M_FW);
+
 }
 
 /* Call once after reboot */
@@ -1590,6 +1605,10 @@
 		}
 		fwdev->fc = fc;
 		fwdev->eui = binfo->eui64;
+		fwdev->dst = dfwdev->dst;
+		fwdev->maxrec = dfwdev->maxrec;
+		fwdev->status = dfwdev->status;
+
 		/*
 		 * Pre-1394a-2000 didn't have link_spd in
 		 * the Bus Info block, so try and use the 
@@ -1599,7 +1618,7 @@
 		 * ignore the speed map alltogether. SWB
 		 */
 		if ( binfo->link_spd == FWSPD_S100 /* 0 */) {
-			device_printf(fc->bdev, "%s"
+			device_printf(fc->bdev, "%s: "
 				"Pre 1394a-2000 detected\n",
 				__func__);
 			fwdev->speed = fc->speed_map->speed[fc->nodeid][node];
@@ -1609,21 +1628,19 @@
 		 * Test this speed with a read to the CSRROM.
 		 * If it fails, slow down the speed and retry.
 		 */
-		while (fwdev->speed > 0) {
+		while (fwdev->speed > FWSPD_S100 /* 0 */) {
 			err = fw_explore_read_quads(fwdev, CSRROMOFF,
             				&speed_test, 1);
-			if (err)
+			if (err) {
+				device_printf(fc->bdev, "%s: fwdev->speed(%s)"
+						" decremented due to negotiation\n",
+						__func__,
+						linkspeed[fwdev->speed]);
 				fwdev->speed--;
-			else
+			} else
 				break;
 				
 		}
-		if (fwdev->speed != binfo->link_spd)
-			device_printf(fc->bdev, "%s: fwdev->speed(%s)"
-						" set lower than binfo->link_spd(%s)\n",
-						__func__,
-						linkspeed[fwdev->speed],
-						linkspeed[binfo->link_spd]);
 		/* inesrt into sorted fwdev list */
 		pfwdev = NULL;
 		STAILQ_FOREACH(tfwdev, &fc->devices, link) {
@@ -1641,17 +1658,17 @@
 		device_printf(fc->bdev, "New %s device ID:%08x%08x\n",
 		    linkspeed[fwdev->speed],
 		    fwdev->eui.hi, fwdev->eui.lo);
+	} else {
+		fwdev->dst = node;
+		fwdev->status = FWDEVINIT;
+		/* unchanged ? */
+		if (bcmp(&csr[0], &fwdev->csrrom[0], sizeof(uint32_t) * 5) == 0) {
+			if (firewire_debug)
+				device_printf(fc->dev, "node%d: crom unchanged\n", node);
+			return (0);
+		}
 	}
-	fwdev->dst = node;
-	fwdev->status = FWDEVINIT;
 
-	/* unchanged ? */
-	if (bcmp(&csr[0], &fwdev->csrrom[0], sizeof(uint32_t) * 5) == 0) {
-		if (firewire_debug)
-			device_printf(fc->dev, "node%d: crom unchanged\n", node);
-		return (0);
-	}
-
 	bzero(&fwdev->csrrom[0], CROMSIZE);
 
 	/* copy first quad and bus info block */
@@ -1661,6 +1678,9 @@
 	err = fw_explore_csrblock(fwdev, 0x14, 1); /* root directory */
 
 	if (err) {
+		if (firewire_debug)
+			device_printf(fc->dev, "%s: explore csrblock failed err(%d)\n",
+					__func__, err);
 		fwdev->status = FWDEVINVAL;
 		fwdev->csrrom[0] = 0;
 	}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.