From owner-svn-src-head@FreeBSD.ORG Mon Nov 9 11:39:51 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 783D71065676; Mon, 9 Nov 2009 11:39:51 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 673928FC18; Mon, 9 Nov 2009 11:39:51 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nA9BdpY1019883; Mon, 9 Nov 2009 11:39:51 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nA9BdpAU019880; Mon, 9 Nov 2009 11:39:51 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <200911091139.nA9BdpAU019880@svn.freebsd.org> From: Alexander Motin Date: Mon, 9 Nov 2009 11:39:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r199079 - head/sbin/camcontrol X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Nov 2009 11:39:51 -0000 Author: mav Date: Mon Nov 9 11:39:51 2009 New Revision: 199079 URL: http://svn.freebsd.org/changeset/base/199079 Log: Add support for ATA Power Management. Modified: head/sbin/camcontrol/camcontrol.8 head/sbin/camcontrol/camcontrol.c Modified: head/sbin/camcontrol/camcontrol.8 ============================================================================== --- head/sbin/camcontrol/camcontrol.8 Mon Nov 9 11:32:34 2009 (r199078) +++ head/sbin/camcontrol/camcontrol.8 Mon Nov 9 11:39:51 2009 (r199079) @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 4, 2009 +.Dd November 9, 2009 .Dt CAMCONTROL 8 .Os .Sh NAME @@ -165,6 +165,20 @@ .Op Fl w .Op Fl y .Nm +.Ic idle +.Op device id +.Op generic args +.Op Fl t Ar time +.Nm +.Ic standby +.Op device id +.Op generic args +.Op Fl t Ar time +.Nm +.Ic sleep +.Op device id +.Op generic args +.Nm .Ic help .Sh DESCRIPTION The @@ -821,6 +835,15 @@ The user will not be asked about the timeout if a timeout is specified on the command line. .El +.It Ic idle +Put ATA device into IDLE state. Optional parameter specifies automatic +idle timer value in seconds. +.It Ic standby +Put ATA device into STANDBY state. Optional parameter specifies automatic +standby timer value in seconds. +.It Ic sleep +Put ATA device into SLEEP state. Note that the only way get device out of +this state may be reset. .It Ic help Print out verbose usage information. .El Modified: head/sbin/camcontrol/camcontrol.c ============================================================================== --- head/sbin/camcontrol/camcontrol.c Mon Nov 9 11:32:34 2009 (r199078) +++ head/sbin/camcontrol/camcontrol.c Mon Nov 9 11:39:51 2009 (r199079) @@ -74,7 +74,10 @@ typedef enum { CAM_CMD_DETACH = 0x00000010, CAM_CMD_REPORTLUNS = 0x00000011, CAM_CMD_READCAP = 0x00000012, - CAM_CMD_IDENTIFY = 0x00000013 + CAM_CMD_IDENTIFY = 0x00000013, + CAM_CMD_IDLE = 0x00000014, + CAM_CMD_STANDBY = 0x00000015, + CAM_CMD_SLEEP = 0x00000016 } cam_cmdmask; typedef enum { @@ -154,6 +157,9 @@ struct camcontrol_opts option_table[] = {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts}, {"debug", CAM_CMD_DEBUG, CAM_ARG_NONE, "IPTSXc"}, {"format", CAM_CMD_FORMAT, CAM_ARG_NONE, "qrwy"}, + {"idle", CAM_CMD_IDLE, CAM_ARG_NONE, "t:"}, + {"standby", CAM_CMD_STANDBY, CAM_ARG_NONE, "t:"}, + {"sleep", CAM_CMD_SLEEP, CAM_ARG_NONE, ""}, #endif /* MINIMALISTIC */ {"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, {"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL}, @@ -217,6 +223,8 @@ static int scsireportluns(struct cam_dev char *combinedopt, int retry_count, int timeout); static int scsireadcapacity(struct cam_device *device, int argc, char **argv, char *combinedopt, int retry_count, int timeout); +static int atapm(struct cam_device *device, int argc, char **argv, + char *combinedopt, int retry_count, int timeout); #endif /* MINIMALISTIC */ camcontrol_optret @@ -4128,6 +4136,91 @@ bailout: return (retval); } +static int +atapm(struct cam_device *device, int argc, char **argv, + char *combinedopt, int retry_count, int timeout) +{ + union ccb *ccb; + int retval = 0; + int t = -1; + char c; + u_char cmd, sc; + + ccb = cam_getccb(device); + + if (ccb == NULL) { + warnx("%s: error allocating ccb", __func__); + return (1); + } + + while ((c = getopt(argc, argv, combinedopt)) != -1) { + switch (c) { + case 't': + t = atoi(optarg); + break; + default: + break; + } + } + if (strcmp(argv[1], "idle") == 0) { + if (t == -1) + cmd = ATA_IDLE_IMMEDIATE; + else + cmd = ATA_IDLE_CMD; + } else if (strcmp(argv[1], "standby") == 0) { + if (t == -1) + cmd = ATA_STANDBY_IMMEDIATE; + else + cmd = ATA_STANDBY_CMD; + } else { + cmd = ATA_SLEEP; + t = -1; + } + if (t < 0) + sc = 0; + else if (t <= (240 * 5)) + sc = t / 5; + else if (t <= (11 * 30 * 60)) + sc = t / (30 * 60) + 241; + else + sc = 253; + cam_fill_ataio(&ccb->ataio, + retry_count, + NULL, + /*flags*/CAM_DIR_NONE, + MSG_SIMPLE_Q_TAG, + /*data_ptr*/NULL, + /*dxfer_len*/0, + timeout ? timeout : 30 * 1000); + ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, sc); + + /* Disable freezing the device queue */ + ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; + + if (arglist & CAM_ARG_ERR_RECOVER) + ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; + + if (cam_send_ccb(device, ccb) < 0) { + warn("error sending command"); + + if (arglist & CAM_ARG_VERBOSE) + cam_error_print(device, ccb, CAM_ESF_ALL, + CAM_EPF_ALL, stderr); + + retval = 1; + goto bailout; + } + + if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { + cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr); + retval = 1; + goto bailout; + } +bailout: + cam_freeccb(ccb); + return (retval); +} + #endif /* MINIMALISTIC */ void @@ -4166,6 +4259,9 @@ usage(int verbose) " [-R syncrate][-v][-T ]\n" " [-U][-W bus_width]\n" " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n" +" camcontrol idle [dev_id][generic args][-t time]\n" +" camcontrol standby [dev_id][generic args][-t time]\n" +" camcontrol sleep [dev_id][generic args]\n" #endif /* MINIMALISTIC */ " camcontrol help\n"); if (!verbose) @@ -4193,6 +4289,9 @@ usage(int verbose) "tags report or set the number of transaction slots for a device\n" "negotiate report or set device negotiation parameters\n" "format send the SCSI FORMAT UNIT command to the named device\n" +"idle send the ATA IDLE command to the named device\n" +"standby send the ATA STANDBY command to the named device\n" +"sleep send the ATA SLEEP command to the named device\n" "help this message\n" "Device Identifiers:\n" "bus:target specify the bus and target, lun defaults to 0\n" @@ -4259,7 +4358,9 @@ usage(int verbose) "-q be quiet, don't print status messages\n" "-r run in report only mode\n" "-w don't send immediate format command\n" -"-y don't ask any questions\n"); +"-y don't ask any questions\n" +"idle/standby arguments:\n" +"-t number of seconds before respective state.\n"); #endif /* MINIMALISTIC */ } @@ -4555,6 +4656,13 @@ main(int argc, char **argv) combinedopt, retry_count, timeout); break; + case CAM_CMD_IDLE: + case CAM_CMD_STANDBY: + case CAM_CMD_SLEEP: + error = atapm(cam_dev, argc, argv, + combinedopt, retry_count, + timeout); + break; #endif /* MINIMALISTIC */ case CAM_CMD_USAGE: usage(1);