Make SATA XPT negotiate and enable some additional SATA features, such as:

- device initiated power management (some devices support only this way);
 - Automatic Partial to Slumber Transition (more power saving);
 - DMA auto-activation (expected to slightly improve performance).
More features could be added later, when hardware supports.
This commit is contained in:
Alexander Motin 2010-05-02 12:07:47 +00:00
parent f930c0db49
commit da6808c111
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=207499
8 changed files with 277 additions and 73 deletions

View File

@ -2855,6 +2855,10 @@ cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
sata->tags);
}
if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
sata->caps);
}
}
if (cts->protocol == PROTO_SCSI) {
struct ccb_trans_settings_scsi *scsi=

View File

@ -101,6 +101,7 @@ struct pmp_softc {
int events;
#define PMP_EV_RESET 1
#define PMP_EV_RESCAN 2
u_int caps;
struct task sysctl_task;
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
@ -457,6 +458,14 @@ pmpstart(struct cam_periph *periph, union ccb *start_ccb)
ata_pm_read_cmd(ataio, 2, 15);
break;
case PMP_STATE_PRECONFIG:
/* Get/update host SATA capabilities. */
bzero(&cts, sizeof(cts));
xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
xpt_action((union ccb *)&cts);
if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
softc->caps = cts.xport_specific.sata.caps;
cam_fill_ataio(ataio,
pmp_retry_count,
pmpdone,
@ -644,14 +653,16 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
(done_ccb->ataio.res.lba_mid << 16) +
(done_ccb->ataio.res.lba_low << 8) +
done_ccb->ataio.res.sector_count;
if ((res & 0xf0f) == 0x103 && (res & 0x0f0) != 0) {
if (((res & 0xf0f) == 0x103 && (res & 0x0f0) != 0) ||
(res & 0x600) != 0) {
if (bootverbose) {
printf("%s%d: port %d status: %08x\n",
periph->periph_name, periph->unit_number,
softc->pm_step, res);
}
/* Report device speed. */
if (xpt_create_path(&dpath, periph,
/* Report device speed if it is online. */
if ((res & 0xf0f) == 0x103 &&
xpt_create_path(&dpath, periph,
xpt_path_path_id(periph->path),
softc->pm_step, 0) == CAM_REQ_CMP) {
bzero(&cts, sizeof(cts));
@ -660,6 +671,9 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
cts.type = CTS_TYPE_CURRENT_SETTINGS;
cts.xport_specific.sata.revision = (res & 0x0f0) >> 4;
cts.xport_specific.sata.valid = CTS_SATA_VALID_REVISION;
cts.xport_specific.sata.caps = softc->caps &
(CTS_SATA_CAPS_H_PMREQ | CTS_SATA_CAPS_H_DMAAA);
cts.xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
xpt_action((union ccb *)&cts);
xpt_free_path(dpath);
}

View File

@ -88,6 +88,9 @@ typedef enum {
PROBE_IDENTIFY,
PROBE_SPINUP,
PROBE_SETMODE,
PROBE_SETPM,
PROBE_SETAPST,
PROBE_SETDMAAA,
PROBE_SET_MULTI,
PROBE_INQUIRY,
PROBE_FULL_INQUIRY,
@ -101,6 +104,9 @@ static char *probe_action_text[] = {
"PROBE_IDENTIFY",
"PROBE_SPINUP",
"PROBE_SETMODE",
"PROBE_SETPM",
"PROBE_SETAPST",
"PROBE_SETDMAAA",
"PROBE_SET_MULTI",
"PROBE_INQUIRY",
"PROBE_FULL_INQUIRY",
@ -132,6 +138,7 @@ typedef struct {
uint32_t pm_prv;
int restart;
int spinup;
u_int caps;
struct cam_periph *periph;
} probe_softc;
@ -393,6 +400,45 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
break;
}
case PROBE_SETPM:
cam_fill_ataio(ataio,
1,
probedone,
CAM_DIR_NONE,
0,
NULL,
0,
30*1000);
ata_28bit_cmd(ataio, ATA_SETFEATURES,
(softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90,
0, 0x03);
break;
case PROBE_SETAPST:
cam_fill_ataio(ataio,
1,
probedone,
CAM_DIR_NONE,
0,
NULL,
0,
30*1000);
ata_28bit_cmd(ataio, ATA_SETFEATURES,
(softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90,
0, 0x07);
break;
case PROBE_SETDMAAA:
cam_fill_ataio(ataio,
1,
probedone,
CAM_DIR_NONE,
0,
NULL,
0,
30*1000);
ata_28bit_cmd(ataio, ATA_SETFEATURES,
(softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90,
0, 0x02);
break;
case PROBE_SET_MULTI:
{
u_int sectors, bytecount;
@ -685,6 +731,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
probe_softc *softc;
struct cam_path *path;
u_int32_t priority;
u_int caps;
int found = 1;
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n"));
@ -879,6 +926,67 @@ device_fail: if ((!softc->restart) &&
xpt_schedule(periph, priority);
return;
case PROBE_SETMODE:
if (path->device->transport != XPORT_SATA)
goto notsata;
/* Set supported bits. */
bzero(&cts, sizeof(cts));
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
xpt_action((union ccb *)&cts);
if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H;
else
caps = 0;
if (ident_buf->satacapabilities != 0xffff) {
if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV)
caps |= CTS_SATA_CAPS_D_PMREQ;
if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST)
caps |= CTS_SATA_CAPS_D_APST;
}
/* Mask unwanted bits. */
bzero(&cts, sizeof(cts));
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_USER_SETTINGS;
xpt_action((union ccb *)&cts);
if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
caps &= cts.xport_specific.sata.caps;
/* Store result to SIM. */
bzero(&cts, sizeof(cts));
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
cts.xport_specific.sata.caps = caps;
cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS;
xpt_action((union ccb *)&cts);
softc->caps = caps;
if (ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) {
PROBE_SET_ACTION(softc, PROBE_SETPM);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
return;
}
/* FALLTHROUGH */
case PROBE_SETPM:
if (ident_buf->satacapabilities != 0xffff &&
ident_buf->satacapabilities & ATA_SUPPORT_DAPST) {
PROBE_SET_ACTION(softc, PROBE_SETAPST);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
return;
}
/* FALLTHROUGH */
case PROBE_SETAPST:
if (ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) {
PROBE_SET_ACTION(softc, PROBE_SETDMAAA);
xpt_release_ccb(done_ccb);
xpt_schedule(periph, priority);
return;
}
/* FALLTHROUGH */
case PROBE_SETDMAAA:
notsata:
if (path->device->protocol == PROTO_ATA) {
PROBE_SET_ACTION(softc, PROBE_SET_MULTI);
} else {
@ -964,6 +1072,35 @@ device_fail: if ((!softc->restart) &&
snprintf(ident_buf->revision, sizeof(ident_buf->revision),
"%04x", softc->pm_prv);
path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID;
/* Set supported bits. */
bzero(&cts, sizeof(cts));
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
xpt_action((union ccb *)&cts);
if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H;
else
caps = 0;
/* All PMPs must support PM requests. */
caps |= CTS_SATA_CAPS_D_PMREQ;
/* Mask unwanted bits. */
bzero(&cts, sizeof(cts));
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_USER_SETTINGS;
xpt_action((union ccb *)&cts);
if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
caps &= cts.xport_specific.sata.caps;
/* Store result to SIM. */
bzero(&cts, sizeof(cts));
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
cts.xport_specific.sata.caps = caps;
cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS;
xpt_action((union ccb *)&cts);
softc->caps = caps;
if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
path->device->flags &= ~CAM_DEV_UNCONFIGURED;
xpt_acquire_device(path->device);

View File

@ -837,12 +837,21 @@ struct ccb_trans_settings_sata {
#define CTS_SATA_VALID_PM 0x08
#define CTS_SATA_VALID_TAGS 0x10
#define CTS_SATA_VALID_ATAPI 0x20
#define CTS_SATA_VALID_CAPS 0x40
int mode; /* Legacy PATA mode */
u_int bytecount; /* Length of PIO transaction */
int revision; /* SATA revision */
u_int pm_present; /* PM is present (XPT->SIM) */
u_int tags; /* Number of allowed tags */
u_int atapi; /* Length of ATAPI CDB */
u_int caps; /* Device and host SATA caps. */
#define CTS_SATA_CAPS_H 0x0000ffff
#define CTS_SATA_CAPS_H_PMREQ 0x00000001
#define CTS_SATA_CAPS_H_APST 0x00000002
#define CTS_SATA_CAPS_H_DMAAA 0x00000010 /* Auto-activation */
#define CTS_SATA_CAPS_D 0xffff0000
#define CTS_SATA_CAPS_D_PMREQ 0x00010000
#define CTS_SATA_CAPS_D_APST 0x00020000
};
/* Get/Set transfer rate/width/disconnection/tag queueing settings */

View File

@ -111,6 +111,7 @@ static struct {
#define AHCI_Q_EDGEIS 64
#define AHCI_Q_SATA2 128
#define AHCI_Q_NOBSYRES 256
#define AHCI_Q_NOAA 512
} ahci_ids[] = {
{0x43801002, 0x00, "ATI IXP600", 0},
{0x43901002, 0x00, "ATI IXP700", 0},
@ -167,75 +168,75 @@ static struct {
{0x614511ab, 0x00, "Marvell 88SX6145", AHCI_Q_NOFORCE|AHCI_Q_4CH|AHCI_Q_EDGEIS},
{0x91231b4b, 0x11, "Marvell 88SE912x", AHCI_Q_NOBSYRES},
{0x91231b4b, 0x00, "Marvell 88SE912x", AHCI_Q_EDGEIS|AHCI_Q_SATA2|AHCI_Q_NOBSYRES},
{0x044c10de, 0x00, "NVIDIA MCP65", 0},
{0x044d10de, 0x00, "NVIDIA MCP65", 0},
{0x044e10de, 0x00, "NVIDIA MCP65", 0},
{0x044f10de, 0x00, "NVIDIA MCP65", 0},
{0x045c10de, 0x00, "NVIDIA MCP65", 0},
{0x045d10de, 0x00, "NVIDIA MCP65", 0},
{0x045e10de, 0x00, "NVIDIA MCP65", 0},
{0x045f10de, 0x00, "NVIDIA MCP65", 0},
{0x055010de, 0x00, "NVIDIA MCP67", 0},
{0x055110de, 0x00, "NVIDIA MCP67", 0},
{0x055210de, 0x00, "NVIDIA MCP67", 0},
{0x055310de, 0x00, "NVIDIA MCP67", 0},
{0x055410de, 0x00, "NVIDIA MCP67", 0},
{0x055510de, 0x00, "NVIDIA MCP67", 0},
{0x055610de, 0x00, "NVIDIA MCP67", 0},
{0x055710de, 0x00, "NVIDIA MCP67", 0},
{0x055810de, 0x00, "NVIDIA MCP67", 0},
{0x055910de, 0x00, "NVIDIA MCP67", 0},
{0x055A10de, 0x00, "NVIDIA MCP67", 0},
{0x055B10de, 0x00, "NVIDIA MCP67", 0},
{0x058410de, 0x00, "NVIDIA MCP67", 0},
{0x07f010de, 0x00, "NVIDIA MCP73", 0},
{0x07f110de, 0x00, "NVIDIA MCP73", 0},
{0x07f210de, 0x00, "NVIDIA MCP73", 0},
{0x07f310de, 0x00, "NVIDIA MCP73", 0},
{0x07f410de, 0x00, "NVIDIA MCP73", 0},
{0x07f510de, 0x00, "NVIDIA MCP73", 0},
{0x07f610de, 0x00, "NVIDIA MCP73", 0},
{0x07f710de, 0x00, "NVIDIA MCP73", 0},
{0x07f810de, 0x00, "NVIDIA MCP73", 0},
{0x07f910de, 0x00, "NVIDIA MCP73", 0},
{0x07fa10de, 0x00, "NVIDIA MCP73", 0},
{0x07fb10de, 0x00, "NVIDIA MCP73", 0},
{0x0ad010de, 0x00, "NVIDIA MCP77", 0},
{0x0ad110de, 0x00, "NVIDIA MCP77", 0},
{0x0ad210de, 0x00, "NVIDIA MCP77", 0},
{0x0ad310de, 0x00, "NVIDIA MCP77", 0},
{0x0ad410de, 0x00, "NVIDIA MCP77", 0},
{0x0ad510de, 0x00, "NVIDIA MCP77", 0},
{0x0ad610de, 0x00, "NVIDIA MCP77", 0},
{0x0ad710de, 0x00, "NVIDIA MCP77", 0},
{0x0ad810de, 0x00, "NVIDIA MCP77", 0},
{0x0ad910de, 0x00, "NVIDIA MCP77", 0},
{0x0ada10de, 0x00, "NVIDIA MCP77", 0},
{0x0adb10de, 0x00, "NVIDIA MCP77", 0},
{0x0ab410de, 0x00, "NVIDIA MCP79", 0},
{0x0ab510de, 0x00, "NVIDIA MCP79", 0},
{0x0ab610de, 0x00, "NVIDIA MCP79", 0},
{0x0ab710de, 0x00, "NVIDIA MCP79", 0},
{0x0ab810de, 0x00, "NVIDIA MCP79", 0},
{0x0ab910de, 0x00, "NVIDIA MCP79", 0},
{0x0aba10de, 0x00, "NVIDIA MCP79", 0},
{0x0abb10de, 0x00, "NVIDIA MCP79", 0},
{0x0abc10de, 0x00, "NVIDIA MCP79", 0},
{0x0abd10de, 0x00, "NVIDIA MCP79", 0},
{0x0abe10de, 0x00, "NVIDIA MCP79", 0},
{0x0abf10de, 0x00, "NVIDIA MCP79", 0},
{0x0d8410de, 0x00, "NVIDIA MCP89", 0},
{0x0d8510de, 0x00, "NVIDIA MCP89", 0},
{0x0d8610de, 0x00, "NVIDIA MCP89", 0},
{0x0d8710de, 0x00, "NVIDIA MCP89", 0},
{0x0d8810de, 0x00, "NVIDIA MCP89", 0},
{0x0d8910de, 0x00, "NVIDIA MCP89", 0},
{0x0d8a10de, 0x00, "NVIDIA MCP89", 0},
{0x0d8b10de, 0x00, "NVIDIA MCP89", 0},
{0x0d8c10de, 0x00, "NVIDIA MCP89", 0},
{0x0d8d10de, 0x00, "NVIDIA MCP89", 0},
{0x0d8e10de, 0x00, "NVIDIA MCP89", 0},
{0x0d8f10de, 0x00, "NVIDIA MCP89", 0},
{0x044c10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
{0x044d10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
{0x044e10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
{0x044f10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
{0x045c10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
{0x045d10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
{0x045e10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
{0x045f10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA},
{0x055010de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x055110de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x055210de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x055310de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x055410de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x055510de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x055610de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x055710de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x055810de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x055910de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x055A10de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x055B10de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x058410de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA},
{0x07f010de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
{0x07f110de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
{0x07f210de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
{0x07f310de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
{0x07f410de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
{0x07f510de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
{0x07f610de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
{0x07f710de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
{0x07f810de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
{0x07f910de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
{0x07fa10de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
{0x07fb10de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA},
{0x0ad010de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
{0x0ad110de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
{0x0ad210de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
{0x0ad310de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
{0x0ad410de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
{0x0ad510de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
{0x0ad610de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
{0x0ad710de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
{0x0ad810de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
{0x0ad910de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
{0x0ada10de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
{0x0adb10de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA},
{0x0ab410de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0ab510de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0ab610de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0ab710de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0ab810de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0ab910de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0aba10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0abb10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0abc10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0abd10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0abe10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0abf10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0d8410de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8510de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8610de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8710de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8810de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8910de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8a10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8b10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8c10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8d10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8e10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8f10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x33491106, 0x00, "VIA VT8251", 0},
{0x62871106, 0x00, "VIA VT8251", 0},
{0x11841039, 0x00, "SiS 966", 0},
@ -860,7 +861,14 @@ ahci_ch_attach(device_t dev)
ch->user[i].mode = 0;
ch->user[i].bytecount = 8192;
ch->user[i].tags = ch->numslots;
ch->user[i].caps = 0;
ch->curr[i] = ch->user[i];
if (ch->pm_level) {
ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ |
CTS_SATA_CAPS_H_APST |
CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST;
}
ch->user[i].caps |= CTS_SATA_CAPS_H_DMAAA;
}
rid = ch->unit;
if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@ -1960,7 +1968,8 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et)
et != AHCI_ERR_TIMEOUT)
ahci_rearm_timeout(dev);
/* Start PM timer. */
if (ch->numrslots == 0 && ch->pm_level > 3) {
if (ch->numrslots == 0 && ch->pm_level > 3 &&
(ch->curr[ch->pm_present ? 15 : 0].caps & CTS_SATA_CAPS_D_PMREQ)) {
callout_schedule(&ch->pm_timer,
(ch->pm_level == 4) ? hz / 1000 : hz / 8);
}
@ -2464,6 +2473,8 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
ch->pm_present = cts->xport_specific.sata.pm_present;
if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI)
d->atapi = cts->xport_specific.sata.atapi;
if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
d->caps = cts->xport_specific.sata.caps;
ccb->ccb_h.status = CAM_REQ_CMP;
break;
}
@ -2496,9 +2507,24 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
cts->xport_specific.sata.valid |=
CTS_SATA_VALID_REVISION;
}
cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D;
if (ch->pm_level) {
if (ch->caps & (AHCI_CAP_PSC | AHCI_CAP_SSC))
cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ;
if (ch->caps2 & AHCI_CAP2_APST)
cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_APST;
}
if ((ch->caps & AHCI_CAP_SNCQ) &&
(ch->quirks & AHCI_Q_NOAA) == 0)
cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_DMAAA;
cts->xport_specific.sata.caps &=
ch->user[ccb->ccb_h.target_id].caps;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
} else {
cts->xport_specific.sata.revision = d->revision;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
cts->xport_specific.sata.caps = d->caps;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
}
cts->xport_specific.sata.mode = d->mode;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE;

View File

@ -372,6 +372,7 @@ struct ahci_device {
u_int bytecount;
u_int atapi;
u_int tags;
u_int caps;
};
/* structure describing an ATA channel */

View File

@ -448,6 +448,8 @@ siis_ch_attach(device_t dev)
ch->user[i].bytecount = 8192;
ch->user[i].tags = SIIS_MAX_SLOTS;
ch->curr[i] = ch->user[i];
if (ch->pm_level)
ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ;
}
mtx_init(&ch->mtx, "SIIS channel lock", NULL, MTX_DEF);
rid = ch->unit;
@ -1697,6 +1699,8 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
}
if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS)
d->atapi = cts->xport_specific.sata.atapi;
if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
d->caps = cts->xport_specific.sata.caps;
ccb->ccb_h.status = CAM_REQ_CMP;
break;
}
@ -1729,9 +1733,17 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
cts->xport_specific.sata.valid |=
CTS_SATA_VALID_REVISION;
}
cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D;
if (ch->pm_level)
cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ;
cts->xport_specific.sata.caps &=
ch->user[ccb->ccb_h.target_id].caps;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
} else {
cts->xport_specific.sata.revision = d->revision;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
cts->xport_specific.sata.caps = d->caps;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
}
cts->xport_specific.sata.mode = d->mode;
cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE;

View File

@ -358,6 +358,7 @@ struct siis_device {
u_int bytecount;
u_int atapi;
u_int tags;
u_int caps;
};
/* structure describing an ATA channel */