Commit aad52673 authored by (no author)'s avatar (no author)
Browse files

This commit was manufactured by cvs2svn to create tag

'RELEASE_5_0_9'.

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/tags/RELEASE_5_0_9@56 4ea69e1a-61f1-4043-bf83-b5c94c648137
parent c80bf8c9
# The "checkoutlist" file is used to support additional version controlled
# administrative files in $CVSROOT/CVSROOT, such as template files.
#
# The first entry on a line is a filename which will be checked out from
# the corresponding RCS file in the $CVSROOT/CVSROOT directory.
# The remainder of the line is an error message to use if the file cannot
# be checked out.
#
# File format:
#
# [<whitespace>]<filename><whitespace><error message><end-of-line>
#
# comment lines begin with '#'
# The "commitinfo" file is used to control pre-commit checks.
# The filter on the right is invoked with the repository and a list
# of files to check. A non-zero exit of the filter program will
# cause the commit to be aborted.
#
# The first entry on a line is a regular expression which is tested
# against the directory that the change is being committed to, relative
# to the $CVSROOT. For the first match that is found, then the remainder
# of the line is the name of the filter to run.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name "ALL" appears as a regular expression it is always used
# in addition to the first matching regex or "DEFAULT".
# Set this to "no" if pserver shouldn't check system users/passwords
#SystemAuth=no
# Put CVS lock files in this directory rather than directly in the repository.
#LockDir=/var/lock/cvs
# Set `TopLevelAdmin' to `yes' to create a CVS directory at the top
# level of the new working directory when using the `cvs checkout'
# command.
#TopLevelAdmin=no
# Set `LogHistory' to `all' or `TOFEWGCMAR' to log all transactions to the
# history file, or a subset as needed (ie `TMAR' logs all write operations)
#LogHistory=TOFEWGCMAR
# This file affects handling of files based on their names.
#
# The -t/-f options allow one to treat directories of files
# as a single file, or to transform a file in other ways on
# its way in and out of CVS.
#
# The -m option specifies whether CVS attempts to merge files.
#
# The -k option specifies keyword expansion (e.g. -kb for binary).
#
# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
#
# wildcard [option value][option value]...
#
# where option is one of
# -f from cvs filter value: path to filter
# -t to cvs filter value: path to filter
# -m update methodology value: MERGE or COPY
# -k expansion mode value: b, o, kkv, &c
#
# and value is a single-quote delimited value.
# For example:
#*.gif -k 'b'
# The "editinfo" file is used to allow verification of logging
# information. It works best when a template (as specified in the
# rcsinfo file) is provided for the logging procedure. Given a
# template with locations for, a bug-id number, a list of people who
# reviewed the code before it can be checked in, and an external
# process to catalog the differences that were code reviewed, the
# following test can be applied to the code:
#
# Making sure that the entered bug-id number is correct.
# Validating that the code that was reviewed is indeed the code being
# checked in (using the bug-id number or a seperate review
# number to identify this particular code set.).
#
# If any of the above test failed, then the commit would be aborted.
#
# Actions such as mailing a copy of the report to each reviewer are
# better handled by an entry in the loginfo file.
#
# One thing that should be noted is the the ALL keyword is not
# supported. There can be only one entry that matches a given
# repository.
# The "loginfo" file controls where "cvs commit" log information
# is sent. The first entry on a line is a regular expression which must match
# the directory that the change is being made to, relative to the
# $CVSROOT. If a match is found, then the remainder of the line is a filter
# program that should expect log information on its standard input.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name ALL appears as a regular expression it is always used
# in addition to the first matching regex or DEFAULT.
#
# You may specify a format string as part of the
# filter. The string is composed of a `%' followed
# by a single format character, or followed by a set of format
# characters surrounded by `{' and `}' as separators. The format
# characters are:
#
# s = file name
# V = old version number (pre-checkin)
# v = new version number (post-checkin)
#
# For example:
#DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog
# or
#DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog
# Three different line formats are valid:
# key -a aliases...
# key [options] directory
# key [options] directory files...
#
# Where "options" are composed of:
# -i prog Run "prog" on "cvs commit" from top-level of module.
# -o prog Run "prog" on "cvs checkout" of module.
# -e prog Run "prog" on "cvs export" of module.
# -t prog Run "prog" on "cvs rtag" of module.
# -u prog Run "prog" on "cvs update" of module.
# -d dir Place module in directory "dir" instead of module name.
# -l Top-level directory only -- do not recurse.
#
# NOTE: If you change any of the "Run" options above, you'll have to
# release and re-checkout any working directories of these modules.
#
# And "directory" is a path to a directory relative to $CVSROOT.
#
# The "-a" option specifies an alias. An alias is interpreted as if
# everything on the right of the "-a" had been typed on the command line.
#
# You can encode a module within a module by using the special '&'
# character to interpose another module into the current module. This
# can be useful for creating a module that consists of many directories
# spread out over the entire source repository.
# The "notify" file controls where notifications from watches set by
# "cvs watch add" or "cvs edit" are sent. The first entry on a line is
# a regular expression which is tested against the directory that the
# change is being made to, relative to the $CVSROOT. If it matches,
# then the remainder of the line is a filter program that should contain
# one occurrence of %s for the user to notify, and information on its
# standard input.
#
# "ALL" or "DEFAULT" can be used in place of the regular expression.
#
# For example:
#ALL mail %s -s "CVS notification"
# The "rcsinfo" file is used to control templates with which the editor
# is invoked on commit and import.
#
# The first entry on a line is a regular expression which is tested
# against the directory that the change is being made to, relative to the
# $CVSROOT. For the first match that is found, then the remainder of the
# line is the name of the file that contains the template.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name "ALL" appears as a regular expression it is always used
# in addition to the first matching regex or "DEFAULT".
# The "taginfo" file is used to control pre-tag checks.
# The filter on the right is invoked with the following arguments:
#
# $1 -- tagname
# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d
# $3 -- repository
# $4-> file revision [file revision ...]
#
# A non-zero exit of the filter program will cause the tag to be aborted.
#
# The first entry on a line is a regular expression which is tested
# against the directory that the change is being committed to, relative
# to the $CVSROOT. For the first match that is found, then the remainder
# of the line is the name of the filter to run.
#
# If the repository name does not match any of the regular expressions in this
# file, the "DEFAULT" line is used, if it is specified.
#
# If the name "ALL" appears as a regular expression it is always used
# in addition to the first matching regex or "DEFAULT".
# The "verifymsg" file is used to allow verification of logging
# information. It works best when a template (as specified in the
# rcsinfo file) is provided for the logging procedure. Given a
# template with locations for, a bug-id number, a list of people who
# reviewed the code before it can be checked in, and an external
# process to catalog the differences that were code reviewed, the
# following test can be applied to the code:
#
# Making sure that the entered bug-id number is correct.
# Validating that the code that was reviewed is indeed the code being
# checked in (using the bug-id number or a seperate review
# number to identify this particular code set.).
#
# If any of the above test failed, then the commit would be aborted.
#
# Actions such as mailing a copy of the report to each reviewer are
# better handled by an entry in the loginfo file.
#
# One thing that should be noted is the the ALL keyword is not
# supported. There can be only one entry that matches a given
# repository.
// $Id: atacmds.cpp,v 1.8 2002/10/15 14:24:26 ballen4705 Exp $
/*
* atacmds.c
*
* Home page of code is: http://smartmontools.sourceforge.net
*
* Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
* Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
*/
#include <stdio.h>
#include <string.h>
#include "atacmds.h"
// These Drive Identity tables are taken from hdparm 5.2. That's the
// "Gold Standard"
#define NOVAL_0 0x0000
#define NOVAL_1 0xffff
/* word 81: minor version number */
#define MINOR_MAX 0x1C
const char *minor_str[] = { /* word 81 value: */
"Device does not report version", /* 0x0000 */
"ATA-1 X3T9.2 781D prior to revision 4", /* 0x0001 */
"ATA-1 published, ANSI X3.221-1994", /* 0x0002 */
"ATA-1 X3T9.2 781D revision 4", /* 0x0003 */
"ATA-2 published, ANSI X3.279-1996", /* 0x0004 */
"ATA-2 X3T10 948D prior to revision 2k", /* 0x0005 */
"ATA-3 X3T10 2008D revision 1", /* 0x0006 */
"ATA-2 X3T10 948D revision 2k", /* 0x0007 */
"ATA-3 X3T10 2008D revision 0", /* 0x0008 */
"ATA-2 X3T10 948D revision 3", /* 0x0009 */
"ATA-3 published, ANSI X3.298-199x", /* 0x000a */
"ATA-3 X3T10 2008D revision 6", /* 0x000b */
"ATA-3 X3T13 2008D revision 7 and 7a", /* 0x000c */
"ATA/ATAPI-4 X3T13 1153D revision 6", /* 0x000d */
"ATA/ATAPI-4 T13 1153D revision 13", /* 0x000e */
"ATA/ATAPI-4 X3T13 1153D revision 7", /* 0x000f */
"ATA/ATAPI-4 T13 1153D revision 18", /* 0x0010 */
"ATA/ATAPI-4 T13 1153D revision 15", /* 0x0011 */
"ATA/ATAPI-4 published, ANSI NCITS 317-1998", /* 0x0012 */
"ATA/ATAPI-5 T13 1321D revision 3", /* 0x0013 */
"ATA/ATAPI-4 T13 1153D revision 14", /* 0x0014 */
"ATA/ATAPI-5 T13 1321D revision 1", /* 0x0015 */
"ATA/ATAPI-5 published, ANSI NCITS 340-2000", /* 0x0016 */
"ATA/ATAPI-4 T13 1153D revision 17", /* 0x0017 */
"ATA/ATAPI-6 T13 1410D revision 0", /* 0x0018 */
"ATA/ATAPI-6 T13 1410D revision 3a", /* 0x0019 */
"Reserved", /* 0x001a */
"ATA/ATAPI-6 T13 1410D revision 2", /* 0x001b */
"ATA/ATAPI-6 T13 1410D revision 1", /* 0x001c */
"reserved" /* 0x001d */
"reserved" /* 0x001e */
"reserved" /* 0x001f-0xfffe*/
};
const char actual_ver[] = {
/* word 81 value: */
0, /* 0x0000 WARNING: */
1, /* 0x0001 WARNING: */
1, /* 0x0002 WARNING: */
1, /* 0x0003 WARNING: */
2, /* 0x0004 WARNING: This array */
2, /* 0x0005 WARNING: corresponds */
3, /* 0x0006 WARNING: *exactly* */
2, /* 0x0007 WARNING: to the ATA/ */
3, /* 0x0008 WARNING: ATAPI version */
2, /* 0x0009 WARNING: listed in */
3, /* 0x000a WARNING: the */
3, /* 0x000b WARNING: minor_str */
3, /* 0x000c WARNING: array */
4, /* 0x000d WARNING: above. */
4, /* 0x000e WARNING: */
4, /* 0x000f WARNING: If you change */
4, /* 0x0010 WARNING: that one, */
4, /* 0x0011 WARNING: change this one */
4, /* 0x0012 WARNING: too!!! */
5, /* 0x0013 WARNING: */
4, /* 0x0014 WARNING: */
5, /* 0x0015 WARNING: */
5, /* 0x0016 WARNING: */
4, /* 0x0017 WARNING: */
6, /* 0x0018 WARNING: */
6, /* 0x0019 WARNING: */
0, /* 0x001a WARNING: */
6, /* 0x001b WARNING: */
6, /* 0x001c WARNING: */
0 /* 0x001d-0xfffe */
};
int ataReadHDIdentity ( int device, struct hd_driveid *buf)
{
if (ioctl ( device , HDIO_GET_IDENTITY, buf ) != 0)
{
perror ("ATA GET HD Failed");
return -1;
}
return 0;
}
int ataVersionInfo (const char** description, struct hd_driveid drive){
unsigned short major,minor;
int i,atavalue=0;
// get major and minor ATA revision numbers
#ifdef __NEW_HD_DRIVE_ID
major=drive.major_rev_num;
minor=drive.minor_rev_num;
#else
major=drive.word80;
minor=drive.word81;
#endif
// First check if device has ANY ATA version information in it
if (major==NOVAL_0 || major==NOVAL_1) {
*description=NULL;
return -1;
}
// The minor revision number has more information - try there first
if (minor && (minor<=MINOR_MAX)){
int std = actual_ver[minor];
if (std) {
*description=minor_str[minor];
return std;
}
}
// HDPARM has a very complicated algorithm from here on. Since SMART only
// exists on ATA-3 and later standards, let's punt on this. If you don't
// like it, please fix it. The code's in CVS.
for (i=1; i<16;i++ )
if (major & (0x1<<i))
atavalue = i;
*description=NULL;
return atavalue;
}
int ataSmartSupport ( struct hd_driveid drive){
#ifdef __NEW_HD_DRIVE_ID
if (drive.command_set_1 & 0x0001)
#else
if (drive.command_sets & 0x0001)
#endif
return 1; /* drive supports S.M.A.R.T. and is disabled */
return 0;
}
int ataReadSmartValues (int device, struct ata_smart_values *data){
int i;
unsigned char chksum=0;
unsigned char buf[HDIO_DRIVE_CMD_HDR_SIZE+ATA_SMART_SEC_SIZE]=
{WIN_SMART, 0, SMART_READ_VALUES, 1};
if (ioctl(device,HDIO_DRIVE_CMD,buf)){
perror ("Smart Values Read failed");
return -1;
}
// compute checksum
for (i=0;i<ATA_SMART_SEC_SIZE;i++)
chksum+=buf[i+HDIO_DRIVE_CMD_HDR_SIZE];
// verify that checksum vanishes
if (chksum){
perror ("Smart Read Failed, Checksum error!");
return -1;
}
// copy data and return
memcpy(data,buf+HDIO_DRIVE_CMD_HDR_SIZE,ATA_SMART_SEC_SIZE);
return 0;
}
int ataReadSelfTestLog (int device, struct ata_smart_selftestlog *data)
{
int i;
unsigned char chksum=0;
unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE +
ATA_SMART_SEC_SIZE] =
{ WIN_SMART, 0x06, SMART_READ_LOG_SECTOR, 1};
if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
{
perror ("Smart Error Log Read failed");
return -1;
}
// compute checksum
for (i=0;i<ATA_SMART_SEC_SIZE;i++)
chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
if (chksum){
fprintf(stderr,"Smart Self Test Log Checksum Incorrect!\n");
return -1;
}
memcpy( data, &buf[HDIO_DRIVE_CMD_HDR_SIZE] , ATA_SMART_SEC_SIZE);
return 0;
}
int ataReadErrorLog (int device, struct ata_smart_errorlog *data)
{
int i;
unsigned char chksum=0;
unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE +
ATA_SMART_SEC_SIZE] =
{ WIN_SMART, 0x01, SMART_READ_LOG_SECTOR, 1};
if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
{
perror ("Smart Error Log Read failed");
return -1;
}
// compute checksum
for (i=0;i<ATA_SMART_SEC_SIZE;i++)
chksum+=buf[HDIO_DRIVE_CMD_HDR_SIZE+i];
if (chksum){
fprintf(stderr,"Smart Error Log Checksum Incorrect!\n");
return -1;
}
memcpy( data, &buf[HDIO_DRIVE_CMD_HDR_SIZE] , ATA_SMART_SEC_SIZE);
return 0;
}
int ataReadSmartThresholds ( int device, struct ata_smart_thresholds *data)
{
unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE +
ATA_SMART_SEC_SIZE] =
{ WIN_SMART, 1, SMART_READ_THRESHOLDS, 1};
if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
{
perror ("Smart Thresholds Read failed");
return -1;
}
memcpy( data, &buf[HDIO_DRIVE_CMD_HDR_SIZE] , ATA_SMART_SEC_SIZE);
return 0;
}
int ataSetSmartThresholds ( int device, struct ata_smart_thresholds *data)
{
unsigned char buf[ HDIO_DRIVE_CMD_HDR_SIZE +
ATA_SMART_SEC_SIZE] =
{ WIN_SMART, 1, 0xD7, 1};
memcpy( &buf[HDIO_DRIVE_CMD_HDR_SIZE], data , ATA_SMART_SEC_SIZE);
if (ioctl ( device , HDIO_DRIVE_CMD, (unsigned char *) &buf ) != 0)
{
perror ("Smart Thresholds Read failed");
return -1;
}
return 0;
}
int ataEnableSmart (int device )
{
unsigned char parms[4] = { WIN_SMART, 1, SMART_ENABLE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms ) != 0)
{
perror ("Smart Enable failed");
return -1;
}
return 0;
}
int ataDisableSmart (int device )
{
unsigned char parms[4] = { WIN_SMART, 1, SMART_DISABLE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms ) != 0)
{
perror ("Smart Disable failed");
return -1;
}
return 0;
}
int ataEnableAutoSave(int device){
unsigned char parms[4] = { WIN_SMART, 241, SMART_AUTOSAVE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms ) != 0)
{
perror ("Smart Enable Auto-save failed");
return -1;
}
return 0;
};
int ataDisableAutoSave(int device){
unsigned char parms[4] = { WIN_SMART, 0, SMART_AUTOSAVE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms ) != 0)
{
perror ("Smart Disable Auto-save failed");
return -1;
}
return 0;
};
int ataEnableAutoOffline (int device )
{
/* timer hard coded to 4 hours */
unsigned char parms[4] = { WIN_SMART, 248, SMART_AUTO_OFFLINE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms ) != 0)
{
perror ("Smart Enable Automatic Offline failed");
return -1;
}
return 0;
}
int ataDisableAutoOffline (int device )
{
unsigned char parms[4] = { WIN_SMART, 0, SMART_AUTO_OFFLINE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms ) != 0)
{
perror ("Smart Disable Automatic Offline failed");
return -1;
}
return 0;
}
// Not being used correctly. Must examine the CL and CH registers to
// see what the smart status was. How to fix this? I don't know...
int ataSmartStatus (int device ){
unsigned char parms[4] = { WIN_SMART, 0, SMART_STATUS, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms))
return -1;
return 0;
}
int ataSmartTest (int device, int testtype)
{
unsigned char parms[4] = { WIN_SMART, testtype,
SMART_IMMEDIATE_OFFLINE, 0};
if (ioctl ( device , HDIO_DRIVE_CMD, &parms) != 0)
{
perror ("Smart Offline failed");
return -1;
}
printf("Completed Off-line command\n");
return 0;
}
int ataSmartOfflineTest (int device)
{
return ataSmartTest( device, OFFLINE_FULL_SCAN );
}
int ataSmartShortSelfTest (int device)
{
return ataSmartTest( device, SHORT_SELF_TEST );
}
int ataSmartExtendSelfTest (int device)
{
return ataSmartTest( device, EXTEND_SELF_TEST );
}