Date: Tue, 8 Nov 2005 02:31:20 +0100 (CET) From: Jean-Yves Lefort <jylefort@FreeBSD.org> To: FreeBSD-gnats-submit@FreeBSD.org Cc: sos@FreeBSD.org Subject: bin/88634: Add idle and standby commands to atacontrol Message-ID: <20051108013120.DB8C9C0FF@jsite.lefort.net> Resent-Message-ID: <200511080140.jA81eBLm081184@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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@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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20051108013120.DB8C9C0FF>