Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 9 Jun 2011 16:30:13 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r222897 - head/sys/dev/ata
Message-ID:  <201106091630.p59GUDGP086251@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Thu Jun  9 16:30:13 2011
New Revision: 222897
URL: http://svn.freebsd.org/changeset/base/222897

Log:
  Intel NM10 chipset's SATA controller has same PCI ID and revision as ICH7's,
  but has only 2 SATA ports instead of 4. The worst part is that SStatus and
  SError registers for missing ports are not implemented and return wrong
  values (0xffffffff), that caused infinite reset loop.
  
  Just ignore that SError value while I found no better way to identify them.

Modified:
  head/sys/dev/ata/ata-sata.c

Modified: head/sys/dev/ata/ata-sata.c
==============================================================================
--- head/sys/dev/ata/ata-sata.c	Thu Jun  9 11:54:11 2011	(r222896)
+++ head/sys/dev/ata/ata-sata.c	Thu Jun  9 16:30:13 2011	(r222897)
@@ -54,6 +54,11 @@ ata_sata_phy_check_events(device_t dev, 
     u_int32_t error, status;
 
     ata_sata_scr_read(ch, port, ATA_SERROR, &error);
+
+    /* Check that SError value is sane. */
+    if (error == 0xffffffff)
+	return;
+
     /* Clear set error bits/interrupt. */
     if (error)
 	ata_sata_scr_write(ch, port, ATA_SERROR, error);
@@ -163,18 +168,18 @@ ata_sata_phy_reset(device_t dev, int por
 
     if (bootverbose) {
 	if (port < 0) {
-	    device_printf(dev, "hardware reset ...\n");
+	    device_printf(dev, "hard reset ...\n");
 	} else {
-	    device_printf(dev, "p%d: hardware reset ...\n", port);
+	    device_printf(dev, "p%d: hard reset ...\n", port);
 	}
     }
     for (retry = 0; retry < 10; retry++) {
 	for (loop = 0; loop < 10; loop++) {
 	    if (ata_sata_scr_write(ch, port, ATA_SCONTROL, ATA_SC_DET_RESET))
-		return (0);
+		goto fail;
 	    ata_udelay(100);
 	    if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
-		return (0);
+		goto fail;
 	    if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_RESET)
 		break;
 	}
@@ -183,15 +188,26 @@ ata_sata_phy_reset(device_t dev, int por
 	    if (ata_sata_scr_write(ch, port, ATA_SCONTROL,
 		    ATA_SC_DET_IDLE | ((ch->pm_level > 0) ? 0 :
 		    ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)))
-		return (0);
+		goto fail;
 	    ata_udelay(100);
 	    if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
-		return (0);
+		goto fail;
 	    if ((val & ATA_SC_DET_MASK) == 0)
 		return ata_sata_connect(ch, port, 0);
 	}
     }
-    return 0;
+fail:
+    /* Clear SATA error register. */
+    ata_sata_scr_write(ch, port, ATA_SERROR, 0xffffffff);
+
+    if (bootverbose) {
+	if (port < 0) {
+	    device_printf(dev, "hard reset failed\n");
+	} else {
+	    device_printf(dev, "p%d: hard reset failed\n", port);
+	}
+    }
+    return (0);
 }
 
 int



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