svn commit: r213291 - in stable/8/sys/dev/ata: . chipsets
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Thu Sep 30 04:03:15 UTC 2010
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);
More information about the svn-src-all
mailing list