Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37545777
en ru br
Репозитории ALT
S:2.5-alt1.qa1
5.1: 0.9-alt2
4.1: 0.9-alt2
4.0: 0.9-alt2
3.0: 0.6-alt1
www.altlinux.org/Changes

Группа :: Система/Ядро и оборудование
Пакет: ataidle

 Главная   Изменения   Спек   Патчи   Исходники   Загрузить   Gear   Bugs and FR  Repocop 

ataidle-2.5/000075500000000000000000000000001213266322700127655ustar00rootroot00000000000000ataidle-2.5/COPYING000064400000000000000000000026031213266322700140210ustar00rootroot00000000000000Copyright 2004-2010 Bruce Cran <bruce@cran.org.uk>. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ataidle-2.5/Changelog000064400000000000000000000055631213266322700146100ustar00rootroot00000000000000Thu Jan 1 01:25 2004 brucec
* released 0.01

Fri Jan 2 04:20 2004 brucec
* released 0.02

remove automake/autoconf junk,
tidy code.

Sun Jan 11 12:46 2004 brucec
* released 20040111
added power management and acoustic
level features, and tidied more code

Sun Jan 11 19:50 2004 brucec
* released 0.3
added support for listing installed
devices, and getting information about
a device.

Tue Jan 27 23:05 2004 brucec
* added support for immediately
transitioning to idle and standby
power saving modes

Thu Jan 29 20:30 2004 brucec
* More information is now
reported when no parameters
are given.

Tue Feb 03 23:45 2004 brucec
* Added drive reinitialisation
support following AAM or APM settings.
This fixes the case where settings are
not activated. Also added documentation
about AAM and APM, and now scale AAM from
1-127, instead of 127-254

Sat Feb 07 21:48 2004 brucec
* Removed drive reinitialization, turns out
it isn't needed - atacontrol doesn't see new
settings, but 'ataidle <chan> <dev>' does, and
new settings are audibly active. Add '0'
value for APM and AAM which disables drive
management for said feature.

Sun Feb 08 21:32 2004 brucec
* Ported to Linux, cleaned up lots of code,
split into OS-dependant/independant code,
added my own structures to use in preference
to OS-supplied ones.

Tue June 29 23:40 2004 brucec
* Fixed a uninitialized variable which showed up
due to a problem with the FreeBSD ATA driver
returning an error code for ATA_GETMAXCHAN.
At the same time, add return code checking for
all malloc calls, and handle appropriately

Sun July 18 19:48 2004 brucec
* Fixed command-line handling to make it work
on amd64 platform. Also fixed typo in freebsd
code.

Mon Aug 09 11:00 2004 brucec
* Miscellaneous bug-fixes to prevent crashes
under unusual situations

Tue Jan 11 18:34 2005 brucec
* Merged the types fix from FreeBSD ports fixes.
Added LSB->MSB conversions so it now works
properly on SPARC64 systems too

Fri Oct 15 00:57 2005 brucec
* Added code to support FreeBSD 6 and newer,
by renaming freebsd directory to freebsd5
and adding freebsd 6+ code in freebsd
directory.

Thu May 17 21:02 2007 brucec
* Added support to put drive into sleep mode
Build system now uses a single Makefile

Wed May 30 23:00 2007 brucec
* Removed support for FreeBSD 5
Changed parameters so device is specified by
entry in /dev

Fri Jan 04 23:12 2008 brucec
* Removed device listing option and notes about
meaning of ATA, AAM and SMART.
Completed code changes to support specifying
device entry in /dev.

Sat Aug 30 02:55 2008 brucec
* Fixed endian issue. ataidle now runs correctly
on FreeBSD/powerpc.

Sun Sep 15 01:44 2008 brucec
* Cleanup. Make function static where possible.

Tue Oct 02 19:00 2010 brucec
* Added support for ATA disks using ATA_CAM
and ahci(4) in FreeBSD.
ataidle-2.5/INSTALL000064400000000000000000000004741213266322700140230ustar00rootroot00000000000000To install ATAidle, run 'make' to build it, followed by 'make install' to
install the binary into /usr/local/sbin and install the man page into
/usr/local/man/man8. If you later want to remove ataidle, simply run
'make uninstall'.

Alternatively, the binary can be copied and run from a more convenient
location.
ataidle-2.5/Makefile000064400000000000000000000024661213266322700144350ustar00rootroot00000000000000PREFIX = /usr/local
CC ?= gcc
LD ?= ld
CFLAGS += -Wall -pedantic -std=c99
LIBS = -lm
SOURCES = ataidle.c
MAN = ataidle.8
PROG = ataidle
MAINTAINER = Bruce Cran <bruce@cran.org.uk>
OS:sh = uname -s
OS ?= $(shell uname -s)
REV:sh = uname -r | head -c 1

all: ataidle

ataidle: ataidle.o util.o main.o
@if [ "$(OS)" = FreeBSD ]; then \
$(CC) $(CFLAGS) $(LIBS) -lcam -o ataidle main.o ataidle.o util.o; \
else \
$(CC) $(CFLAGS) $(LIBS) -o ataidle main.o ataidle.o util.o; \
fi

main.o: main.c mi/atagen.h
$(CC) $(CFLAGS) -c main.c

ataidle.o: linux/ataidle.c freebsd/ataidle.c mi/atagen.h
@if [ "$(OS)" = Linux ]; then \
$(CC) $(CFLAGS) -c linux/ataidle.c; \
elif [ "$(OS)" = FreeBSD ]; then \
$(CC) $(CFLAGS) -c freebsd/ataidle.c; \
fi

util.o: mi/util.c mi/atagen.h
$(CC) $(CFLAGS) -c mi/util.c

install: ataidle ataidle.8 freebsd/ataidle_rc
install $(PROG) $(PREFIX)/sbin

if [ "$(OS)" = Linux ]; then \
if [ ! -d $(PREFIX)/share/man/man8 ]; then \
mkdir -p $(PREFIX)/share/man/man8; \
fi; \
install $(MAN) $(PREFIX)/share/man/man8; \
else \
install $(MAN) $(PREFIX)/man/man8; \
install freebsd/ataidle_rc $(PREFIX)/etc/rc.d/ataidle; \
sed -I '' s:%%PREFIX%%:$(PREFIX):g $(PREFIX)/etc/rc.d/ataidle; \
fi

uninstall:
rm $(PREFIX)/sbin/$(PROG)
rm $(PREFIX)/man/man8/$(MAN)

clean:
rm -f *.o $(PROG)
ataidle-2.5/README000064400000000000000000000020031213266322700136400ustar00rootroot00000000000000ATAidle sets the standby timer on ATA hard drives so they spin down when the
period of inactivity has expired. To use it you must be running FreeBSD 6.2
or newer - alternatively, you can also run it on Linux - it's been tested with
kernel 2.6.1, but should work with any recent kernel.

Supplying a device name without any parameters will display
information about the specified device.

Notes on Auto Acoustic Management (AAM) and APM support

Meaning of various AutoAcoustic values:

0 Acoustic management disabled.
1 Minimum noise.
2-126 Intermediate noise levels.
127 Maximum performance, maximum noise.

Meaning of various APM values:

1 Minimum power usage with Standby (spindown).
2-127 Intermediate power usage with Standby.
128 Minimum power usage without Standby (no spindown).
129-253 Intermediate power usage without Standby.
254 Maximum performance, maximum power usage.

Some values may not be supported, in this case you will see an error
message 'Set APM failed: Inappropriate ioctl for device'.
ataidle-2.5/ataidle.8000064400000000000000000000047171213266322700144720ustar00rootroot00000000000000.\" man page for ATAidle
.\" Contact bruce@cran.org.uk to correct errors or omissions
.TH man 8 "November 2010" "2.5" "ATAidle"
.SH NAME
ataidle \- a utility to spin down ATA drives
.SH SYNOPSIS
.\" Syntax goes here.
.B ataidle [-h] [-i] [-s] [-o] [-I
.I standby_mins
.B ] [-S
.I standby_mins
.B ] [-A
.I aam_level
.B ] [-P
.I apm_level
.B ]
.I device
.SH DESCRIPTION
.B ATAidle
sets various power management features on hard drives, including timeouts to
switch to idle and standby power saving modes, and setting the
APM (power) and AAM (acoustic) levels.
If only a device is specified, without options, information about the
selected device will be shown.

.SH OPTIONS
.IP -h
Show usage information
.IP -i
Puts the drive into Idle mode
.IP -s
Puts the drive into Standby mode
.IP -o
Puts the drive into Sleep mode
.IP -I
Puts the drive into
.B Idle
mode and configures the standby timer to put the drive into
.B Standby
mode after standby_mins minutes of inactivity.
.IP -S
Puts the drive into
.B Standby
mode and configures the standby timer to put the drive into
.B Standby
mode after standby_mins minutes of inactivity.
.IP -A
Set the
.B acoustic
level of the hard drive. This allows you to reduce the
acoustic output of the drive at the expense of performance.
.IP -P
Set the
.B Advanced Power Management
level of the drive. This allows you to reduce the power
consumption of the drive at the expense of performance.
A low
.B apm_level
will cause the drive to go into
.B Standby
mode to save power.

.SH NOTES
Notes on Auto Acoustic Management (AAM) and APM support

AAM and APM settings are vendor-specific and not all intermediate values may be valid.
If you set an invalid APM value you will be notified that it failed - when
setting an AAM value you should check the output of 'ataidle <device>' to see
if it has been updated.
If it hasn't, the value isn't supported and you should try a higher or lower setting.

.IP

Meaning of AAM values:

.IP 0
Acoustic management disabled.
.IP 1
Minimum noise.
.IP 2-126
Intermediate noise levels.
.IP 127
Maximum performance, maximum noise.

Meaning of APM values:

.IP 0
APM disabled
.IP 1
Minimum power usage with Standby (spindown).
.IP 2-127
Intermediate power usage with Standby.
.IP 128
Minimum power usage without Standby (no spindown).
.IP 129-253
Intermediate power usage without Standby.
.IP 254
Maximum performance, maximum power usage.
.SH AUTHOR
Bruce Cran <bruce@cran.org.uk>
.SH "SEE ALSO"
.BR atacontrol (8),
.BR hdparm (8),
.BR smartctl (8)
ataidle-2.5/freebsd/000075500000000000000000000000001213266322700143775ustar00rootroot00000000000000ataidle-2.5/freebsd/ataidle.c000064400000000000000000000121201213266322700161420ustar00rootroot00000000000000/*-
*
* Copyright 2004-2010 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#include <errno.h>
#include <libgen.h>

#include <sys/types.h>
#include <sys/ata.h>
#include <sys/ioctl.h>
#include <stdbool.h>

#include <stdio.h>
#include <camlib.h>
#include <cam/cam_ccb.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>

#include "../mi/atagen.h"
#include "ataidle.h"

ATA*
ata_open(const char *path)
{
ATA *ata = NULL;
bool using_cam = false;

ata = malloc(sizeof(ATA));
if (ata == NULL)
return NULL;

char *bp = basename(path);

/* Check which driver we're using: ata(4), ahci(4) or da(4) */
if (bp[0] == 'a' && bp[1] == 'd') {
if (bp[2] == 'a') {
ata->disk_protocol = DISK_PROTO_ATA_CAM;
using_cam = true;
} else {
ata->disk_protocol = DISK_PROTO_ATA;
ata->ata_fd = open(path, O_RDONLY);
if (ata->ata_fd < 0) {
free(ata);
return NULL;
}
}
} else {
ata->disk_protocol = DISK_PROTO_SCSI;
using_cam = true;
}

if (using_cam) {
ata->cam_dev = cam_open_device( path, O_RDWR );
if (ata->cam_dev == NULL) {
free(ata);
return NULL;
}
}

return ata;
}

void
ata_close( ATA *ata )
{
if (ata->ata_fd >= 0)
close(ata->ata_fd);

free(ata);
}

int
atacmd_ata(ATA *ata, int atacmd, int feature, int feature_val)
{
int rc;

ata->atacmd.u.ata.command = atacmd;
ata->atacmd.u.ata.feature = feature;
ata->atacmd.u.ata.count = feature_val;

rc = ioctl(ata->ata_fd, IOCATAREQUEST, &(ata->atacmd));
return rc;
}

int
atacmd_cam(ATA *ata, int atacmd, int feature, int feature_val)
{
union ccb *ccb = cam_getccb(ata->cam_dev);

int direction;
int rc = 0;
uint32_t timeout = ATA_CMD_TIMEOUT*1000;

if (atacmd == ATA__IDENTIFY || atacmd == ATA__ATAPI_IDENTIFY)
direction = CAM_DIR_IN;
else
direction = CAM_DIR_OUT;

memset(&(&ccb->ccb_h)[1], 0, sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));

cam_fill_ataio(&ccb->ataio,
5, NULL,
direction, MSG_SIMPLE_Q_TAG,
(uint8_t*)ata->outbuffer, ata->outbuffer_size,
timeout);

ata_28bit_cmd(&ccb->ataio, atacmd, feature, 0, feature_val);

ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;

if (cam_send_ccb(ata->cam_dev, ccb) < 0) {
cam_error_print(ata->cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
rc = 1;
}

if (!rc && (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
cam_error_print(ata->cam_dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
rc = 1;
}

cam_freeccb(ccb);

return rc;
}

/* send a command to the drive */
int
ata_cmd(ATA *ata, int atacmd, int feature, int feature_val)
{
int rc = 0;

if (ata->disk_protocol == DISK_PROTO_ATA)
rc = atacmd_ata(ata, atacmd, feature, feature_val);
else if (ata->disk_protocol == DISK_PROTO_ATA_CAM)
rc = atacmd_cam(ata, atacmd, feature, feature_val);

return rc;

}

/* initialize the ata_cmd structure with supplied values */
void
ata_init(ATA *ata)
{
if (ata->disk_protocol == DISK_PROTO_ATA) {
memset(&ata->atacmd, 0, sizeof(struct ata_cmd));

ata->atacmd.u.ata.command = (uint8_t) IOCATAREQUEST;
ata->atacmd.flags = ATA_CMD_CONTROL;
ata->atacmd.timeout = ATA_CMD_TIMEOUT;
ata->atacmd.count = 0;
}
}


char*
ata_setup_buffer(ATA *ata, int nbytes)
{
char *databuf = malloc(nbytes);

if (databuf == NULL)
{
/* malloc failed, there's no way to recover here */
fprintf(stderr, "malloc failed.\n");
exit(1);
}

memset(databuf, 0, nbytes);

if (ata->disk_protocol == DISK_PROTO_ATA) {
ata->atacmd.data = databuf;
ata->atacmd.count = nbytes;
ata->atacmd.flags = ATA_CMD_READ;
}

ata->outbuffer = databuf;
ata->outbuffer_size = nbytes;

return databuf;
}

void
ata_free(ATA *ata)
{
if (ata->outbuffer != NULL)
free(ata->outbuffer);
}
ataidle-2.5/freebsd/ataidle.h000064400000000000000000000034441213266322700161600ustar00rootroot00000000000000/*-
*
* Copyright 2004-2010 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/


#ifndef ATAIDLE_H
#define ATAIDLE_H

#include <sys/types.h>
#include <sys/ata.h>

#include <stdio.h>
#include <camlib.h>

typedef struct
{
int ata_fd;
struct cam_device *cam_dev;
uint32_t cmd;
struct ata_ioc_request atacmd;
enum DISK_PROTO disk_protocol;
char *outbuffer;
size_t outbuffer_size;

} ATA;

#endif /* ATAIDLE_H */
ataidle-2.5/freebsd/ataidle_rc000064400000000000000000000020431213266322700164100ustar00rootroot00000000000000#!/bin/sh

# PROVIDE: ataidle
# BEFORE: LOGIN

#
# Add the following lines to /etc/rc.conf to enable ataidle:
#
# ataidle_enable (bool): set to NO by default.
# Set to YES to enable ataidle.
# ataidle_devices: list of devices on which to run ataidle
# ataidle_adaX: parameters to pass to ataidle(8)

# Example:
# Put the disks ada0, ada1 and ada2 into Standby mode after 60 minutes:
#
# ataidle_devices="ada0 ada1 ada2"
# ataidle_ada0="-S 60"
# ataidle_ada1="-S 60"
# ataidle_ada2="-S 60"
#

. /etc/rc.subr

name="ataidle"
rcvar=${name}_enable

command=%%PREFIX%%/sbin/${name}
start_cmd=ataidle_start

load_rc_config $name

: ${ataidle_enable="NO"}

ataidle_start()
{
if [ -n "${ataidle_device}" -a -z "${ataidle_devices}" ]; then
echo "warning: old ataidle rc settings found"
ataidle_devices=${ataidle_device}
fi

if [ -n "${ataidle_devices}" ]; then
for i in ${ataidle_devices}; do
eval ataidle_args=\$ataidle_${i}
echo "ataidle: configuring device /dev/${i}"
${command} ${ataidle_args} /dev/${i}
done
fi
}

run_rc_command "$1"
ataidle-2.5/linux/000075500000000000000000000000001213266322700141245ustar00rootroot00000000000000ataidle-2.5/linux/ataidle.c000064400000000000000000000052511213266322700156760ustar00rootroot00000000000000/*-
*
* Copyright 2004-2010 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/hdreg.h>

#include "../mi/atagen.h"

/* send a command to the drive */
int
ata_cmd(ATA *ata, int cmd, int feature, int feature_val)
{
int rc = 0;

ata->atacmd.feature = feature;

if(feature != 0)
ata->atacmd.sector_number = feature;
else
ata->atacmd.sector_count = 1;

ata->atacmd.cmd = cmd;
rc = ioctl( ata->ata_fd, HDIO_DRIVE_CMD, &ata->atacmd );

return rc;
}

/* initialize the ata_cmd structure with supplied values */
void
ata_init(ATA *ata)
{
memset(&ata->atacmd, 0, sizeof(struct ata_cmd));
}

char*
ata_setup_buffer(ATA *ata, int nbytes)
{
return (char*) ata->atacmd.buf;
}

ATA*
ata_open(const char *path)
{
ATA *ata = NULL;

ata = malloc(sizeof(ATA));
if (ata == NULL)
return NULL;

ata->disk_protocol = DISK_PROTO_ATA;
ata->ata_fd = open(path, O_RDONLY);
if (ata->ata_fd < 0) {
free(ata);
return NULL;
}

return ata;
}

void
ata_close(ATA *ata)
{
if (ata->ata_fd >= 0)
close(ata->ata_fd);

free(ata);
}

void
ata_free(ATA *ata)
{
/* nothing to do */
}
ataidle-2.5/linux/ataidle.h000064400000000000000000000035241213266322700157040ustar00rootroot00000000000000/*-
*
* Copyright 2004-2010 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/


#ifndef ATAIDLE_H
#define ATAIDLE_H

#include <stdint.h>

struct ata_cmd {
unsigned char cmd;
unsigned char sector_number;
unsigned char feature;
unsigned char sector_count;
unsigned char buf[512];
};

typedef struct
{
int ata_fd;
uint32_t cmd;
struct ata_cmd atacmd;
enum DISK_PROTO disk_protocol;
char *outbuffer;
size_t outbuffer_size;
} ATA;


#endif /* ATAIDLE_H */
ataidle-2.5/main.c000064400000000000000000000104701213266322700140570ustar00rootroot00000000000000/*-
*
* Copyright 2004-2010 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

#include <err.h>
#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "mi/atagen.h"

#ifdef __FreeBSD__
#include <osreldate.h>

#if __FreeBSD_version < 600034
#error ATAidle requires FreeBSD 6.1 or newer
#endif
#endif

int
main(int argc, char ** argv)
{
int rc = 0;
ATA *ata = NULL;
long opt_val;
int ch;
struct ata_ident ident;
const char * const optstr = "hA:S:sI:iP:o";

/* need more than just the executable name */
if( argc == 1 )
usage();

ata = ata_open(argv[argc-1]);

if (ata == NULL)
errx(1, "error opening %s", argv[argc-1]);

rc = ata_identify(ata, &ident);

if (rc)
errx(1, "error: identify device %s\n", argv[argc-1]);

if (argc == 2)
ata_showdeviceinfo(ata, ident);

optind = 1;
opterr = 1;

while ((ch = getopt(argc, argv, optstr)) != -1)
{
switch(ch)
{
/* Standby */
case 'S':
opt_val = strtol(optarg, NULL, 10);
if(opt_val == LONG_MIN || opt_val == LONG_MAX ||
(opt_val == 0 && errno == EINVAL))
warnx("invalid standby timer value");
else {
if (ident.cmd_supp1 & ATA_PM_SUPPORTED)
rc = ata_setstandbytimer(ata, opt_val);
else
warnx("the device does not support power management");
}
break;

case 's':
rc = ata_setstandbytimer(ata, ATA_IDLEVAL_IMMEDIATE);
break;

/* o = Sleep (off) */
case 'o':
if (ident.cmd_supp1 & ATA_PM_SUPPORTED)
rc = ata_sleep(ata);
else
warnx("the device does not support power management");
break;

/* Idle */
case 'I':
opt_val = strtol(optarg, NULL, 10);

if(opt_val == LONG_MIN || opt_val == LONG_MAX ||
(opt_val == 0 && errno == EINVAL))
warnx("invalid standby timer value");
else {
if (ident.cmd_supp1 & ATA_PM_SUPPORTED)
rc = ata_setidletimer(ata, opt_val);
else
warnx("the device does not support power management");
}
break;

case 'i':
rc = ata_setidletimer(ata, ATA_IDLEVAL_IMMEDIATE);
break;

/* Acoustic */
case 'A':
opt_val = strtol(optarg, NULL, 10);
if(opt_val == LONG_MIN || opt_val == LONG_MAX ||
(opt_val == 0 && errno == EINVAL))
warnx("invalid AAM value");
else {
if (ident.cmd_supp2 & ATA_AAM_SUPPORTED)
rc = ata_setacoustic(ata, opt_val);
else
warnx("the device does not support acoustic management");
}
break;

/* Power (APM) */
case 'P':
opt_val = strtol(optarg, NULL, 10);
if(opt_val == LONG_MIN || opt_val == LONG_MAX ||
(opt_val == 0 && errno == EINVAL))
warnx("invalid APM value");
else {
if (ident.cmd_supp2 & ATA_APM_SUPPORTED)
rc = ata_setapm(ata, opt_val);
else
warnx("the device does not support advanced power management");
}
break;

case 'h':
default:
usage();
break;
}
}

if (ata != NULL)
ata_close(ata);

return (rc);
}

ataidle-2.5/mi/000075500000000000000000000000001213266322700133725ustar00rootroot00000000000000ataidle-2.5/mi/atagen.h000064400000000000000000000116721213266322700150110ustar00rootroot00000000000000/*-
*
* Copyright 2004-2010 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

/* Generic definitions (applicable to all supported operating systems) */

#ifndef ATAGEN_H
#define ATAGEN_H

#include <stdint.h>
#include <stdbool.h>

#define ATAIDLE_VERSION "2.5"

enum DISK_PROTO
{
DISK_PROTO_ATA,
DISK_PROTO_ATA_CAM,
DISK_PROTO_SCSI
};

#ifdef __FreeBSD__
#include <osreldate.h>
#include <sys/ata.h>
#include "../freebsd/ataidle.h"
#else
#include "../linux/ataidle.h"
#endif

#define ATA_PM_SUPPORTED 0x0008

#define ATA_APM_SUPPORTED 0x0008
#define ATA_APM_ENABLED 0x0008

#define ATA_AAM_SUPPORTED 0x0200
#define ATA_AAM_ENABLED 0x0200

#define ATA_SMART_SUPPORTED 0x0001
#define ATA_SMART_ENABLED 0x0001

#define ATA__SETFEATURES 0xEF
#define ATA__IDENTIFY 0xEC
#define ATA__ATAPI_IDENTIFY 0xA1
#define ATA_IDLE 0xE3
#define ATA_STANDBY 0xE2

#ifndef ATA_SLEEP
#define ATA_SLEEP 0xE6
#endif

#define ATA_AUTOACOUSTIC_ENABLE 0x42
#define ATA_AUTOACOUSTIC_DISABLE 0xC2
#define ATA_APM_ENABLE 0x05
#define ATA_APM_DISABLE 0x85
#define ATA_AUTOACOUSTIC_MAXPERF 0xFE
#define ATA_AUTOACOUSTIC_MINPERF 0x80
#define ATA_APM_MINPOWER_NO_STANDBY 0x80
#define ATA_APM_MINPERF 0x01
#define ATA_APM_MAXPERF 0xFE
#define ATA_POWERSTATUS_GET 0xE5
#define ATA_CMD_TIMEOUT 30
#define ATA_IDLEVAL_IMMEDIATE 900

#ifndef __FreeBSD__
#define ATA_STANDBY_IMMEDIATE 0xE0
#define ATA_IDLE_IMMEDIATE 0xE1
#endif

struct ata_ident
{
uint16_t config;
uint16_t word1;
uint16_t config_specific;
uint16_t word3;
uint16_t word4[2];
uint16_t word6;
uint16_t word7[2];
uint16_t word9;
uint8_t serial[20];
uint16_t word20[2];
uint16_t word22;
uint8_t firmware[8];
uint8_t model[40];
uint16_t max_sect_per_trans;
uint16_t word48;
uint16_t caps1;
uint16_t caps2;
uint16_t word51[2];
uint16_t words_valid;
uint16_t word54[5];
uint16_t sectors_per_interrupt;
uint16_t nsect[2];
uint16_t word62;
uint16_t mdma_supp;
uint16_t pio_supp;
uint16_t mdma_trans_time;
uint16_t mdma_trans_time_vendor;
uint16_t pio_trans_time_noflow;
uint16_t pio_trans_time_flow;
uint16_t word69[2];
uint16_t word71[4];
uint16_t queue_depth;
uint16_t word76[4];
uint16_t version_major;
uint16_t version_minor;
uint16_t cmd_supp1;
uint16_t cmd_supp2;
uint16_t cmd_supp_ext;
uint16_t cmd_enabled1;
uint16_t cmd_enabled2;
uint16_t cmd_ext_default;
uint16_t udma_modes;
uint16_t erase_time_security;
uint16_t erate_time_security_enhance;
uint16_t apm_value;
uint16_t master_passwd_rev_code;
uint16_t hardware_reset_result;
uint16_t aam_value;
uint16_t word95[5];
uint16_t max_lba48_address[4];
uint16_t word104[23];
uint16_t removable_media_features_supp;
uint16_t security_status;
uint16_t vendor_specific[31];
uint16_t cfa_powermode_1;
uint16_t word161[15];
uint16_t media_serial_no[30];
uint16_t word206[49];
uint16_t integrity;
};

ATA* ata_open(const char *device);
void ata_close(ATA *ata);
int ata_setidletimer(ATA *ata, uint32_t idle_mins);
int ata_sleep(ATA *ata);
int ata_setstandbytimer(ATA *ata, uint32_t standby_mins);
int ata_setacoustic(ATA *ata, uint32_t acoustic_val);
int ata_setapm(ATA *ata, uint32_t apm_val);
void ata_listdevices(ATA *ata);
int ata_getmaxchan(ATA *ata, uint32_t *maxchan);
int ata_cmd(ATA *ata, int atacmd, int feature, int feature_val);
bool ata_devpresent(ATA *ata);
int ata_identify(ATA *ata, struct ata_ident *identity);
void ata_showdeviceinfo(ATA *ata, struct ata_ident ident);
void ata_setfeature(ATA *ata, int feature_val);
void ata_init(ATA *ata);
char* ata_setup_buffer(ATA *ata, int nbytes);
void ata_free(ATA *ata);
void usage(void);

#endif /* ATAIDLE_H */
ataidle-2.5/mi/util.c000064400000000000000000000272621213266322700145240ustar00rootroot00000000000000/*-
*
* Copyright 2004-2010 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

#include <arpa/inet.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "atagen.h"

static int is_big_endian(void);
static int ata_getidleval(uint32_t idle_mins, uint16_t *timer_val);
static char* ata_getversionstring(uint16_t ata_version);
static void byteswap(char *buf, int from, int to);
static void strpack(char *buf, int from, int to);
static void byteswap_ata_data(int16_t *buf);
static void mem_swap(int16_t *val);

/* calculate the standby timer value to send to the drive. */
static int
ata_getidleval(uint32_t idle_mins, uint16_t *timer_val)
{
int rc = 0;

/* idle value of 0 disables spindown */
if( idle_mins == 0 )
*timer_val = 0;

/* value is (value*5)s between 1 and 20 minutes */
if( idle_mins <= 20 )
*timer_val = (idle_mins*60)/5;

/* special case for 21 minutes */
if( idle_mins == 21 )
*timer_val = 252;

/* there is no encoding for values between 21 and 30 minutes */
if( (idle_mins > 21) && (idle_mins < 30) ) {
fprintf(stderr, "Cannot set timeout for 22-29 minutes\n" );
rc = -1;
}

/* after 30 mins, encoding is (idle_mins-29)*30, so you
* can only encode multiples of 30 minutes
*/
if( idle_mins >= 30 ) {
/* if it's not a multiple of 30 minutes,
* or it's greater than 5 hours, we can't handle it.
*/
if ((((idle_mins % 30) != 0) || (idle_mins > 330))
&& (idle_mins != ATA_IDLEVAL_IMMEDIATE) )
{
fprintf(stderr, "Idle timer must be 1-21, or a multiple of 30 "
"up to 330 (5.5 hours)\n");
rc = -1;
}

/* otherwise, calculate the timer value */
if(idle_mins == ATA_IDLEVAL_IMMEDIATE)
*timer_val = ATA_IDLEVAL_IMMEDIATE;
else
*timer_val = 240 + (idle_mins/30);
}

return rc;
}

static char*
ata_getversionstring(uint16_t ata_version)
{
const int ATAVERSION_LEN = 16;
char * version = malloc(ATAVERSION_LEN);
int i;

if (version == 0) { /* malloc failed */
fprintf(stderr, "malloc failed\n");
return NULL;
}

memset(version, 0, ATAVERSION_LEN);

for (i = 0; i < 15; i++) {
if ((ata_version >> i) > 0)
sprintf(version, "ATA-%d", i);
}

return version;
}

void
usage(void)
{
printf("ataidle version " ATAIDLE_VERSION "\n\n"
"usage: \n"
"ataidle [-h] [-i] [-s] [-o] [-I standby_mins] [-S standby_mins]\n"
" [-A aam] [-P apm] device\n\n"
"Options:\n");
printf(
"-h\t\tdisplay this help\n"
"-I\t\tenter idle mode and set the standby timer (minutes)\n"
"-i\t\tenter idle mode\n"
"-S\t\tenter standby mode and set the standby timer (minutes)\n"
"-s\t\tenter standby mode\n"
"-o\t\tenter sleep mode\n"
"-A\t\tset the AAM (acoustic) level (1-127)\n"
"-P\t\tset the APM (power) level, (1-254)\n"
"device\t\tthe device node e.g. /dev/ada0\n\n"
"standby_mins is in minutes and has a range of 1-21, then 30-330 in 30\n"
"minute steps.\n\n"
"If no options are specified, information about the device will be displayed.\n");

exit(1);
}

static void
byteswap(char * buf, int from, int to)
{
int i;

for (i = from; i <= to; i+=2)
{
char b1 = buf[i];
buf[i] = buf[i+1];
buf[i+1] = b1;
}
}

/* Trim leading whitespace */
static void
strpack(char *buf, int from, int to)
{
int i = 0, j= 0, k = 0;
int numchars = (to-from)+1;
char *tmpbuf = malloc(numchars*sizeof(char));

if(tmpbuf == NULL) { /* malloc failed, skip the string packing */
fprintf(stderr, "malloc failed\n");
return;
}

strncpy(tmpbuf, buf+from, numchars);
memset(buf+from, 0, numchars);

i = 0;

while(tmpbuf[i] == ' ')
i++;

j = 0;
k = 0;

for(j = i; j < numchars; j++)
{
buf[from+k] = tmpbuf[j];
k++;
}

free(tmpbuf);
}

/* swap the bytes */
static void
mem_swap(int16_t * val)
{
int8_t * smallval = (int8_t*) val;
int8_t tmp = smallval[0];

smallval[0] = smallval[1];
smallval[1] = tmp;
}

/* detect if we're running on a big-endian platform */
static int
is_big_endian(void)
{
int i = 0;
((char*)(&i))[0] = 1;
return (i != 1);
}

void
ata_showdeviceinfo(ATA *ata, struct ata_ident ident)
{
int16_t *buf;
unsigned int mbsize;
char model[41];
char serial[21];
char firmware[9];
char *ata_version = NULL;

buf = (int16_t*) &ident;

memset(model, 0, 41);
memset(serial, 0, 21);
memset(firmware, 0, 9);

strncpy(model, (char*) ident.model, 40);
strncpy(serial, (char*) ident.serial, 20);
strncpy(firmware, (char*) ident.firmware, 8);

printf("Model:\t\t\t%s\n", model);
printf("Serial:\t\t\t%s\n", serial);
printf("Firmware Rev:\t\t%s\n", firmware);
ata_version = ata_getversionstring(buf[80]);
printf("ATA revision:\t\t%s\n", (ident.version_major > 1)?
ata_version : "unknown/pre ATA-2");
printf("LBA 48:\t\t\t%s\n", (buf[86] & 0x400)? "yes" : "no");
printf("Geometry:\t\t%d cyls, %d heads, %d spt\n",
buf[1], buf[3], buf[6]);

if (ata_version != NULL)
free(ata_version);

mbsize = 0;

if (buf[86] & 0x400)
{
mbsize = (((uint64_t)ident.max_lba48_address[0] +
((uint64_t)ident.max_lba48_address[1] << 16) +
((uint64_t)ident.max_lba48_address[2] << 32) +
((uint64_t)ident.max_lba48_address[3] << 48))*512)/1048576;
}
else
{
mbsize = ((ident.nsect[0] + (ident.nsect[1] << 16))*512)/1048576;
}

bool smart_supported = buf[82] & ATA_SMART_SUPPORTED;
bool smart_enabled = buf[85] & ATA_SMART_ENABLED;
bool apm_supported = buf[83] & ATA_APM_SUPPORTED;
bool apm_enabled = buf[86] & ATA_APM_ENABLED;
bool aam_supported = buf[83] & ATA_AAM_SUPPORTED;
bool aam_enabled = buf[86] & ATA_AAM_ENABLED;

printf("Capacity:\t\t%u%s\n", (mbsize < 1024)?
mbsize : mbsize/1024, (mbsize < 1024)? "MB" : "GB");

printf("SMART Supported: \t%s\n", smart_supported? "yes" : "no" );

if (smart_supported)
printf("SMART Enabled: \t\t%s\n", smart_enabled? "yes" : "no" );

printf("APM Supported: \t\t%s\n", apm_supported? "yes" : "no" );

if (apm_supported) {
printf("APM Enabled: \t\t%s\n", apm_enabled? "yes" : "no" );
if (apm_enabled)
printf("APM Value: \t\t%d\n", buf[91]);
}

printf("AAM Supported: \t\t%s\n", aam_supported? "yes" : "no" );

if (aam_supported) {
printf("AAM Enabled: \t\t%s\n", aam_enabled? "yes" : "no");
if (aam_enabled)
printf("AAM Value: \t\t%d\n", ((buf[94] & 0x00FF))-127);

printf("Vendor Recommended AAM: %d\n", ((buf[94] & 0xFF00) >> 8)-127);
}
}

static void
byteswap_ata_data(int16_t * buf)
{
int i;

for (i = 0; i < 10; i++) {
mem_swap(buf+i);
}

for (i = 20; i < 23; i++) {
mem_swap(buf+i);
}

for (i = 47; i < 255; i++) {
mem_swap(buf + i);
}
}

/*
* Set the Advanced Power Management mode for the drive. Modern hard
* drives can have a number of power management states, ranging from
* lowest (least performance) to highest power consumption, which results
* in the highest performance.
*/
int
ata_setapm(ATA *ata, uint32_t apm_val)
{
int rc = 0;
int apm_onoff_setting;

/* user inputs vale 1-126, 0x01-0xFE */

if (apm_val > ATA_APM_MAXPERF) {
fprintf(stderr, "Invalid APM value: must be %d-%d\n",
ATA_APM_MINPERF, ATA_APM_MAXPERF);
rc = -1;
}

/* allocate and initialize the ata_cmd structure */
ata_init(ata);

if(apm_val == 0)
apm_onoff_setting = ATA_APM_DISABLE;
else
apm_onoff_setting = ATA_APM_ENABLE;

/* send the APM command to the drive as a FEATURE */
if(!rc) {
rc = ata_cmd(ata, ATA__SETFEATURES, apm_onoff_setting, apm_val);

if(rc)
perror("Failed to configure APM");
}

return rc;
}

/*
* Sets the acoustic level on modern hard drives. This is used to run it
* at a lower speed/performance level, which in turn reduces noise.
*/
int
ata_setacoustic(ATA *ata, uint32_t acoustic_val)
{
int rc = 0;
int aam_onoff_setting;
static const int aam_user_offset = 127;

acoustic_val += aam_user_offset; /* scale it 0x80-0xFE, 128-254 */
/* range check our acoustic level parameter */
if (acoustic_val > ATA_AUTOACOUSTIC_MAXPERF) {
fprintf(stderr, "Invalid acoustic value: must be %d-%d\n",
1, ATA_AUTOACOUSTIC_MAXPERF - aam_user_offset);
rc = 1;
}

ata_init(ata);

/* disable AAM if user specified 0, which is 127 once offset */
if(acoustic_val == 127)
aam_onoff_setting = ATA_AUTOACOUSTIC_DISABLE;
else
aam_onoff_setting = ATA_AUTOACOUSTIC_ENABLE;

if(!rc) {
rc = ata_cmd(ata, ATA__SETFEATURES, aam_onoff_setting, acoustic_val);

if(rc)
perror("Failed to configure AAM.");
}
return rc;
}

/* command the device to spindown after idle_mins of no disk activity */
int
ata_setidletimer(ATA *ata, uint32_t idle_mins)
{
uint16_t timer_val = 0;
int rc = 0;

rc = ata_getidleval( idle_mins, &timer_val );

if(timer_val == ATA_IDLEVAL_IMMEDIATE)
ata_init(ata);
else
ata_init(ata);

/* send the IDLE command to the drive */
if (!rc) {
if(timer_val == ATA_IDLEVAL_IMMEDIATE)
rc = ata_cmd(ata, ATA_IDLE_IMMEDIATE, 0, 0);
else
rc = ata_cmd(ata, ATA_IDLE, 0, timer_val);
}

if (rc)
{
fprintf(stderr, "Failed to configure idle mode.\n");
}

return rc;
}

/* comand the drive to go into sleep mode */
int
ata_sleep(ATA *ata)
{
int rc = 0;

ata_init(ata);

/* send the SLEEP command to the drive */
rc = ata_cmd(ata, ATA_SLEEP, 0, 0);

if (rc)
perror("Failed to configure sleep mode");

return rc;
}

/* command the device to spindown after standby_mins of no disk activity */
int
ata_setstandbytimer(ATA *ata, uint32_t standby_mins)
{
uint16_t timer_val = 0;
int rc = 0;

rc = ata_getidleval( standby_mins, &timer_val );

if (rc)
return rc;

ata_init(ata);

/* send the STANDBY command to the drive */
if (!rc)
{
if(timer_val == ATA_IDLEVAL_IMMEDIATE)
rc = ata_cmd(ata, ATA_STANDBY_IMMEDIATE, 0, 0);
else
rc = ata_cmd(ata, ATA_STANDBY, 0, timer_val);
}

if (rc)
{
perror("Failed to configure standby timer");
}

return rc;
}

/* this function sends an IDENTIFY command to a drive */
int
ata_identify(ATA *ata, struct ata_ident * identity)
{
int rc = 0;
char *buf;

ata_init(ata);
buf = ata_setup_buffer(ata, 512);
rc = ata_cmd(ata, ATA__IDENTIFY, 0, 0);

if (rc)
{
/* then try an ATAPI IDENTIFY, maybe it didn't like
* an ATA_IDENTIFY */
ata_init(ata);
buf = ata_setup_buffer(ata, 512);
rc = ata_cmd(ata, ATA__ATAPI_IDENTIFY, 0, 0);
}

if (!rc)
{
byteswap( buf, 20, 39 ); /* serial */
byteswap( buf, 46, 52 ); /* firmware */
byteswap( buf, 54, 92 ); /* model */
strpack( buf, 20, 39 );
}

if (is_big_endian())
byteswap_ata_data((int16_t*)buf);

if (!rc)
memcpy(identity, buf, sizeof(struct ata_ident));

return rc;
}
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin