patch; svn186316; SATA port multiplier disk detect bugs

From: James R. Van Artsdalen <james-freebsd-current_at_jrv.org>
Date: Fri, 19 Dec 2008 04:22:18 -0600
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