summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-03-27 08:43:45 +0000
committermav <mav@FreeBSD.org>2015-03-27 08:43:45 +0000
commitf96653efd877c4f04bc148934801b26221f2e365 (patch)
tree230a8642039f2c9fe7bef8236e77a036c6e0041a /usr.sbin
parentf4f616ce8b950629e88c738fd6c27acccbb8c686 (diff)
downloadFreeBSD-src-f96653efd877c4f04bc148934801b26221f2e365.zip
FreeBSD-src-f96653efd877c4f04bc148934801b26221f2e365.tar.gz
MFC r279965: Polish AHCI disk identify data and fix speed negotiation.
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/bhyve/ahci.h22
-rw-r--r--usr.sbin/bhyve/pci_ahci.c44
2 files changed, 49 insertions, 17 deletions
diff --git a/usr.sbin/bhyve/ahci.h b/usr.sbin/bhyve/ahci.h
index 7101dc5..1fd9f20 100644
--- a/usr.sbin/bhyve/ahci.h
+++ b/usr.sbin/bhyve/ahci.h
@@ -96,13 +96,14 @@
#define ATA_SS_SPD_NO_SPEED 0x00000000
#define ATA_SS_SPD_GEN1 0x00000010
#define ATA_SS_SPD_GEN2 0x00000020
-#define ATA_SS_SPD_GEN3 0x00000040
+#define ATA_SS_SPD_GEN3 0x00000030
#define ATA_SS_IPM_MASK 0x00000f00
#define ATA_SS_IPM_NO_DEVICE 0x00000000
#define ATA_SS_IPM_ACTIVE 0x00000100
#define ATA_SS_IPM_PARTIAL 0x00000200
#define ATA_SS_IPM_SLUMBER 0x00000600
+#define ATA_SS_IPM_DEVSLEEP 0x00000800
#define ATA_SERROR 14
#define ATA_SE_DATA_CORRECTED 0x00000001
@@ -133,17 +134,19 @@
#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_SPD_SPEED_GEN3 0x00000030
#define ATA_SC_IPM_MASK 0x00000f00
#define ATA_SC_IPM_NONE 0x00000000
#define ATA_SC_IPM_DIS_PARTIAL 0x00000100
#define ATA_SC_IPM_DIS_SLUMBER 0x00000200
+#define ATA_SC_IPM_DIS_DEVSLEEP 0x00000400
#define ATA_SACTIVE 16
#define AHCI_MAX_PORTS 32
#define AHCI_MAX_SLOTS 32
+#define AHCI_MAX_IRQS 16
/* SATA AHCI v1.0 register defines */
#define AHCI_CAP 0x00
@@ -208,6 +211,9 @@
#define AHCI_CAP2_BOH 0x00000001
#define AHCI_CAP2_NVMP 0x00000002
#define AHCI_CAP2_APST 0x00000004
+#define AHCI_CAP2_SDS 0x00000008
+#define AHCI_CAP2_SADM 0x00000010
+#define AHCI_CAP2_DESO 0x00000020
#define AHCI_OFFSET 0x100
#define AHCI_STEP 0x80
@@ -265,6 +271,7 @@
#define AHCI_P_CMD_ACTIVE 0x10000000
#define AHCI_P_CMD_PARTIAL 0x20000000
#define AHCI_P_CMD_SLUMBER 0x60000000
+#define AHCI_P_CMD_DEVSLEEP 0x80000000
#define AHCI_P_TFD 0x20
#define AHCI_P_SIG 0x24
@@ -284,6 +291,17 @@
#define AHCI_P_FBS_ADO_SHIFT 12
#define AHCI_P_FBS_DWE 0x000f0000
#define AHCI_P_FBS_DWE_SHIFT 16
+#define AHCI_P_DEVSLP 0x44
+#define AHCI_P_DEVSLP_ADSE 0x00000001
+#define AHCI_P_DEVSLP_DSP 0x00000002
+#define AHCI_P_DEVSLP_DETO 0x000003fc
+#define AHCI_P_DEVSLP_DETO_SHIFT 2
+#define AHCI_P_DEVSLP_MDAT 0x00007c00
+#define AHCI_P_DEVSLP_MDAT_SHIFT 10
+#define AHCI_P_DEVSLP_DITO 0x01ff8000
+#define AHCI_P_DEVSLP_DITO_SHIFT 15
+#define AHCI_P_DEVSLP_DM 0x0e000000
+#define AHCI_P_DEVSLP_DM_SHIFT 25
/* Just to be sure, if building as module. */
#if MAXPHYS < 512 * 1024
diff --git a/usr.sbin/bhyve/pci_ahci.c b/usr.sbin/bhyve/pci_ahci.c
index 653a66e..c7a8fd5 100644
--- a/usr.sbin/bhyve/pci_ahci.c
+++ b/usr.sbin/bhyve/pci_ahci.c
@@ -431,7 +431,6 @@ ahci_port_stop(struct ahci_port *p)
static void
ahci_port_reset(struct ahci_port *pr)
{
- pr->sctl = 0;
pr->serr = 0;
pr->sact = 0;
pr->xfermode = ATA_UDMA6;
@@ -443,8 +442,11 @@ ahci_port_reset(struct ahci_port *pr)
pr->tfd = 0x7F;
return;
}
- pr->ssts = ATA_SS_DET_PHY_ONLINE | ATA_SS_SPD_GEN2 |
- ATA_SS_IPM_ACTIVE;
+ pr->ssts = ATA_SS_DET_PHY_ONLINE | ATA_SS_IPM_ACTIVE;
+ if (pr->sctl & ATA_SC_SPD_MASK)
+ pr->ssts |= (pr->sctl & ATA_SC_SPD_MASK);
+ else
+ pr->ssts |= ATA_SS_SPD_GEN3;
pr->tfd = (1 << 8) | ATA_S_DSC | ATA_S_DMA;
if (!pr->atapi) {
pr->sig = PxSIG_ATA;
@@ -470,6 +472,7 @@ ahci_reset(struct pci_ahci_softc *sc)
for (i = 0; i < sc->ports; i++) {
sc->port[i].ie = 0;
sc->port[i].is = 0;
+ sc->port[i].sctl = 0;
ahci_port_reset(&sc->port[i]);
}
}
@@ -808,26 +811,36 @@ handle_identify(struct ahci_port *p, int slot, uint8_t *cfis)
buf[53] = (1 << 1 | 1 << 2);
if (p->mult_sectors)
buf[59] = (0x100 | p->mult_sectors);
- buf[60] = sectors;
- buf[61] = (sectors >> 16);
+ if (sectors <= 0x0fffffff) {
+ buf[60] = sectors;
+ buf[61] = (sectors >> 16);
+ } else {
+ buf[60] = 0xffff;
+ buf[61] = 0x0fff;
+ }
buf[63] = 0x7;
if (p->xfermode & ATA_WDMA0)
buf[63] |= (1 << ((p->xfermode & 7) + 8));
buf[64] = 0x3;
- buf[65] = 100;
- buf[66] = 100;
- buf[67] = 100;
- buf[68] = 100;
+ buf[65] = 120;
+ buf[66] = 120;
+ buf[67] = 120;
+ buf[68] = 120;
buf[69] = 0;
buf[75] = 31;
- buf[76] = (1 << 8 | 1 << 2);
+ buf[76] = (ATA_SATA_GEN1 | ATA_SATA_GEN2 | ATA_SATA_GEN3 |
+ ATA_SUPPORT_NCQ);
buf[80] = 0x1f0;
buf[81] = 0x28;
- buf[82] = (1 << 5 | 1 << 14);
- buf[83] = (1 << 10 | 1 << 12 | 1 << 13 | 1 << 14);
+ buf[82] = (ATA_SUPPORT_POWERMGT | ATA_SUPPORT_WRITECACHE|
+ ATA_SUPPORT_LOOKAHEAD | ATA_SUPPORT_NOP);
+ buf[83] = (ATA_SUPPORT_ADDRESS48 | ATA_SUPPORT_FLUSHCACHE |
+ ATA_SUPPORT_FLUSHCACHE48 | 1 << 14);
buf[84] = (1 << 14);
- buf[85] = (1 << 5 | 1 << 14);
- buf[86] = (1 << 10 | 1 << 12 | 1 << 13);
+ buf[85] = (ATA_SUPPORT_POWERMGT | ATA_SUPPORT_WRITECACHE|
+ ATA_SUPPORT_LOOKAHEAD | ATA_SUPPORT_NOP);
+ buf[86] = (ATA_SUPPORT_ADDRESS48 | ATA_SUPPORT_FLUSHCACHE |
+ ATA_SUPPORT_FLUSHCACHE48);
buf[87] = (1 << 14);
buf[88] = 0x7f;
if (p->xfermode & ATA_UDMA0)
@@ -854,6 +867,7 @@ handle_identify(struct ahci_port *p, int slot, uint8_t *cfis)
buf[117] = sectsz / 2;
buf[118] = ((sectsz / 2) >> 16);
}
+ buf[222] = 0x1020;
ahci_write_fis_piosetup(p);
write_prdt(p, slot, cfis, (void *)buf, sizeof(buf));
ahci_write_fis_d2h(p, slot, cfis, ATA_S_DSC | ATA_S_READY);
@@ -1851,10 +1865,10 @@ pci_ahci_port_write(struct pci_ahci_softc *sc, uint64_t offset, uint64_t value)
WPRINTF("pci_ahci_port: read only registers 0x%"PRIx64"\n", offset);
break;
case AHCI_P_SCTL:
+ p->sctl = value;
if (!(p->cmd & AHCI_P_CMD_ST)) {
if (value & ATA_SC_DET_RESET)
ahci_port_reset(p);
- p->sctl = value;
}
break;
case AHCI_P_SERR:
OpenPOWER on IntegriCloud