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);
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to