Implement SATA revision (speed) control for legacy SATA controller for
both boot (via loader tunables) and run-time (via `camcontrol negotiate`). Tested to work at least on NVIDIA MCP55 chipset. H/w provided by: glebius
This commit is contained in:
parent
4143500b7b
commit
63f83ebad9
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user