summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2009-11-09 11:39:51 +0000
committermav <mav@FreeBSD.org>2009-11-09 11:39:51 +0000
commit1c736394953a2407ed4f4ca6064430856a173c13 (patch)
treee9adde3c74d2d2fa759bf5657584ddbf26f2f314 /sbin
parent595994ce84300f35af6278eae810560129f1b450 (diff)
downloadFreeBSD-src-1c736394953a2407ed4f4ca6064430856a173c13.zip
FreeBSD-src-1c736394953a2407ed4f4ca6064430856a173c13.tar.gz
Add support for ATA Power Management.
Diffstat (limited to 'sbin')
-rw-r--r--sbin/camcontrol/camcontrol.825
-rw-r--r--sbin/camcontrol/camcontrol.c112
2 files changed, 134 insertions, 3 deletions
diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8
index b987cad..a0871ac 100644
--- a/sbin/camcontrol/camcontrol.8
+++ b/sbin/camcontrol/camcontrol.8
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 4, 2009
+.Dd November 9, 2009
.Dt CAMCONTROL 8
.Os
.Sh NAME
@@ -165,6 +165,20 @@
.Op Fl w
.Op Fl y
.Nm
+.Ic idle
+.Op device id
+.Op generic args
+.Op Fl t Ar time
+.Nm
+.Ic standby
+.Op device id
+.Op generic args
+.Op Fl t Ar time
+.Nm
+.Ic sleep
+.Op device id
+.Op generic args
+.Nm
.Ic help
.Sh DESCRIPTION
The
@@ -821,6 +835,15 @@ The user
will not be asked about the timeout if a timeout is specified on the
command line.
.El
+.It Ic idle
+Put ATA device into IDLE state. Optional parameter specifies automatic
+idle timer value in seconds.
+.It Ic standby
+Put ATA device into STANDBY state. Optional parameter specifies automatic
+standby timer value in seconds.
+.It Ic sleep
+Put ATA device into SLEEP state. Note that the only way get device out of
+this state may be reset.
.It Ic help
Print out verbose usage information.
.El
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
index 728b691..1638a5d 100644
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -74,7 +74,10 @@ typedef enum {
CAM_CMD_DETACH = 0x00000010,
CAM_CMD_REPORTLUNS = 0x00000011,
CAM_CMD_READCAP = 0x00000012,
- CAM_CMD_IDENTIFY = 0x00000013
+ CAM_CMD_IDENTIFY = 0x00000013,
+ CAM_CMD_IDLE = 0x00000014,
+ CAM_CMD_STANDBY = 0x00000015,
+ CAM_CMD_SLEEP = 0x00000016
} cam_cmdmask;
typedef enum {
@@ -154,6 +157,9 @@ struct camcontrol_opts option_table[] = {
{"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
{"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXc"},
{"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"},
+ {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"},
+ {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"},
+ {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""},
#endif /* MINIMALISTIC */
{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
@@ -217,6 +223,8 @@ static int scsireportluns(struct cam_device *device, int argc, char **argv,
char *combinedopt, int retry_count, int timeout);
static int scsireadcapacity(struct cam_device *device, int argc, char **argv,
char *combinedopt, int retry_count, int timeout);
+static int atapm(struct cam_device *device, int argc, char **argv,
+ char *combinedopt, int retry_count, int timeout);
#endif /* MINIMALISTIC */
camcontrol_optret
@@ -4128,6 +4136,91 @@ bailout:
return (retval);
}
+static int
+atapm(struct cam_device *device, int argc, char **argv,
+ char *combinedopt, int retry_count, int timeout)
+{
+ union ccb *ccb;
+ int retval = 0;
+ int t = -1;
+ char c;
+ u_char cmd, sc;
+
+ ccb = cam_getccb(device);
+
+ if (ccb == NULL) {
+ warnx("%s: error allocating ccb", __func__);
+ return (1);
+ }
+
+ while ((c = getopt(argc, argv, combinedopt)) != -1) {
+ switch (c) {
+ case 't':
+ t = atoi(optarg);
+ break;
+ default:
+ break;
+ }
+ }
+ if (strcmp(argv[1], "idle") == 0) {
+ if (t == -1)
+ cmd = ATA_IDLE_IMMEDIATE;
+ else
+ cmd = ATA_IDLE_CMD;
+ } else if (strcmp(argv[1], "standby") == 0) {
+ if (t == -1)
+ cmd = ATA_STANDBY_IMMEDIATE;
+ else
+ cmd = ATA_STANDBY_CMD;
+ } else {
+ cmd = ATA_SLEEP;
+ t = -1;
+ }
+ if (t < 0)
+ sc = 0;
+ else if (t <= (240 * 5))
+ sc = t / 5;
+ else if (t <= (11 * 30 * 60))
+ sc = t / (30 * 60) + 241;
+ else
+ sc = 253;
+ cam_fill_ataio(&ccb->ataio,
+ retry_count,
+ NULL,
+ /*flags*/CAM_DIR_NONE,
+ MSG_SIMPLE_Q_TAG,
+ /*data_ptr*/NULL,
+ /*dxfer_len*/0,
+ timeout ? timeout : 30 * 1000);
+ ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc);
+
+ /* Disable freezing the device queue */
+ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+
+ if (arglist & CAM_ARG_ERR_RECOVER)
+ ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
+
+ if (cam_send_ccb(device, ccb) < 0) {
+ warn("error sending command");
+
+ if (arglist & CAM_ARG_VERBOSE)
+ cam_error_print(device, ccb, CAM_ESF_ALL,
+ CAM_EPF_ALL, stderr);
+
+ retval = 1;
+ goto bailout;
+ }
+
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
+ retval = 1;
+ goto bailout;
+ }
+bailout:
+ cam_freeccb(ccb);
+ return (retval);
+}
+
#endif /* MINIMALISTIC */
void
@@ -4166,6 +4259,9 @@ usage(int verbose)
" [-R syncrate][-v][-T <enable|disable>]\n"
" [-U][-W bus_width]\n"
" camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n"
+" camcontrol idle [dev_id][generic args][-t time]\n"
+" camcontrol standby [dev_id][generic args][-t time]\n"
+" camcontrol sleep [dev_id][generic args]\n"
#endif /* MINIMALISTIC */
" camcontrol help\n");
if (!verbose)
@@ -4193,6 +4289,9 @@ usage(int verbose)
"tags report or set the number of transaction slots for a device\n"
"negotiate report or set device negotiation parameters\n"
"format send the SCSI FORMAT UNIT command to the named device\n"
+"idle send the ATA IDLE command to the named device\n"
+"standby send the ATA STANDBY command to the named device\n"
+"sleep send the ATA SLEEP command to the named device\n"
"help this message\n"
"Device Identifiers:\n"
"bus:target specify the bus and target, lun defaults to 0\n"
@@ -4259,7 +4358,9 @@ usage(int verbose)
"-q be quiet, don't print status messages\n"
"-r run in report only mode\n"
"-w don't send immediate format command\n"
-"-y don't ask any questions\n");
+"-y don't ask any questions\n"
+"idle/standby arguments:\n"
+"-t <arg> number of seconds before respective state.\n");
#endif /* MINIMALISTIC */
}
@@ -4555,6 +4656,13 @@ main(int argc, char **argv)
combinedopt, retry_count,
timeout);
break;
+ case CAM_CMD_IDLE:
+ case CAM_CMD_STANDBY:
+ case CAM_CMD_SLEEP:
+ error = atapm(cam_dev, argc, argv,
+ combinedopt, retry_count,
+ timeout);
+ break;
#endif /* MINIMALISTIC */
case CAM_CMD_USAGE:
usage(1);
OpenPOWER on IntegriCloud