Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Sep 2010 04:03:14 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r213291 - in stable/8/sys/dev/ata: . chipsets
Message-ID:  <201009300403.o8U43E8w051952@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Thu Sep 30 04:03:14 2010
New Revision: 213291
URL: http://svn.freebsd.org/changeset/base/213291

Log:
  MFC r212359:
  
  Fix a problem where device detection would work unreliably on Serverworks
  K2 SATA controllers. The chip's status register must be read first, and
  as a long, for other registers to be correctly updated after a command, and
  this includes the command sequence in device detection as well as the
  previously handled case after interrupts. While here, clean up some
  previous hacks related to this controller.

Modified:
  stable/8/sys/dev/ata/ata-all.h
  stable/8/sys/dev/ata/ata-lowlevel.c
  stable/8/sys/dev/ata/chipsets/ata-serverworks.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/dev/ata/ata-all.h
==============================================================================
--- stable/8/sys/dev/ata/ata-all.h	Thu Sep 30 03:16:35 2010	(r213290)
+++ stable/8/sys/dev/ata/ata-all.h	Thu Sep 30 04:03:14 2010	(r213291)
@@ -566,6 +566,7 @@ struct ata_channel {
 #define         ATA_SATA		0x80
 #define         ATA_DMA_BEFORE_CMD	0x100
 #define         ATA_KNOWN_PRESENCE	0x200
+#define         ATA_STATUS_IS_LONG	0x400
 
     int				pm_level;	/* power management level */
     int                         devices;        /* what is present */

Modified: stable/8/sys/dev/ata/ata-lowlevel.c
==============================================================================
--- stable/8/sys/dev/ata/ata-lowlevel.c	Thu Sep 30 03:16:35 2010	(r213290)
+++ stable/8/sys/dev/ata/ata-lowlevel.c	Thu Sep 30 04:03:14 2010	(r213291)
@@ -516,10 +516,13 @@ ata_generic_reset(device_t dev)
 	if ((mask & 0x01) && (stat0 & ATA_S_BUSY)) {
 	    ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(ATA_MASTER));
 	    DELAY(10);
+	    if (ch->flags & ATA_STATUS_IS_LONG)
+		    stat0 = ATA_IDX_INL(ch, ATA_STATUS) & 0xff;
+	    else
+		    stat0 = ATA_IDX_INB(ch, ATA_STATUS);
 	    err = ATA_IDX_INB(ch, ATA_ERROR);
 	    lsb = ATA_IDX_INB(ch, ATA_CYL_LSB);
 	    msb = ATA_IDX_INB(ch, ATA_CYL_MSB);
-	    stat0 = ATA_IDX_INB(ch, ATA_STATUS);
 	    if (bootverbose)
 		device_printf(dev,
 			      "stat0=0x%02x err=0x%02x lsb=0x%02x msb=0x%02x\n",
@@ -546,10 +549,13 @@ ata_generic_reset(device_t dev)
 	    !((mask & 0x01) && (stat0 & ATA_S_BUSY))) {
 	    ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_DEV(ATA_SLAVE));
 	    DELAY(10);
+	    if (ch->flags & ATA_STATUS_IS_LONG)
+		    stat1 = ATA_IDX_INL(ch, ATA_STATUS) & 0xff;
+	    else
+		    stat1 = ATA_IDX_INB(ch, ATA_STATUS);
 	    err = ATA_IDX_INB(ch, ATA_ERROR);
 	    lsb = ATA_IDX_INB(ch, ATA_CYL_LSB);
 	    msb = ATA_IDX_INB(ch, ATA_CYL_MSB);
-	    stat1 = ATA_IDX_INB(ch, ATA_STATUS);
 	    if (bootverbose)
 		device_printf(dev,
 			      "stat1=0x%02x err=0x%02x lsb=0x%02x msb=0x%02x\n",

Modified: stable/8/sys/dev/ata/chipsets/ata-serverworks.c
==============================================================================
--- stable/8/sys/dev/ata/chipsets/ata-serverworks.c	Thu Sep 30 03:16:35 2010	(r213290)
+++ stable/8/sys/dev/ata/chipsets/ata-serverworks.c	Thu Sep 30 04:03:14 2010	(r213291)
@@ -61,9 +61,8 @@ static int ata_serverworks_ch_detach(dev
 static void ata_serverworks_tf_read(struct ata_request *request);
 static void ata_serverworks_tf_write(struct ata_request *request);
 static int ata_serverworks_setmode(device_t dev, int target, int mode);
-#ifdef __powerpc__
+static void ata_serverworks_sata_reset(device_t dev);
 static int ata_serverworks_status(device_t dev);
-#endif
 
 /* misc defines */
 #define SWKS_33		0
@@ -104,7 +103,6 @@ ata_serverworks_probe(device_t dev)
     return (BUS_PROBE_DEFAULT);
 }
 
-#ifdef __powerpc__
 static int
 ata_serverworks_status(device_t dev)
 {
@@ -126,7 +124,6 @@ ata_serverworks_status(device_t dev)
 
     return ata_pci_status(dev);
 }
-#endif
 
 static int
 ata_serverworks_chipinit(device_t dev)
@@ -148,6 +145,7 @@ ata_serverworks_chipinit(device_t dev)
 	ctlr->ch_detach = ata_serverworks_ch_detach;
 	ctlr->setmode = ata_sata_setmode;
 	ctlr->getrev = ata_sata_getrev;
+	ctlr->reset = ata_serverworks_sata_reset;
 	return 0;
     }
     else if (ctlr->chip->cfg1 == SWKS_33) {
@@ -213,14 +211,11 @@ ata_serverworks_ch_attach(device_t dev)
     ch->r_io[ATA_SERROR].offset = ch_offset + 0x44;
     ch->r_io[ATA_SCONTROL].offset = ch_offset + 0x48;
 
-    ch->flags |= ATA_NO_SLAVE;
-    ch->flags |= ATA_SATA;
+    ch->flags |= ATA_NO_SLAVE | ATA_SATA | ATA_KNOWN_PRESENCE;
     ata_pci_hw(dev);
     ch->hw.tf_read = ata_serverworks_tf_read;
     ch->hw.tf_write = ata_serverworks_tf_write;
 #ifdef __powerpc__
-    ch->hw.status = ata_serverworks_status;
-
     /* Make sure that our interrupt is level low */
     powerpc_config_intr(bus_get_resource_start(device_get_parent(dev),
 	SYS_RES_IRQ, 0), INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
@@ -228,19 +223,13 @@ ata_serverworks_ch_attach(device_t dev)
 
     if (ctlr->chip->chipid == ATA_K2) {
 	/*
-	 * The revision 1 K2 SATA controller has interesting bugs. Patch them.
-	 * These magic numbers regulate interrupt delivery in the first few
-	 * cases and are pure magic in the last case.
-	 *
-	 * Values obtained from the Darwin driver.
+	 * Set SICR registers to turn off waiting for a status message
+	 * before sending FIS. Values obtained from the Darwin driver.
 	 */
 
-	ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, 0x04);
-	ATA_IDX_OUTL(ch, ATA_SERROR, 0xffffffff);
-	ATA_IDX_OUTL(ch, ATA_SCONTROL, 0x00000300);
-	ATA_OUTL(ctlr->r_res2, ch_offset + 0x88, 0);
 	ATA_OUTL(ctlr->r_res2, ch_offset + 0x80,
 	    ATA_INL(ctlr->r_res2, ch_offset + 0x80) & ~0x00040000);
+	ATA_OUTL(ctlr->r_res2, ch_offset + 0x88, 0);
 
 	/*
 	 * Some controllers have a bug where they will send the command
@@ -251,6 +240,14 @@ ata_serverworks_ch_attach(device_t dev)
 	 */
 
 	ch->flags |= ATA_DMA_BEFORE_CMD;
+
+	/*
+	 * The status register must be read as a long to fill the other
+	 * registers.
+	 */
+	
+	ch->hw.status = ata_serverworks_status;
+	ch->flags |= ATA_STATUS_IS_LONG;
     }
 
     /* chip does not reliably do 64K DMA transfers */
@@ -411,4 +408,15 @@ ata_serverworks_setmode(device_t dev, in
 	return (mode);
 }
 
+static void
+ata_serverworks_sata_reset(device_t dev)
+{
+	struct ata_channel *ch = device_get_softc(dev);
+
+	if (ata_sata_phy_reset(dev, -1, 1))
+		ata_generic_reset(dev);
+	else
+		ch->devices = 0;
+}
+
 ATA_DECLARE_DRIVER(ata_serverworks);



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