summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsbruno <sbruno@FreeBSD.org>2009-03-17 13:07:11 +0000
committersbruno <sbruno@FreeBSD.org>2009-03-17 13:07:11 +0000
commit09ece7e11668779e8400060a5e793f30272f0aee (patch)
tree84916dc5f5f07bad4d8cbc4ca203faff9a36f067
parente905171fbe93556305cb1fa0334861bd122339d2 (diff)
downloadFreeBSD-src-09ece7e11668779e8400060a5e793f30272f0aee.zip
FreeBSD-src-09ece7e11668779e8400060a5e793f30272f0aee.tar.gz
Reviewed by: scott (scottl@freebsd.org)
Obtained from: Hideotshi Shimokawa This update is based on comments from Hidetoshi. Changeset 183550 removed the call to crom_load() in fw_busreset(). Restore that call such that the Configuration ROM is valid. Stash and update fwdev settings in fw_explore_node() so that negotiation works again.
-rw-r--r--sys/dev/firewire/firewire.c84
1 files changed, 52 insertions, 32 deletions
diff --git a/sys/dev/firewire/firewire.c b/sys/dev/firewire/firewire.c
index 05cf834..c2d4edf 100644
--- a/sys/dev/firewire/firewire.c
+++ b/sys/dev/firewire/firewire.c
@@ -685,7 +685,8 @@ fw_init_crom(struct firewire_comm *fc)
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 @@ fw_busreset(struct firewire_comm *fc, uint32_t new_status)
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 @@ fw_busreset(struct firewire_comm *fc, uint32_t new_status)
}
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 @@ fw_explore_node(struct fw_device *dfwdev)
}
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 @@ fw_explore_node(struct fw_device *dfwdev)
* 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 @@ fw_explore_node(struct fw_device *dfwdev)
* 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,15 +1658,15 @@ fw_explore_node(struct fw_device *dfwdev)
device_printf(fc->bdev, "New %s device ID:%08x%08x\n",
linkspeed[fwdev->speed],
fwdev->eui.hi, fwdev->eui.lo);
- }
- 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);
+ } 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);
+ }
}
bzero(&fwdev->csrrom[0], CROMSIZE);
@@ -1661,6 +1678,9 @@ fw_explore_node(struct fw_device *dfwdev)
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;
}
OpenPOWER on IntegriCloud