svn commit: r212145 - in head/sys/dev/ata: . chipsets

Alexander Motin mav at FreeBSD.org
Thu Sep 2 11:18:44 UTC 2010


Author: mav
Date: Thu Sep  2 11:18:43 2010
New Revision: 212145
URL: http://svn.freebsd.org/changeset/base/212145

Log:
  SATA1.x SiliconImage controllers on power-on reset TFD Status register into
  value 0xff. On hot-plug this value confuses ata_generic_reset() device
  presence detection logic. As soon as we already know drive presence from
  SATA hard reset, hint ata_generic_reset() to wait for device signature
  until success or full timeout.

Modified:
  head/sys/dev/ata/ata-all.h
  head/sys/dev/ata/ata-lowlevel.c
  head/sys/dev/ata/chipsets/ata-siliconimage.c

Modified: head/sys/dev/ata/ata-all.h
==============================================================================
--- head/sys/dev/ata/ata-all.h	Thu Sep  2 09:45:06 2010	(r212144)
+++ head/sys/dev/ata/ata-all.h	Thu Sep  2 11:18:43 2010	(r212145)
@@ -565,6 +565,7 @@ struct ata_channel {
 #define         ATA_NO_ATAPI_DMA	0x40
 #define         ATA_SATA		0x80
 #define         ATA_DMA_BEFORE_CMD	0x100
+#define         ATA_KNOWN_PRESENCE	0x200
 
     int				pm_level;	/* power management level */
     int                         devices;        /* what is present */

Modified: head/sys/dev/ata/ata-lowlevel.c
==============================================================================
--- head/sys/dev/ata/ata-lowlevel.c	Thu Sep  2 09:45:06 2010	(r212144)
+++ head/sys/dev/ata/ata-lowlevel.c	Thu Sep  2 11:18:43 2010	(r212145)
@@ -474,7 +474,8 @@ ata_generic_reset(device_t dev)
     ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(ATA_MASTER));
     DELAY(10);
     ostat0 = ATA_IDX_INB(ch, ATA_STATUS);
-    if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5) {
+    if (((ostat0 & 0xf8) != 0xf8 || (ch->flags & ATA_KNOWN_PRESENCE)) &&
+	    ostat0 != 0xa5) {
 	stat0 = ATA_S_BUSY;
 	mask |= 0x01;
     }
@@ -484,7 +485,8 @@ ata_generic_reset(device_t dev)
 	ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_DEV(ATA_SLAVE));
 	DELAY(10);      
 	ostat1 = ATA_IDX_INB(ch, ATA_STATUS);
-	if ((ostat1 & 0xf8) != 0xf8 && ostat1 != 0xa5) {
+	if (((ostat1 & 0xf8) != 0xf8 || (ch->flags & ATA_KNOWN_PRESENCE)) &&
+		ostat1 != 0xa5) {
 	    stat1 = ATA_S_BUSY;
 	    mask |= 0x02;
 	}
@@ -570,22 +572,16 @@ ata_generic_reset(device_t dev)
 	    }
 	}
 
-	if (mask == 0x00)       /* nothing to wait for */
-	    break;
-	if (mask == 0x01)       /* wait for master only */
-	    if (!(stat0 & ATA_S_BUSY) || (stat0 == 0xff && timeout > 10))
-		break;
-	if (mask == 0x02)       /* wait for slave only */
-	    if (!(stat1 & ATA_S_BUSY) || (stat1 == 0xff && timeout > 10))
-		break;
-	if (mask == 0x03) {     /* wait for both master & slave */
-	    if (!(stat0 & ATA_S_BUSY) && !(stat1 & ATA_S_BUSY))
-		break;
-	    if ((stat0 == 0xff) && (timeout > 20))
-		mask &= ~0x01;
-	    if ((stat1 == 0xff) && (timeout > 20))
-		mask &= ~0x02;
+	if ((ch->flags & ATA_KNOWN_PRESENCE) == 0 &&
+	    timeout > ((mask == 0x03) ? 20 : 10)) {
+		if ((mask & 0x01) && stat0 == 0xff)
+			mask &= ~0x01;
+		if ((mask & 0x02) && stat1 == 0xff)
+			mask &= ~0x02;
 	}
+	if (((mask & 0x01) == 0 || !(stat0 & ATA_S_BUSY)) &&
+	    ((mask & 0x02) == 0 || !(stat1 & ATA_S_BUSY)))
+		break;
 	ata_udelay(100000);
     }
 

Modified: head/sys/dev/ata/chipsets/ata-siliconimage.c
==============================================================================
--- head/sys/dev/ata/chipsets/ata-siliconimage.c	Thu Sep  2 09:45:06 2010	(r212144)
+++ head/sys/dev/ata/chipsets/ata-siliconimage.c	Thu Sep  2 11:18:43 2010	(r212145)
@@ -316,6 +316,7 @@ ata_sii_ch_attach(device_t dev)
 	ch->r_io[ATA_SCONTROL].offset = 0x100 + (unit01 << 7) + (unit10 << 8);
 	ch->flags |= ATA_NO_SLAVE;
 	ch->flags |= ATA_SATA;
+	ch->flags |= ATA_KNOWN_PRESENCE;
 
 	/* enable PHY state change interrupt */
 	ATA_OUTL(ctlr->r_res2, 0x148 + (unit01 << 7) + (unit10 << 8),(1 << 16));


More information about the svn-src-all mailing list