svn commit: r199079 - head/sbin/camcontrol

Alexander Motin mav at FreeBSD.org
Mon Nov 9 11:39:51 UTC 2009


Author: mav
Date: Mon Nov  9 11:39:51 2009
New Revision: 199079
URL: http://svn.freebsd.org/changeset/base/199079

Log:
  Add support for ATA Power Management.

Modified:
  head/sbin/camcontrol/camcontrol.8
  head/sbin/camcontrol/camcontrol.c

Modified: head/sbin/camcontrol/camcontrol.8
==============================================================================
--- head/sbin/camcontrol/camcontrol.8	Mon Nov  9 11:32:34 2009	(r199078)
+++ head/sbin/camcontrol/camcontrol.8	Mon Nov  9 11:39:51 2009	(r199079)
@@ -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

Modified: head/sbin/camcontrol/camcontrol.c
==============================================================================
--- head/sbin/camcontrol/camcontrol.c	Mon Nov  9 11:32:34 2009	(r199078)
+++ head/sbin/camcontrol/camcontrol.c	Mon Nov  9 11:39:51 2009	(r199079)
@@ -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_dev
 			  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);


More information about the svn-src-head mailing list