aboutsummaryrefslogtreecommitdiff
path: root/sys/cam/ata/ata_pmp.c
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2010-05-02 12:07:47 +0000
committerAlexander Motin <mav@FreeBSD.org>2010-05-02 12:07:47 +0000
commitda6808c111755c13b9444a9838ce2415644a5d3f (patch)
treeb5c5b295203637665fed48360b91930d6b26ea37 /sys/cam/ata/ata_pmp.c
parentf930c0db49a2049e7b92ec49b7736546839ed0a3 (diff)
downloadsrc-da6808c111755c13b9444a9838ce2415644a5d3f.tar.gz
src-da6808c111755c13b9444a9838ce2415644a5d3f.zip
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.
Notes
Notes: svn path=/head/; revision=207499
Diffstat (limited to 'sys/cam/ata/ata_pmp.c')
-rw-r--r--sys/cam/ata/ata_pmp.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/sys/cam/ata/ata_pmp.c b/sys/cam/ata/ata_pmp.c
index b60a4a7596b1..0835a2bf228f 100644
--- a/sys/cam/ata/ata_pmp.c
+++ b/sys/cam/ata/ata_pmp.c
@@ -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);
}