This only affects Silicon Image host controllers. It was only tested with a Sil3132. I have found two bugs in the port multiplier code and a place where an added delay is both necessary and sufficient to make my setup work, even though I can't explain why. The first change in ata_siiprb_issue_cmd() increases the timeout count from 10,000 to 31,000 counts. When a soft reset is issued to a port multiplier disk port this loop may have to wait for the hard disk to spin up. I consistently saw 15,000 counts as needed by experiment; assuming counts are milliseconds then 31,000 is what ATA calls for. Note that currently empty disk ports behind a port multiplier are detected by letting this loop time out; i.e., an empty port multiplier enclosure can lengthen boot time by 2.5 minutes. Some other strategy for disk detection might be needed later (the PHY probably is a good approach). The second change in ata_siiprb_issue_cmd() fixes a typo: failure was being returned if a command took more than 1,000 counts even if it completed within the allotted 10,000 counts. The last change in ata_siiprb_softreset() is a delay that mysteriously turns out to be necessary. I don't know why, how much or how little is needed. Hardware is like that sometimes. With this my setup, with a Sil3132 host controller, always detects the drives in my Sil3726-based port-multiplier enclosures. There are other severe problems in usage, especially on my 12GB RAM system, but at least this may let people get past disk detection and on to those other issues. /usr/src-current# svn di Index: sys/dev/ata/chipsets/ata-siliconimage.c =================================================================== --- sys/dev/ata/chipsets/ata-siliconimage.c (revision 186316) +++ sys/dev/ata/chipsets/ata-siliconimage.c (working copy) _at__at_ -679,7 +679,7 _at__at_ ATA_OUTL(ctlr->r_res2, 0x1c04 + offset, prb_bus >> 32); /* poll for command finished */ - for (timeout = 0; timeout < 10000; timeout++) { + for (timeout = 0; timeout < 31000; timeout++) { DELAY(1000); if ((status = ATA_INL(ctlr->r_res2, 0x1008 + offset)) & 0x00010000) break; _at__at_ -687,7 +687,7 _at__at_ // SOS XXX ATA_OUTL(ctlr->r_res2, 0x1008 + offset, 0x00010000); ATA_OUTL(ctlr->r_res2, 0x1008 + offset, 0x08ff08ff); - if (timeout >= 1000) + if (timeout >= 31000) return EIO; if (bootverbose) _at__at_ -761,6 +761,18 _at__at_ prb->control = htole16(0x0080); prb->fis[1] = port & 0x0f; + ata_udelay(150000); + ata_udelay(150000); + ata_udelay(150000); + ata_udelay(150000); + ata_udelay(150000); + ata_udelay(150000); + ata_udelay(150000); + ata_udelay(150000); + ata_udelay(150000); + ata_udelay(150000); + ata_udelay(150000); + /* issue soft reset */ if (ata_siiprb_issue_cmd(dev)) return -1; /usr/src-current#Received on Fri Dec 19 2008 - 09:22:19 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:39 UTC