Subject: Advanced power management in atactl(8)
To: None <netbsd-users@netbsd.org>
From: Marco Trillo <marcotrillo@gmail.com>
List: netbsd-users
Date: 11/18/2007 14:59:37
Hi all,

I have added support for controlling the 'advanced power management'
feature of ATA drives to my local version of the atactl(8) utility.

I use this feature on my laptop; when I use the laptop on a stable
surface and connected to the AC adapter, I do not want the HD drive to be
constantly loading its heads (causing a click noise and incrementing the
'load cycle count' parameters, which is limited to a certain number of cycles
before possibly causing problems).

Are you interested in this feature? I have attached a patch against netbsd-4
(which is the branch that I'm running).

I have documented this on the manual page [I hope that Gmail does not botch
the formatting], as seen below:

ATACTL(8)               NetBSD System Manager's Manual               ATACTL(8)

[...]

     apm [disable | set #]
                Controls the Advanced Power Management feature of the speci-
                fied device.  Advanced Power Management is an optional feature
                used to specify a power management level to balance between
                device performance and power consumption.

                disable         Disable the Advanced Power Management.

                set #           Enable the Advanced Power Management feature
                                and set its level to the value #, where # is
                                an integer within the scale 0-253; being 0 the
                                mode with the lowest power consumption (and
                                thus the worse performance) and 253 the mode
                                which provides the better performance at a
                                cost of more power consumption.

                                It should be noted that the effect of the
                                value need not be continous. For example, a
                                device might provide only two modes: one from
                                0 to 126 and other from 127 to 253. Per the
                                specification, values of 127 and higher do not
                                permit the device to spin down to save power.

[...]

NetBSD 4.0_RC3                  April 12, 2005                  NetBSD 4.0_RC3

The patch is trivial:

Index: sys/dev/ata/atareg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ata/atareg.h,v
retrieving revision 1.29
diff -u -r1.29 atareg.h
--- sys/dev/ata/atareg.h	16 Nov 2006 01:32:47 -0000	1.29
+++ sys/dev/ata/atareg.h	18 Nov 2007 13:33:51 -0000
@@ -194,9 +194,11 @@
 #endif /* _KERNEL */

 /* Subcommands for SET_FEATURES (features register) */
+#define	WDSF_8BIT_PIO_EN	0x01
 #define	WDSF_WRITE_CACHE_EN	0x02
 #define	WDSF_SET_MODE		0x03
 #define	WDSF_REASSIGN_EN	0x04
+#define	WDSF_APM_EN		0x05
 #define	WDSF_RETRY_DS		0x33
 #define	WDSF_SET_CACHE_SGMT	0x54
 #define	WDSF_READAHEAD_DS	0x55
@@ -204,6 +206,7 @@
 #define	WDSF_ECC_DS		0x77
 #define	WDSF_WRITE_CACHE_DS	0x82
 #define	WDSF_REASSIGN_DS	0x84
+#define	WDSF_APM_DS		0x85
 #define	WDSF_ECC_EN		0x88
 #define	WDSF_RETRY_EN		0x99
 #define	WDSF_SET_CURRENT	0x9a
Index: sbin/atactl/atactl.c
===================================================================
RCS file: /cvsroot/src/sbin/atactl/atactl.c,v
retrieving revision 1.45
diff -u -r1.45 atactl.c
--- sbin/atactl/atactl.c	16 Oct 2006 00:45:19 -0000	1.45
+++ sbin/atactl/atactl.c	18 Nov 2007 13:33:52 -0000
@@ -131,6 +131,7 @@
 void	device_identify(int, char *[]);
 void	device_setidle(int, char *[]);
 void	device_idle(int, char *[]);
+void	device_apm(int, char *[]);
 void	device_checkpower(int, char *[]);
 void	device_smart(int, char *[]);
 void	device_security(int, char *[]);
@@ -140,6 +141,7 @@
 struct command device_commands[] = {
 	{ "identify",	"",			device_identify },
 	{ "setidle",	"idle-timer",		device_setidle },
+	{ "apm",	"disable|set #",	device_apm },
 	{ "setstandby",	"standby-timer",	device_setidle },
 	{ "idle",	"",			device_idle },
 	{ "standby",	"",			device_idle },
@@ -925,7 +927,6 @@
  *
  * issue the IDLE IMMEDIATE command to the drive
  */
-
 void
 device_idle(int argc, char *argv[])
 {
@@ -952,6 +953,38 @@
 }

 /*
+ * device apm:
+ *
+ * enable/disable/control the APM feature of the drive
+ */
+void
+device_apm(int argc, char *argv[])
+{
+	struct atareq req;
+	long l;
+
+	memset(&req, 0, sizeof(req));
+	if (argc >= 1) {
+		req.command = SET_FEATURES;
+		req.timeout = 1000;
+		
+		if (strcmp(argv[0], "disable") == 0)
+			req.features = WDSF_APM_DS;
+		else if (strcmp(argv[0], "set") == 0 && argc >= 2 &&
+		         (l = strtol(argv[1], NULL, 0)) >= 0 && l <= 253) {
+			
+			req.features = WDSF_APM_EN;
+			req.sec_count = l + 1;
+		} else
+			usage();
+	} else
+		usage();
+	
+	ata_command(&req);
+}
+	
+
+/*
  * Set the idle timer on the disk.  Set it for either idle mode or
  * standby mode, depending on how we were invoked.
  */
Index: sbin/atactl/atactl.8
===================================================================
RCS file: /cvsroot/src/sbin/atactl/atactl.8,v
retrieving revision 1.21
diff -u -r1.21 atactl.8
--- sbin/atactl/atactl.8	12 Apr 2005 11:50:29 -0000	1.21
+++ sbin/atactl/atactl.8	18 Nov 2007 13:33:52 -0000
@@ -91,6 +91,21 @@
 .It Cm checkpower
 Will print out if the device is in Active, Idle, or Standby power
 management mode.
+.It Cm apm Bq Ar disable | set #
+Controls the Advanced Power Management feature of the specified device.
+Advanced Power Management is an optional feature used to specify a
power management
+level to balance between device performance and power consumption.
+.Bl -tag -width selftestXlogXX
+.It Ar disable
+Disable the Advanced Power Management.
+.It Ar set #
+Enable the Advanced Power Management feature and set its level to the value #,
+where # is an integer within the scale 0-253; being 0 the mode with
the lowest power
+consumption (and thus the worse performance) and 253 the mode which
provides the
+better performance at a cost of more power consumption.
+.Pp
+It should be noted that the effect of the value need not be
continous. For example, a device might provide only two modes: one
from 0 to 126 and other from 127 to 253. Per the specification, values
of 127 and higher do not permit the device to spin down to save power.
+.El
 .It Cm smart Bq Ar enable | disable | status | offline # | error-log
| selftest-log
 Controls SMART feature set of the specified device.
 SMART stands for Self-Monitoring, Analysis, and Reporting Technology.
-- 

     -Marco