[-]
[+]
|
Added |
ataidle.changes
|
|
[-]
[+]
|
Changed |
ataidle.spec
^
|
|
[-]
[+]
|
Changed |
ataidle.patch
^
|
@@ -1,31 +1,29 @@
---- Makefile.orig 2008-08-31 19:13:57.000000000 +0200
-+++ Makefile 2008-08-31 19:15:49.000000000 +0200
+--- Makefile.orig 2010-11-02 21:26:09.000000000 +0100
++++ Makefile 2011-11-14 18:48:16.451883985 +0100
@@ -1,4 +1,4 @@
-PREFIX = /usr/local
+PREFIX := /usr/local
CC ?= gcc
LD ?= ld
- CFLAGS += -Wall -ansi -pedantic
-@@ -30,16 +30,16 @@
- $(CC) $(CFLAGS) -c mi/util.c
-
- install: ataidle ataidle.8 freebsd/ataidle_rc
-- install $(PROG) $(PREFIX)/sbin
-+ install $(PROG) $(DESTDIR)$(PREFIX)/sbin
+ CFLAGS += -Wall -pedantic -std=c99
+@@ -37,14 +37,14 @@
+ install $(PROG) $(PREFIX)/sbin
if [ "$(OS)" = Linux ]; then \
-- if [ ! -d $(PREFIX)/share/man/man8 ]; then \
-- mkdir -p $(PREFIX)/share/man/man8; \
-+ if [ ! -d $(DESTDIR)$(PREFIX)/share/man/man8 ]; then \
-+ mkdir -p $(DESTDIR)$(PREFIX)/share/man/man8; \
- fi; \
-- install $(MAN) $(PREFIX)/share/man/man8; \
-+ install $(MAN) $(DESTDIR)$(PREFIX)/share/man/man8; \
+- if [ ! -d $(PREFIX)/share/man/man8 ]; then \
+- mkdir -p $(PREFIX)/share/man/man8; \
++ if [ ! -d $(DESTDIR)$(PREFIX)/share/man/man8 ]; then \
++ mkdir -p $(DESTDIR)$(PREFIX)/share/man/man8; \
+ fi; \
+- install $(MAN) $(PREFIX)/share/man/man8; \
++ install $(MAN) $(DESTDIR)$(PREFIX)/share/man/man8; \
else \
-- install $(MAN) $(PREFIX)/man/man8; \
-- install freebsd/ataidle_rc $(PREFIX)/etc/rc.d/ataidle; \
-+ install $(MAN) $(DESTDIR)$(PREFIX)/man/man8; \
-+ install freebsd/ataidle_rc $(DESTDIR)$(PREFIX)/etc/rc.d/ataidle; \
+- 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; \
++ install $(MAN) $(DESTDIR)$(PREFIX)/man/man8; \
++ install freebsd/ataidle_rc $(DESTDIR)$(PREFIX)/etc/rc.d/ataidle; \
++ sed -I '' s:%%PREFIX%%:$(PREFIX):g $(DESTDIR)$(PREFIX)/etc/rc.d/ataidle; \
fi
uninstall:
|
[-]
[+]
|
Deleted |
ataidle-2.4.tar.gz/mi/atadefs.h
^
|
@@ -1,34 +0,0 @@
-#ifndef ATADEFS_H
-#define ATADEFS_H
-
-#include <stdint.h>
-
-static const uint32_t ATA__SETFEATURES = 0xEF;
-static const uint32_t ATA__IDENTIFY = 0xEC;
-static const uint32_t ATA__ATAPI_IDENTIFY = 0xA1;
-static const uint32_t ATA_IDLE = 0xE3;
-static const uint32_t ATA_STANDBY = 0xE2;
-
-#ifndef ATA_SLEEP
-static const uint32_t ATA_SLEEP = 0xE6;
-#endif
-
-static const uint32_t ATA_AUTOACOUSTIC_ENABLE = 0x42;
-static const uint32_t ATA_AUTOACOUSTIC_DISABLE = 0xC2;
-static const uint32_t ATA_APM_ENABLE = 0x05;
-static const uint32_t ATA_APM_DISABLE = 0x85;
-static const uint32_t ATA_AUTOACOUSTIC_MAXPERF = 0xFE;
-static const uint32_t ATA_AUTOACOUSTIC_MINPERF = 0x80;
-static const uint32_t ATA_APM_MINPOWER_NO_STANDBY = 0x80;
-static const uint32_t ATA_APM_MINPERF = 0x01;
-static const uint32_t ATA_APM_MAXPERF = 0xFE;
-static const uint32_t ATA_POWERSTATUS_GET = 0xE5;
-static const uint32_t ATA_CMD_TIMEOUT = 10;
-static const uint32_t ATA_IDLEVAL_IMMEDIATE = 900;
-
-#ifndef __FreeBSD__
-static const uint32_t ATA_STANDBY_IMMEDIATE = 0xE0;
-static const uint32_t ATA_IDLE_IMMEDIATE = 0xE1;
-#endif
-
-#endif /* ATADEFS_H */
|
[-]
[+]
|
Deleted |
ataidle-2.4.tar.gz/mi/util.h
^
|
@@ -1,20 +0,0 @@
-#ifndef UTIL_H
-#define UTIL_H
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#define ATAIDLE_VERSION "2.4"
-
-void usage(void);
-int ata_strtolong( const char *src, long * dest );
-int ata_getidleval( uint32_t idle_mins, uint16_t *timer_val );
-char* ata_getversionstring(uint16_t ata_version);
-void byteswap(char * buf, int from, int to);
-void strpack(char * buf, int from, int to);
-bool checkargs( int argc, char ** argv, const char *optstr, bool * needchandev );
-void byteswap_ata_data( int16_t * buf );
-void hexdump( const char *data, int count );
-void mem_swap(int16_t * val);
-
-#endif /* UTIL_H */
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/COPYING
^
|
@@ -1,4 +1,4 @@
-Copyright 2004-2008 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
+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
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/Changelog
^
|
@@ -95,3 +95,20 @@
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.
+Thu Sep 22 20:47 2011 brucec
+ * Integrated cleanup and write cache support
+ from FreeBSD.
+ Fixed bug that caused problems on some
+ controllers due to setting CAM_OUT for commands
+ where no data is transferred.
+Sun Oct 23 13:23 2011 brucec
+ * Resolve symlinks when checking which device
+ interface to use, since FreeBSD 9.0 creates
+ symlinks from adX to adaX.
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/Makefile
^
|
@@ -1,7 +1,7 @@
PREFIX = /usr/local
CC ?= gcc
LD ?= ld
-CFLAGS += -Wall -ansi -pedantic
+CFLAGS += -Wall -pedantic -std=c99
LIBS = -lm
SOURCES = ataidle.c
MAN = ataidle.8
@@ -11,35 +11,40 @@
OS ?= $(shell uname -s)
REV:sh = uname -r | head -c 1
-all: ataidle
+all: ataidle
-ataidle: ataidle.o util.o main.o
- $(CC) $(CFLAGS) $(LIBS) -o ataidle main.o ataidle.o util.o
+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/atadefs.h mi/atagen.h mi/util.h
+main.o: main.c mi/atagen.h
$(CC) $(CFLAGS) -c main.c
-ataidle.o: linux/ataidle.c freebsd/ataidle.c mi/atagen.h mi/atadefs.h mi/util.h
+ataidle.o: linux/ataidle.c freebsd/ataidle.c mi/atagen.h
@if [ "$(OS)" = Linux ]; then \
- $(CC) $(CFLAGS) -c linux/ataidle.c; \
+ $(CC) $(CFLAGS) -c linux/ataidle.c; \
elif [ "$(OS)" = FreeBSD ]; then \
- $(CC) $(CFLAGS) -c freebsd/ataidle.c; \
+ $(CC) $(CFLAGS) -c freebsd/ataidle.c; \
fi
-util.o: mi/util.c mi/util.h mi/atadefs.h mi/atagen.h
+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; \
+ 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; \
+ 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:
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/README
^
|
@@ -1,33 +1,27 @@
-ATAidle sets the idle 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.
+ATAidle 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
-Use of this feature is experimental, and may crash your computer - although
-it is believed to be stable, it is modifying hard disk behaviour as data is
-being read or written, so any fault in the drive could have disastrous
-consequenses for your data.
-
Meaning of various AutoAcoustic values:
-0 Acoustic management disabled
-1 Minimum acoustic output
-2-126 Intermediate acoustic output levels
-127 Maximum performance, maximum acoustic output
+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
+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'.
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/ataidle.8
^
|
@@ -1,100 +1,101 @@
.\" man page for ATAidle
.\" Contact bruce@cran.org.uk to correct errors or omissions
-.TH man 8 "August 2008" "2.4" "ATAidle"
+.TH man 8 "November 2011" "2.7.1" "ATAidle"
.SH NAME
ataidle \- a utility to spin down ATA drives
.SH SYNOPSIS
-.\" Syntax goes here.
-.B ataidle [-h] [-i] [-s] [-o] [-I
-.I idle_mins
+.\" Syntax goes here.
+.B ataidle [-h] [-i] [-s] [-o] [-I
+.I standby_mins
.B ] [-S
.I standby_mins
.B ] [-A
-.I acoustic_level
+.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.
+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
+Show usage information
.IP -i
-put the drive into idle mode
+Puts the drive into Idle mode
.IP -s
-put the drive into standby mode
+Puts the drive into Standby mode
.IP -o
-put the drive into sleep mode
-.IP -I
-spins down the drive into
-.B idle
-mode after idle_mins minutes of inactivity
+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
-spins down the drive into
-.B standby
+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.
-However, using this mode usually immediately spins
-down the drive.
.IP -A
-set the
+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
+Set the
.B Advanced Power Management
-level of the drive. This allows you to lower the power
-consumption of the drive, at the expense of performance.
-A very low
+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 make the drive go into standby mode to save power.
+will cause the drive to go into
+.B Standby
+mode to save power.
.SH NOTES
Notes on Auto Acoustic Management (AAM) and APM support
-These features are experimental, and should only be used
-after verifying that the drive works when sent those commands.
-
-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.
+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 acoustic output
-.IP 2-126
-Intermediate acoustic output levels
-.IP 127
-Maximum performance, maximum acoustic output
+.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
+.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"
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/freebsd/ataidle.c
^
|
@@ -1,6 +1,6 @@
/*-
*
- * Copyright 2004-2008 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
+ * Copyright 2004-2011 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
@@ -26,77 +26,203 @@
*
*/
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <limits.h>
+#include <osreldate.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <fcntl.h>
-#include <limits.h>
#include <unistd.h>
-#include <errno.h>
#include <sys/types.h>
#include <sys/ata.h>
#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <camlib.h>
+#include <cam/cam_ccb.h>
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_message.h>
-#include "ataidle.h"
#include "../mi/atagen.h"
-#include "../mi/atadefs.h"
-#include "../mi/util.h"
+#include "ataidle.h"
-/* send a command to the drive */
-int ata_cmd(ATA *ata, int atacmd, int drivercmd)
+ATA*
+ata_open(const char *path)
+{
+ ATA *ata = NULL;
+ bool using_cam = false;
+
+ ata = malloc(sizeof(ATA));
+ if (ata == NULL)
+ return NULL;
+
+ char *fullpath = realpath(path, NULL);
+ if (fullpath == NULL)
+ return NULL;
+
+ char *bp = basename(fullpath);
+
+ /* 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(fullpath, O_RDONLY);
+ if (ata->ata_fd < 0) {
+ free(ata);
+ free(fullpath);
+ return NULL;
+ }
+ }
+ } else {
+ ata->disk_protocol = DISK_PROTO_SCSI;
+ using_cam = true;
+ }
+
+ if (using_cam) {
+ ata->cam_dev = cam_open_device( fullpath, O_RDWR );
+ if (ata->cam_dev == NULL) {
+ free(ata);
+ free(fullpath);
+ return NULL;
+ }
+ }
+
+ free(fullpath);
+ 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;
+}
+
+#if __FreeBSD_version > 800000
+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 > 0)
- ata->atacmd.ata_cmd.u.ata.command = atacmd;
+ if (atacmd == ATA__IDENTIFY || atacmd == ATA__ATAPI_IDENTIFY)
+ direction = CAM_DIR_IN;
+ else
+ direction = CAM_DIR_NONE;
+ memset(&(&ccb->ccb_h)[1], 0, sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
- if (drivercmd == IOCATAGMAXCHANNEL) {
- int maxchan = 0;
- rc = ioctl( ata->fd, drivercmd, &maxchan );
- ata->atacmd.ata_cmd.data = malloc(sizeof(int));
- *ata->atacmd.ata_cmd.data = maxchan;
- } else {
- rc = ioctl( ata->fd, IOCATAREQUEST, &(ata->atacmd.ata_cmd) );
+ 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;
}
+#endif
-/* initialize the ata_cmd structure with supplied values */
-int ata_setataparams( ATA *ata, int seccount, int count)
+/* send a command to the drive */
+int
+ata_cmd(ATA *ata, int atacmd, int feature, int feature_val)
{
- /* clear the structure to remove any random values */
- memset(& ata->atacmd, 0, sizeof(struct ata_cmd));
- ata->atacmd.ata_cmd.u.ata.command = (uint8_t) IOCATAREQUEST;
- ata->atacmd.ata_cmd.flags = ATA_CMD_CONTROL;
- ata->atacmd.ata_cmd.timeout = ATA_CMD_TIMEOUT;
- ata->atacmd.ata_cmd.count = count;
- ata->atacmd.ata_cmd.u.ata.count = seccount;
+ int rc = 0;
+
+ if (ata->disk_protocol == DISK_PROTO_ATA)
+ rc = atacmd_ata(ata, atacmd, feature, feature_val);
+#if __FreeBSD_version > 800000
+ else if (ata->disk_protocol == DISK_PROTO_ATA_CAM)
+ rc = atacmd_cam(ata, atacmd, feature, feature_val);
+#endif
+
+ return rc;
- return 0;
}
-void ata_setfeature_param( ATA *ata, int feature_val)
+/* initialize the ata_cmd structure with supplied values */
+void
+ata_init(ATA *ata)
{
- ata->atacmd.ata_cmd.u.ata.feature = feature_val;
+ if (ata->disk_protocol == DISK_PROTO_ATA) {
+ memset(&ata->atacmd, 0, sizeof(struct ata_ioc_request));
+
+ ata->atacmd.u.ata.command = (uint8_t) IOCATAREQUEST;
+ ata->atacmd.flags = ATA_CMD_CONTROL;
+ ata->atacmd.timeout = ATA_CMD_TIMEOUT;
+ ata->atacmd.count = 0;
+ }
}
-void ata_setdataout_params( ATA *ata, char ** databuf, int nbytes)
+
+char*
+ata_setup_buffer(ATA *ata, int nbytes)
{
- *databuf = malloc(nbytes);
+ char *databuf = malloc(nbytes);
- if(*databuf == 0)
+ if (databuf == NULL)
{
/* malloc failed, there's no way to recover here */
- fprintf(stderr, "malloc failed. aborting\n");
- exit(EXIT_FAILURE);
+ fprintf(stderr, "malloc failed.\n");
+ exit(1);
}
- memset(*databuf, 0, nbytes);
- ata->atacmd.ata_cmd.data = *databuf;
- ata->atacmd.ata_cmd.count = nbytes;
- ata->atacmd.ata_cmd.flags = ATA_CMD_READ;
+ 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);
+}
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/freebsd/ataidle.h
^
|
@@ -1,7 +1,7 @@
/*-
- *
- * Copyright 2004-2008 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
- *
+ *
+ * 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:
@@ -12,7 +12,7 @@
* 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.
@@ -23,7 +23,7 @@
* 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.
- *
+ *
*/
@@ -33,9 +33,19 @@
#include <sys/types.h>
#include <sys/ata.h>
-struct ata_cmd
+#include <stdio.h>
+#include <camlib.h>
+
+typedef struct
{
- struct ata_ioc_request ata_cmd;
-};
+ 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 */
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/freebsd/ataidle_rc
^
|
@@ -9,27 +9,24 @@
# 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_adX: parameters to pass to ataidle(8)
+# ataidle_adaX: parameters to pass to ataidle(8)
# Example:
-# Put the disks ad0, ad1 and ad2 into Idle mode after 60
-# minutes and Standby mode after 120 minutes. Also, set the
-# AAM and APM values to their maximum so the drives run at
-# their maximum performance.
+# Put the disks ada0, ada1 and ada2 into Standby mode after 60 minutes:
#
-# ataidle_devices="ad0 ad1 ad2"
-# ataidle_ad0="-I 60 -S 120 -A 127 -P 254"
-# ataidle_ad1="-I 60 -S 120 -A 127 -P 254"
-# ataidle_ad2="-I 60 -S 120 -A 127 -P 254"
+# ataidle_devices="ada0 ada1 ada2"
+# ataidle_ada0="-S 60"
+# ataidle_ada1="-S 60"
+# ataidle_ada2="-S 60"
#
-. %%RC_SUBR%%
+. /etc/rc.subr
name="ataidle"
rcvar=${name}_enable
-command="%%PREFIX%%/sbin/${name}"
-start_cmd="ataidle_start"
+command=%%PREFIX%%/sbin/${name}
+start_cmd=ataidle_start
load_rc_config $name
@@ -45,7 +42,7 @@
if [ -n "${ataidle_devices}" ]; then
for i in ${ataidle_devices}; do
eval ataidle_args=\$ataidle_${i}
- echo "ATAidle: configuring device /dev/${i}"
+ echo "ataidle: configuring device /dev/${i}"
${command} ${ataidle_args} /dev/${i}
done
fi
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/linux/ataidle.c
^
|
@@ -1,7 +1,7 @@
/*-
- *
- * Copyright 2004-2008 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
- *
+ *
+ * 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:
@@ -12,7 +12,7 @@
* 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.
@@ -23,10 +23,9 @@
* 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.
- *
+ *
*/
-/* standard includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -40,44 +39,70 @@
#include <sys/stat.h>
#include <linux/hdreg.h>
-/* application-specific includes */
-#include "ataidle.h"
#include "../mi/atagen.h"
-#include "../mi/atadefs.h"
-#include "../mi/util.h"
/* send a command to the drive */
-int ata_cmd(ATA *ata, int cmd, int drivercmd)
+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->fd, HDIO_DRIVE_CMD, &ata->atacmd );
-
+ rc = ioctl( ata->ata_fd, HDIO_DRIVE_CMD, &ata->atacmd );
+
return rc;
}
/* initialize the ata_cmd structure with supplied values */
-int ata_setataparams(ATA *ata, int seccount, int count)
+void
+ata_init(ATA *ata)
{
- /* clear the structure to remove any random values */
memset(&ata->atacmd, 0, sizeof(struct ata_cmd));
-
- if(seccount != 0)
- ata->atacmd.sector_number = seccount;
- else
- ata->atacmd.sector_count = 1;
-
- return 0;
}
-void ata_setdataout_params(ATA *ata, char ** databuf, int nbytes)
+char*
+ata_setup_buffer(ATA *ata, int nbytes)
{
- *databuf = (char*) ata->atacmd.buf;
+ 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;
+ }
-void ata_setfeature_param(ATA *ata, int feature)
+ return ata;
+}
+
+void
+ata_close(ATA *ata)
{
- ata->atacmd.feature = feature;
+ if (ata->ata_fd >= 0)
+ close(ata->ata_fd);
+
+ free(ata);
+}
+
+void
+ata_free(ATA *ata)
+{
+ /* nothing to do */
}
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/linux/ataidle.h
^
|
@@ -1,7 +1,7 @@
/*-
- *
- * Copyright 2004-2008 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
- *
+ *
+ * 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:
@@ -12,7 +12,7 @@
* 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.
@@ -23,7 +23,7 @@
* 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.
- *
+ *
*/
@@ -31,7 +31,6 @@
#define ATAIDLE_H
#include <stdint.h>
-#include <stdbool.h>
struct ata_cmd {
unsigned char cmd;
@@ -41,4 +40,15 @@
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 */
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/main.c
^
|
@@ -1,6 +1,6 @@
/*-
*
- * Copyright 2004-2008 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
+ * 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
@@ -28,19 +28,12 @@
#include <err.h>
#include <errno.h>
-#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <sysexits.h>
#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include "mi/atadefs.h"
-#include "mi/util.h"
#include "mi/atagen.h"
#ifdef __FreeBSD__
@@ -51,100 +44,76 @@
#endif
#endif
-int main( int argc, char ** argv )
+int
+main(int argc, char ** argv)
{
int rc = 0;
- ATA *ata;
+ ATA *ata = NULL;
long opt_val;
int ch;
struct ata_ident ident;
- const char * const optstr = "hA:S:sI:iP:o";
-
- ata = malloc(sizeof(ATA));
-
- if (ata == NULL)
- err(EX_SOFTWARE, NULL);
+ const char * const optstr = "hA:S:sI:iP:owW";
/* need more than just the executable name */
if( argc == 1 )
usage();
- ata->fd = -1;
+ ata = ata_open(argv[argc-1]);
- /* now we've done all the checking of parameters etc.,
- * let's see what the user wants us to do.
- */
-
- /* if we've got a non-option string,
- * see if it's a device node */
- if (argv[argc-1][0] != '-') {
- struct stat sb;
- rc = stat( argv[argc-1], &sb );
- if (rc)
- err(EX_OSFILE, "%s", argv[argc-1]);
-
- if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode))
- rc = open( argv[argc-1], O_RDONLY );
- else
- errx(EX_OSFILE, "%s isn't a device node", argv[argc-1]);
-
- if (rc > 0)
- ata->fd = rc;
- else
- err(EX_IOERR, "error opening %s", argv[argc-1]);
-
- if (argc == 2)
- ata_showdeviceinfo(ata);
- }
+ if (ata == NULL)
+ errx(1, "error opening %s", argv[argc-1]);
- optind = 1;
- opterr = 1;
+ rc = ata_identify(ata, &ident);
- if (ata->fd != -1) {
- rc = ata_ident( ata, &ident );
- if (rc)
- errx(EX_SOFTWARE, "an error occurred identifying the device %s\n", argv[argc-1]);
- }
+ 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)
{
- /* S = Standby */
+ /* Standby */
case 'S':
- opt_val = strtol( optarg, NULL, 10 );
- if(opt_val == LONG_MIN || opt_val == LONG_MAX)
- warnx("invalid standby value");
+ 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 );
+ 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 );
+ rc = ata_setstandbytimer(ata, ATA_IDLEVAL_IMMEDIATE);
break;
/* o = Sleep (off) */
case 'o':
if (ident.cmd_supp1 & ATA_PM_SUPPORTED)
- rc = ata_sleep( ata );
+ rc = ata_sleep(ata);
else
warnx("the device does not support power management");
break;
- /* I = Idle */
+ /* Idle */
case 'I':
- opt_val = strtol( optarg, NULL, 10 );
+ opt_val = strtol(optarg, NULL, 10);
- if(opt_val == LONG_MIN || opt_val == LONG_MAX)
- warnx("invalid idle value");
+ 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 );
+ rc = ata_setidletimer(ata, opt_val);
else
warnx("the device does not support power management");
}
@@ -154,32 +123,52 @@
rc = ata_setidletimer(ata, ATA_IDLEVAL_IMMEDIATE);
break;
- /* A = AutoAcoustic */
+ /* Acoustic */
case 'A':
- opt_val = strtol( optarg, NULL, 10 );
- if(opt_val == LONG_MIN || opt_val == LONG_MAX)
- warnx("invalid acoustic value");
+ 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 );
+ rc = ata_setacoustic(ata, opt_val);
else
warnx("the device does not support acoustic management");
}
break;
- /* P = Power (APM) */
+ /* Power (APM) */
case 'P':
- opt_val = strtol( optarg, NULL, 10 );
- if(opt_val == LONG_MIN || opt_val == LONG_MAX)
- warnx("invalid apm value");
+ 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 );
+ rc = ata_setapm(ata, opt_val);
else
warnx("the device does not support advanced power management");
}
break;
+ /* Write Cache Disable */
+ case 'w':
+ if (!(ident.cmd_supp1 & ATA_WC_SUPPORTED)) {
+ warnx("the device does not support write cache");
+ break;
+ }
+ rc = ata_setwc(ata, 0);
+ break;
+
+ /* Write Cache Enable */
+ case 'W':
+ if (!(ident.cmd_supp1 & ATA_WC_SUPPORTED)) {
+ warnx("the device does not support write cache");
+ break;
+ }
+ rc = ata_setwc(ata, 1);
+ break;
+
case 'h':
default:
usage();
@@ -188,13 +177,8 @@
}
if (ata != NULL)
- {
- if (ata->fd > 0)
- close(ata->fd);
+ ata_close(ata);
- free(ata);
- }
-
return (rc);
}
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/mi/atagen.h
^
|
@@ -1,29 +1,30 @@
/*-
-* Copyright 2004-2008 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.
-*
-*/
+ *
+ * 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) */
@@ -33,6 +34,15 @@
#include <stdint.h>
#include <stdbool.h>
+#define ATAIDLE_VERSION "2.7.1"
+
+enum DISK_PROTO
+{
+ DISK_PROTO_ATA,
+ DISK_PROTO_ATA_CAM,
+ DISK_PROTO_SCSI
+};
+
#ifdef __FreeBSD__
#include <osreldate.h>
#include <sys/ata.h>
@@ -41,6 +51,50 @@
#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_WC_SUPPORTED 0x0020
+#define ATA_WC_ENABLED 0x0020
+
+#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_WC_ENABLE 0x02
+#define ATA_WC_DISABLE 0x82
+#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;
@@ -104,41 +158,24 @@
uint16_t integrity;
};
-#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
-
-typedef struct
-{
- int fd;
- uint32_t chan;
- uint32_t dev;
- uint32_t cmd;
- struct ata_cmd atacmd;
-} ATA;
-
-int ata_open( ATA *ata, 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 drivercmd );
-bool ata_devpresent( ATA *ata );
-int ata_ident( ATA *ata, struct ata_ident * identity);
-void ata_showdeviceinfo( ATA *ata );
-void ata_setfeature_param( ATA *ata, int feature_val);
-int ata_setataparams( ATA *ata, int seccount, int count);
-void ata_setdataout_params( ATA *ata, char ** databuf, int nbytes);
+ATA* ata_open(const char *device);
+void ata_close(ATA *ata);
+int ata_setidletimer(ATA *ata, uint32_t idle_mins);
+int ata_setwc(ATA *ata, int enable);
+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 */
|
[-]
[+]
|
Changed |
ataidle-2.7.1.tar.bz2/mi/util.c
^
|
@@ -1,5 +1,6 @@
/*-
- * Copyright 2004-2008 Bruce Cran <bruce@cran.org.uk>. All rights reserved.
+ *
+ * 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
@@ -32,17 +33,21 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sysexits.h>
#include <unistd.h>
-#include "atadefs.h"
#include "atagen.h"
-#include "util.h"
static int is_big_endian(void);
-
-/* calculate the idle timer value to send to the drive. */
-int ata_getidleval(uint32_t idle_mins, uint16_t *timer_val)
+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;
@@ -60,86 +65,90 @@
/* there is no encoding for values between 21 and 30 minutes */
if( (idle_mins > 21) && (idle_mins < 30) ) {
- printf("cannot set timeout for values 20-30 minutes\n" );
- rc = -2;
+ 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 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))
+ if ((((idle_mins % 30) != 0) || (idle_mins > 330))
&& (idle_mins != ATA_IDLEVAL_IMMEDIATE) )
{
- printf( "idle value must be a multiple of 30 minutes, "
- "up to 5 hours\n" );
- rc = -2;
+ 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 = 241 + (idle_mins/30);
+ *timer_val = 240 + (idle_mins/30);
}
return rc;
}
-
-char * ata_getversionstring( unsigned short ata_version )
+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 */
+ 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 ) {
+ for (i = 0; i < 15; i++) {
+ if ((ata_version >> i) > 0)
sprintf(version, "ATA-%d", i);
- }
}
return version;
}
-
-void usage(void)
+void
+usage(void)
{
- printf( "ataidle version " ATAIDLE_VERSION "\n\n"
+ printf("ataidle version " ATAIDLE_VERSION "\n\n"
"usage: \n"
- "ataidle [-h] [-i] [-s] [-o] [-I idle] [-S standby] [-A acoustic] [-P apm]\n"
- "\tdevice\n\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 and exit\n"
- "-I\t\tset the idle timeout in minutes\n"
- "-i\t\tput the drive into idle mode\n"
- "-S\t\tset the standby timeout in minutes\n"
- "-s\t\tput the drive into standby mode\n"
- "-o\t\tput the drive into sleep mode\n"
- "-A\t\tset the acoustic level, values 1-127\n"
- "-P\t\tset the power management level, values 1-254\n"
- "device\t\tthe device node e.g /dev/ad0\n\n"
- "if no options are specified, information\n"
- "about the device will be displayed\n\n");
+ "-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"
+ "-W\t\tenable the write cache\n"
+ "-w\t\tdisable the write cache\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(EX_USAGE);
+ exit(1);
}
-void byteswap(char * buf, int from, int to)
+static void
+byteswap(char * buf, int from, int to)
{
int i;
- for(i = from; i <= to; i+=2)
+
+ for (i = from; i <= to; i+=2)
{
char b1 = buf[i];
buf[i] = buf[i+1];
@@ -147,13 +156,15 @@
}
}
-void strpack(char * buf, int from, int to)
+/* 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 == 0) { /* malloc failed, skip the string packing */
+ if(tmpbuf == NULL) { /* malloc failed, skip the string packing */
fprintf(stderr, "malloc failed\n");
return;
}
@@ -178,7 +189,9 @@
free(tmpbuf);
}
-void mem_swap(int16_t * val)
+/* swap the bytes */
+static void
+mem_swap(int16_t * val)
{
int8_t * smallval = (int8_t*) val;
int8_t tmp = smallval[0];
@@ -187,17 +200,18 @@
smallval[1] = tmp;
}
-static int is_big_endian(void)
+/* 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 )
+void
+ata_showdeviceinfo(ATA *ata, struct ata_ident ident)
{
- int rc = 0;
- struct ata_ident ident;
int16_t *buf;
unsigned int mbsize;
char model[41];
@@ -205,15 +219,6 @@
char firmware[9];
char *ata_version = NULL;
- memset(&ident, 0, sizeof(struct ata_ident));
-
- rc = ata_ident( ata,(struct ata_ident*) &ident );
-
- if (rc) {
- printf("could not get device information: is a device attached?\n");
- return;
- }
-
buf = (int16_t*) &ident;
memset(model, 0, 41);
@@ -227,61 +232,87 @@
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]);
+ ata_version = ata_getversionstring(ident.version_major);
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]);
+ printf("LBA 48:\t\t\t%s\n", (ident.cmd_enabled2 & 0x400)? "yes" : "no");
+ printf("Geometry:\t\t%d cyls, %d heads, %d spt\n",
+ ident.word1, ident.word3, ident.word6);
if (ata_version != NULL)
free(ata_version);
mbsize = 0;
- if (buf[86] & 0x400)
+ if (ident.cmd_enabled2 & 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
+ else
{
mbsize = ((ident.nsect[0] + (ident.nsect[1] << 16))*512)/1048576;
}
+ bool smart_supported = ident.cmd_supp1 & ATA_SMART_SUPPORTED;
+ bool smart_enabled = ident.cmd_enabled1 & ATA_SMART_ENABLED;
+ bool wc_supported = ident.cmd_supp1 & ATA_WC_SUPPORTED;
+ bool wc_enabled = ident.cmd_enabled1 & ATA_WC_ENABLED;
+ bool apm_supported = ident.cmd_supp2 & ATA_APM_SUPPORTED;
+ bool apm_enabled = ident.cmd_enabled2 & ATA_APM_ENABLED;
+ bool aam_supported = ident.cmd_supp2 & ATA_AAM_SUPPORTED;
+ bool aam_enabled = ident.cmd_enabled2 & 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", (buf[82] & 1)? "yes" : "no" );
- if(buf[82] & 1)
- printf("SMART Enabled: \t\t%s\n", (buf[85] & 1)? "yes" : "no" );
- printf("APM Supported: \t\t%s\n", (buf[83] & 8)? "yes" : "no" );
- if(buf[83] & 8)
- printf("APM Enabled: \t\t%s\n", (buf[86] & 8)? "yes" : "no" );
- printf("AAM Supported: \t\t%s\n", (buf[83] & 0x200)? "yes" : "no" );
- printf("AAM Enabled: \t\t%s\n", (buf[86] & 0x200)? "yes" : "no");
- if((buf[86] & 0x200)) {
- printf("Current AAM: \t\t%d\n", ((buf[94] & 0x00FF))-127);
- printf("Vendor Recommends AAM: \t%d\n", ((buf[94] & 0xFF00) >> 8)-127);
+
+ 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("Write Cache Supported: \t%s\n", wc_supported? "yes" : "no" );
+
+ if (wc_supported)
+ printf("Write Cache Enabled: \t%s\n", wc_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", ident.apm_value);
}
- if((buf[86] & 8))
- 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", ((ident.aam_value & 0x00FF))-127);
+
+ printf("Vendor Recommended AAM: %d\n", ((ident.aam_value & 0xFF00) >> 8)-127);
+ }
}
-void byteswap_ata_data( int16_t * buf )
+static void
+byteswap_ata_data(int16_t * buf)
{
int i;
- for (i = 0; i < 10; i++)
+ for (i = 0; i < 10; i++) {
mem_swap(buf+i);
+ }
- for (i = 20; i < 23; i++)
+ for (i = 20; i < 23; i++) {
mem_swap(buf+i);
+ }
- for (i = 47; i < 255; i++)
+ for (i = 47; i < 255; i++) {
mem_swap(buf + i);
-
+ }
}
/*
@@ -290,40 +321,50 @@
* lowest (least performance) to highest power consumption, which results
* in the highest performance.
*/
-int ata_setapm( ATA *ata, uint32_t apm_val)
+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) {
- printf("invalid APM value: must be %d-%d\n", ATA_APM_MINPERF, 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_setataparams(ata, apm_val, 0);
- ata_setfeature_param(ata, ATA_APM_ENABLE);
+ ata_init(ata);
if(apm_val == 0)
- ata_setfeature_param(ata, ATA_APM_DISABLE);
+ 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, 0);
+ rc = ata_cmd(ata, ATA__SETFEATURES, apm_onoff_setting, apm_val);
- if(rc) {
- perror("set APM failed");
- } else {
- printf("APM set to %d\n", apm_val);
- if(apm_val == ATA_APM_MAXPERF)
- printf("APM set to highest power consumption\n");
- else if(apm_val == ATA_APM_MINPERF)
- printf("APM set to lowest power consumption\n");
- else if(apm_val == 0)
- printf("APM Disabled\n");
- }
+ if(rc)
+ perror("Failed to configure APM");
}
+
+ return rc;
+}
+
+int
+ata_setwc(ATA *ata, int enable)
+{
+ int rc, cmd;
+
+ /* allocate and initialize the ata_cmd structure */
+ ata_init(ata);
+ cmd = enable ? ATA_WC_ENABLE : ATA_WC_DISABLE;
+ rc = ata_cmd(ata, ATA__SETFEATURES, cmd, 0);
+ if(rc)
+ perror("Failed to configure Write Cache");
return rc;
}
@@ -331,49 +372,41 @@
* 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
+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) {
- printf("invalid acoustic value: must be %d-%d\n", 1, ATA_AUTOACOUSTIC_MAXPERF - aam_user_offset);
- rc = -1;
+ fprintf(stderr, "Invalid acoustic value: must be %d-%d\n",
+ 1, ATA_AUTOACOUSTIC_MAXPERF - aam_user_offset);
+ rc = 1;
}
- ata_setataparams(ata, acoustic_val, 0);
- ata_setfeature_param(ata, ATA_AUTOACOUSTIC_ENABLE);
+ ata_init(ata);
/* disable AAM if user specified 0, which is 127 once offset */
if(acoustic_val == 127)
- ata_setfeature_param(ata, ATA_AUTOACOUSTIC_DISABLE);
+ aam_onoff_setting = ATA_AUTOACOUSTIC_DISABLE;
+ else
+ aam_onoff_setting = ATA_AUTOACOUSTIC_ENABLE;
- /* send the drive a SET_FEATURES command
- * with a FEATURE of ATA_AUTOACOUSTIC_ENABLE
- */
if(!rc) {
- rc = ata_cmd( ata, ATA__SETFEATURES, 0 );
+ rc = ata_cmd(ata, ATA__SETFEATURES, aam_onoff_setting, acoustic_val);
if(rc)
- perror("set AAM failed");
- else
- {
- printf("AAM set to %d\n", acoustic_val-aam_user_offset);
- if(acoustic_val == ATA_AUTOACOUSTIC_MAXPERF)
- printf("AAM set to maximum performance\n");
- else if(acoustic_val == ATA_AUTOACOUSTIC_MINPERF)
- printf("AAM set to quietest setting\n");
- else if(acoustic_val == 127)
- printf("AAM disabled\n");
- }
+ 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)
+int
+ata_setidletimer(ATA *ata, uint32_t idle_mins)
{
uint16_t timer_val = 0;
int rc = 0;
@@ -381,110 +414,92 @@
rc = ata_getidleval( idle_mins, &timer_val );
if(timer_val == ATA_IDLEVAL_IMMEDIATE)
- ata_setataparams(ata, 0, 0);
+ ata_init(ata);
else
- ata_setataparams(ata, timer_val, 0);
+ ata_init(ata);
/* send the IDLE command to the drive */
- if(!rc) {
+ if (!rc) {
if(timer_val == ATA_IDLEVAL_IMMEDIATE)
- rc = ata_cmd(ata, ATA_IDLE_IMMEDIATE, 0);
+ rc = ata_cmd(ata, ATA_IDLE_IMMEDIATE, 0, 0);
else
- rc = ata_cmd(ata, ATA_IDLE, 0);
+ rc = ata_cmd(ata, ATA_IDLE, 0, timer_val);
}
- if(rc)
- {
- if(rc == -2)
- printf("error setting idle timeout\n");
- else
- perror("error setting idle timeout");
- }
- else
+ if (rc)
{
- if(timer_val == ATA_IDLEVAL_IMMEDIATE)
- printf("drive set to idle immediately\n");
- else if(timer_val == 0)
- printf("turned off idle timer\n");
- else
- printf("idle timer set to %d minutes\n", idle_mins);
+ fprintf(stderr, "Failed to configure idle mode.\n");
}
+
return rc;
}
/* comand the drive to go into sleep mode */
-int ata_sleep(ATA *ata)
+int
+ata_sleep(ATA *ata)
{
int rc = 0;
- ata_setataparams(ata, 0, 0);
+ ata_init(ata);
/* send the SLEEP command to the drive */
- rc = ata_cmd(ata, ATA_SLEEP, 0);
+ rc = ata_cmd(ata, ATA_SLEEP, 0, 0);
if (rc)
- {
- perror("error setting sleep mode");
- }
- else
- {
- printf("drive set to sleep\n");
- }
+ 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)
+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 (timer_val == ATA_IDLEVAL_IMMEDIATE)
- ata_setataparams(ata, 0, 0);
- else
- ata_setataparams(ata, timer_val, 0);
+ if (rc)
+ return rc;
+
+ ata_init(ata);
/* send the STANDBY command to the drive */
- if(!rc)
+ if (!rc)
{
if(timer_val == ATA_IDLEVAL_IMMEDIATE)
- rc = ata_cmd(ata, ATA_STANDBY_IMMEDIATE, 0);
+ rc = ata_cmd(ata, ATA_STANDBY_IMMEDIATE, 0, 0);
else
- rc = ata_cmd(ata, ATA_STANDBY, 0);
+ rc = ata_cmd(ata, ATA_STANDBY, 0, timer_val);
}
- if(rc)
+
+ if (rc)
{
- perror("error setting idle timeout");
- } else {
- if( timer_val == ATA_IDLEVAL_IMMEDIATE )
- printf("drive set to standby immediately\n");
- else if(timer_val == 0)
- printf("turned off standby timer\n");
- else
- printf("standby timer set to %d minutes\n", standby_mins);
+ perror("Failed to configure standby timer");
}
+
return rc;
}
/* this function sends an IDENTIFY command to a drive */
-int ata_ident(ATA *ata, struct ata_ident * identity)
+int
+ata_identify(ATA *ata, struct ata_ident * identity)
{
int rc = 0;
- char * buf = NULL;
+ char *buf;
- ata_setataparams(ata, 0, 0);
- ata_setdataout_params(ata, &buf, 512);
- rc = ata_cmd(ata, ATA__IDENTIFY, 0);
+ ata_init(ata);
+ buf = ata_setup_buffer(ata, 512);
+ rc = ata_cmd(ata, ATA__IDENTIFY, 0, 0);
- if(rc)
+ if (rc)
{
- /* then try an ATAPI IDENTIFY, maybe it didn't like an ATA_IDENTIFY */
- ata_setataparams(ata, 0, 0);
- ata_setdataout_params(ata, &buf, 512);
- rc = ata_cmd(ata, ATA__ATAPI_IDENTIFY, 0);
+ /* 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)
@@ -498,17 +513,8 @@
if (is_big_endian())
byteswap_ata_data((int16_t*)buf);
- if(!rc)
+ if (!rc)
memcpy(identity, buf, sizeof(struct ata_ident));
return rc;
}
-
-void hexdump(const char *data, int count)
-{
- int i;
- for (i = 0; i < count; i++)
- {
- printf( "%c ", data[i]);
- }
-}
|