summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/ata.410
-rw-r--r--sys/dev/ata/ata-all.c9
-rw-r--r--sys/dev/ata/ata-all.h1
-rw-r--r--sys/dev/ata/ata-sata.c21
4 files changed, 35 insertions, 6 deletions
diff --git a/share/man/man4/ata.4 b/share/man/man4/ata.4
index 939c8b1..b325eb7 100644
--- a/share/man/man4/ata.4
+++ b/share/man/man4/ata.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 18, 2012
+.Dd October 3, 2012
.Dt ATA 4
.Os
.Sh NAME
@@ -99,7 +99,7 @@ set to 0 to disable the 80pin cable check (the default is 1, check the cable).
set to 1 to allow Message Signalled Interrupts (MSI) to be used by the
specified PCI ATA controller, if supported.
.It Va hint.ata.X.devX.mode
-limits the initial ATA mode for the specified device on specified the channel.
+limits the initial ATA mode for the specified device on the specified channel.
.It Va hint.ata.X.mode
limits the initial ATA mode for every device on the specified channel.
.It Va hint.ata.X.pm_level
@@ -120,6 +120,12 @@ host initiates SLUMBER PM state transition every time port becomes idle.
.El
.Pp
Modes 2 and 3 are only supported for AHCI.
+.It Va hint.ata. Ns Ar X Ns Va .dev Ns Ar X Ns Va .sata_rev
+limits the initial SATA revision (speed) for the specified device
+on the specified channel.
+Values 1, 2 and 3 are respectively 1.5, 3 and 6Gbps.
+.It Va hint.ata. Ns Ar X Ns Va .sata_rev
+Same, but for every device on the specified channel.
.El
.Sh DESCRIPTION
The
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 07cb91f..e061744 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -172,6 +172,15 @@ ata_attach(device_t dev)
TASK_INIT(&ch->conntask, 0, ata_conn_event, dev);
#ifdef ATA_CAM
for (i = 0; i < 16; i++) {
+ ch->user[i].revision = 0;
+ snprintf(buf, sizeof(buf), "dev%d.sata_rev", i);
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), buf, &mode) != 0 &&
+ resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "sata_rev", &mode) != 0)
+ mode = -1;
+ if (mode >= 0)
+ ch->user[i].revision = mode;
ch->user[i].mode = 0;
snprintf(buf, sizeof(buf), "dev%d.mode", i);
if (resource_string_value(device_get_name(dev),
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 8209808..7154d56 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -142,6 +142,7 @@
#define ATA_SC_SPD_NO_SPEED 0x00000000
#define ATA_SC_SPD_SPEED_GEN1 0x00000010
#define ATA_SC_SPD_SPEED_GEN2 0x00000020
+#define ATA_SC_SPD_SPEED_GEN3 0x00000040
#define ATA_SC_IPM_MASK 0x00000f00
#define ATA_SC_IPM_NONE 0x00000000
diff --git a/sys/dev/ata/ata-sata.c b/sys/dev/ata/ata-sata.c
index 465e4b2..931c60e 100644
--- a/sys/dev/ata/ata-sata.c
+++ b/sys/dev/ata/ata-sata.c
@@ -152,8 +152,12 @@ int
ata_sata_phy_reset(device_t dev, int port, int quick)
{
struct ata_channel *ch = device_get_softc(dev);
- int loop, retry;
- uint32_t val;
+ int loop, retry, sata_rev;
+ uint32_t val, val1;
+
+ sata_rev = ch->user[port < 0 ? 0 : port].revision;
+ if (sata_rev > 0)
+ quick = 0;
if (quick) {
if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
@@ -173,9 +177,18 @@ ata_sata_phy_reset(device_t dev, int port, int quick)
device_printf(dev, "p%d: hard reset ...\n", port);
}
}
+ if (sata_rev == 1)
+ val1 = ATA_SC_SPD_SPEED_GEN1;
+ else if (sata_rev == 2)
+ val1 = ATA_SC_SPD_SPEED_GEN2;
+ else if (sata_rev == 3)
+ val1 = ATA_SC_SPD_SPEED_GEN3;
+ else
+ val1 = 0;
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))
+ if (ata_sata_scr_write(ch, port, ATA_SCONTROL, ATA_SC_DET_RESET |
+ val1 | ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER))
goto fail;
ata_udelay(100);
if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
@@ -186,7 +199,7 @@ ata_sata_phy_reset(device_t dev, int port, int quick)
ata_udelay(5000);
for (loop = 0; loop < 10; loop++) {
if (ata_sata_scr_write(ch, port, ATA_SCONTROL,
- ATA_SC_DET_IDLE | ((ch->pm_level > 0) ? 0 :
+ ATA_SC_DET_IDLE | val1 | ((ch->pm_level > 0) ? 0 :
ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)))
goto fail;
ata_udelay(100);
OpenPOWER on IntegriCloud