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