bin/88634: Add idle and standby commands to atacontrol
Jean-Yves Lefort
jylefort at FreeBSD.org
Mon Nov 7 17:40:12 PST 2005
>Number: 88634
>Category: bin
>Synopsis: Add idle and standby commands to atacontrol
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Tue Nov 08 01:40:10 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Jean-Yves Lefort
>Release: FreeBSD 6.0-RELEASE i386
>Organization:
>Environment:
System: FreeBSD jsite.lefort.net 6.0-RELEASE FreeBSD 6.0-RELEASE #0: Mon Nov 7 19:32:08 CET 2005 jylefort at jsite.lefort.net:/usr/obj/usr/src/sys/JSITE i386
>Description:
Inspired by sysutils/ataidle. Timer calculation taken from NetBSD's atactl.
>How-To-Repeat:
>Fix:
--- atacontrol.8.orig Fri Aug 19 17:54:42 2005
+++ atacontrol.8 Tue Nov 8 01:51:32 2005
@@ -64,6 +64,12 @@
.Ic mode
.Ar device
.Nm
+.Ic idle
+.Ar device Oo Ar seconds Oc
+.Nm
+.Ic standby
+.Ar device Oo Ar seconds Oc
+.Nm
.Ic info
.Ar channel
.Nm
@@ -187,6 +193,20 @@
(alias
.Cm UDMA133 ) .
The device name and manufacture/version strings are shown.
+.It Ic idle
+Place
+.Ar device
+into idle mode. Additionally, if
+.Ar seconds
+are specified, set the idle timer to that number of seconds. A value of
+0 will disable the idle timer.
+.It Ic standby
+Place
+.Ar device
+into standby mode. Additionally, if
+.Ar seconds
+are specified, set the standby timer to that number of seconds. A value of
+0 will disable the standby timer.
.It Ic cap
Show detailed info about the device on
.Ar device .
--- atacontrol.c.orig Sun Aug 7 13:16:58 2005
+++ atacontrol.c Tue Nov 8 02:02:51 2005
@@ -37,6 +37,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <limits.h>
#include <string.h>
#include <sysexits.h>
@@ -48,6 +49,8 @@
void cap_print(struct ata_params *parm);
int ata_cap_print(int fd);
int info_print(int fd, int channel, int prchan);
+int open_device(const char *name);
+void set_power(int fd, const char *seconds, u_int8_t immediate_command, u_int8_t set_command);
const char *
mode2str(int mode)
@@ -108,6 +111,8 @@
" atacontrol rebuild array\n"
" atacontrol status array\n"
" atacontrol mode device [mode]\n"
+ " atacontrol idle device [seconds]\n"
+ " atacontrol standby device [seconds]\n"
" atacontrol cap device\n"
);
exit(EX_USAGE);
@@ -287,6 +292,68 @@
}
int
+open_device(const char *name)
+{
+ int disk;
+ int fd;
+ char device[64];
+
+ if (!(sscanf(name, "ad%d", &disk) == 1 ||
+ sscanf(name, "acd%d", &disk) == 1 ||
+ sscanf(name, "afd%d", &disk) == 1 ||
+ sscanf(name, "ast%d", &disk) == 1)) {
+ fprintf(stderr, "atacontrol: Invalid device %s\n",
+ name);
+ exit(EX_USAGE);
+ }
+
+ sprintf(device, "/dev/%s", name);
+ if ((fd = open(device, O_RDONLY)) < 0)
+ err(1, "device not found");
+
+ return fd;
+}
+
+void
+set_power(int fd, const char *seconds, u_int8_t immediate_command, u_int8_t set_command)
+{
+ struct ata_ioc_request request;
+
+ memset(&request, 0, sizeof(request));
+ request.flags = ATA_CMD_CONTROL;
+ request.timeout = 1000;
+ if (seconds) {
+ unsigned long idle;
+ char *end;
+
+ idle = strtoul(seconds, &end, 0);
+
+ if (*end != '\0') {
+ fprintf(stderr, "atacontrol: Invalid idle time %s\n", seconds);
+ exit(EX_USAGE);
+ }
+ if (idle > 19800) {
+ fprintf(stderr, "atacontrol: Idle time has a maximum value of 5.5 hours\n");
+ exit(EX_USAGE);
+ }
+ if (idle != 0 && idle < 5) {
+ fprintf(stderr, "atacontrol: Idle time must be at least 5 seconds\n");
+ exit(EX_USAGE);
+ }
+
+ request.u.ata.command = set_command;
+ if (idle <= 240 * 5)
+ request.u.ata.count = idle / 5;
+ else
+ request.u.ata.count = idle / (30 * 60) + 240;
+ } else
+ request.u.ata.command = immediate_command;
+
+ if (ioctl(fd, IOCATAREQUEST, &request) < 0)
+ err(1, "ioctl(IOCATAREQUEST)");
+}
+
+int
main(int argc, char **argv)
{
int fd;
@@ -295,20 +362,8 @@
usage();
if (!strcmp(argv[1], "mode") && (argc == 3 || argc == 4)) {
- int disk, mode;
- char device[64];
-
- if (!(sscanf(argv[2], "ad%d", &disk) == 1 ||
- sscanf(argv[2], "acd%d", &disk) == 1 ||
- sscanf(argv[2], "afd%d", &disk) == 1 ||
- sscanf(argv[2], "ast%d", &disk) == 1)) {
- fprintf(stderr, "atacontrol: Invalid device %s\n",
- argv[2]);
- exit(EX_USAGE);
- }
- sprintf(device, "/dev/%s", argv[2]);
- if ((fd = open(device, O_RDONLY)) < 0)
- err(1, "device not found");
+ int mode;
+ fd = open_device(argv[2]);
if (argc == 4) {
mode = str2mode(argv[3]);
if (ioctl(fd, IOCATASMODE, &mode) < 0)
@@ -321,21 +376,20 @@
}
exit(EX_OK);
}
+ if (!strcmp(argv[1], "idle") && (argc == 3 || argc == 4)) {
+ fd = open_device(argv[2]);
+ set_power(fd, argc == 4 ? argv[3] : NULL,
+ ATA_IDLE_IMMEDIATE, ATA_IDLE_CMD);
+ exit(EX_OK);
+ }
+ if (!strcmp(argv[1], "standby") && (argc == 3 || argc == 4)) {
+ fd = open_device(argv[2]);
+ set_power(fd, argc == 4 ? argv[3] : NULL,
+ ATA_STANDBY_IMMEDIATE, ATA_STANDBY_CMD);
+ exit(EX_OK);
+ }
if (!strcmp(argv[1], "cap") && argc == 3) {
- int disk;
- char device[64];
-
- if (!(sscanf(argv[2], "ad%d", &disk) == 1 ||
- sscanf(argv[2], "acd%d", &disk) == 1 ||
- sscanf(argv[2], "afd%d", &disk) == 1 ||
- sscanf(argv[2], "ast%d", &disk) == 1)) {
- fprintf(stderr, "atacontrol: Invalid device %s\n",
- argv[2]);
- exit(EX_USAGE);
- }
- sprintf(device, "/dev/%s", argv[2]);
- if ((fd = open(device, O_RDONLY)) < 0)
- err(1, "device not found");
+ fd = open_device(argv[2]);
ata_cap_print(fd);
exit(EX_OK);
}
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list