From owner-freebsd-bugs@FreeBSD.ORG Tue Nov 8 01:40:12 2005 Return-Path: X-Original-To: freebsd-bugs@hub.freebsd.org Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1696116A41F for ; Tue, 8 Nov 2005 01:40:12 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 7889943D4C for ; Tue, 8 Nov 2005 01:40:11 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.3/8.13.3) with ESMTP id jA81eB51081185 for ; Tue, 8 Nov 2005 01:40:11 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.3/8.13.1/Submit) id jA81eBLm081184; Tue, 8 Nov 2005 01:40:11 GMT (envelope-from gnats) Resent-Date: Tue, 8 Nov 2005 01:40:11 GMT Resent-Message-Id: <200511080140.jA81eBLm081184@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Jean-Yves Lefort Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E2FB616A41F; Tue, 8 Nov 2005 01:31:23 +0000 (GMT) (envelope-from jylefort@brutele.be) Received: from 212.68.244.220.brutele.be (212.68.244.220.brutele.be [212.68.244.220]) by mx1.FreeBSD.org (Postfix) with ESMTP id C519143D45; Tue, 8 Nov 2005 01:31:22 +0000 (GMT) (envelope-from jylefort@brutele.be) Received: from jsite.lefort.net (jsite.lefort.net [192.168.1.2]) by gateway.lefort.net (Postfix) with ESMTP id F073854FB; Tue, 8 Nov 2005 02:31:20 +0100 (CET) Received: by jsite.lefort.net (Postfix, from userid 1000) id DB8C9C0FF; Tue, 8 Nov 2005 02:31:20 +0100 (CET) Message-Id: <20051108013120.DB8C9C0FF@jsite.lefort.net> Date: Tue, 8 Nov 2005 02:31:20 +0100 (CET) From: Jean-Yves Lefort To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Cc: sos@FreeBSD.org Subject: bin/88634: Add idle and standby commands to atacontrol X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Jean-Yves Lefort List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Nov 2005 01:40:12 -0000 >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 #include #include +#include #include #include @@ -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: