Skip to content
Snippets Groups Projects
Commit 8b53cee0 authored by (no author)'s avatar (no author)
Browse files

This commit was manufactured by cvs2svn to create tag 'RELEASE_5_21'.

parent 2a113b5b
No related branches found
No related tags found
No related merge requests found
Showing with 0 additions and 7481 deletions
# 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
^sm5$ /cvsroot/sitedocs/CVSROOT/cvstools/syncmail -u %{sVv} smartmontools-cvs@lists.sourceforge.net
^www$ /cvsroot/sitedocs/CVSROOT/cvstools/syncmail -u %{sVv} ballen4705@users.sourceforge.net
# 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.
/*
* atacmdnames.c
*
* This module is based on the T13/1532D Volume 1 Revision 3 (ATA/ATAPI-7)
* specification, which is available from http://www.t13.org/#FTP_site
*
* Home page of code is: http://smartmontools.sourceforge.net
* Address of support mailing list: smartmontools-support@lists.sourceforge.net
*
* Copyright (C) 2003 Philip Williams
*
* 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.
*
*/
#include "atacmdnames.h"
#include <stdlib.h>
#include <stdio.h>
#define COMMAND_TABLE_SIZE 256
const char *atacmdnames_c_cvsid="$Id: atacmdnames.cpp,v 1.9 2003/08/13 12:33:22 ballen4705 Exp $" ATACMDNAMES_H_CVSID;
const char cmd_reserved[] = "[RESERVED]";
const char cmd_vendor_specific[] = "[VENDOR SPECIFIC]";
const char cmd_reserved_sa[] = "[RESERVED FOR SERIAL ATA]";
const char cmd_reserved_cf[] = "[RESERVED FOR COMPACTFLASH ASSOCIATION]";
const char cmd_reserved_mcpt[] = "[RESERVED FOR MEDIA CARD PASS THROUGH]";
const char cmd_recalibrate_ret4[]= "RECALIBRATE [RET-4]";
const char cmd_seek_ret4[] = "SEEK [RET-4]";
const char *command_table[COMMAND_TABLE_SIZE] = {
/*-------------------------------------------------- 00h-0Fh -----*/
"NOP",
cmd_reserved,
cmd_reserved,
"CFA REQUEST EXTENDED ERROR CODE",
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
"DEVICE RESET",
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
/*-------------------------------------------------- 10h-1Fh -----*/
"RECALIBRATE [OBS-4]",
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
cmd_recalibrate_ret4,
/*-------------------------------------------------- 20h-2Fh -----*/
"READ SECTOR(S)",
"READ SECTOR(S) [OBS-5]",
"READ LONG (w/ retry) [OBS-4]",
"READ LONG (w/o retry) [OBS-4]",
"READ SECTOR(S) EXT",
"READ DMA EXT",
"READ DMA QUEUED EXT",
"READ NATIVE MAX ADDRESS EXT",
cmd_reserved,
"READ MULTIPLE EXT",
"READ STREAM DMA",
"READ STREAM PIO",
cmd_reserved,
cmd_reserved,
cmd_reserved,
"READ LOG EXT",
/*-------------------------------------------------- 30h-3Fh -----*/
"WRITE SECTOR(S)",
"WRITE SECTOR(S) [OBS-5]",
"WRITE LONG(w/ retry) [OBS-4]",
"WRITE LONG(w/o retry) [OBS-4]",
"WRITE SECTORS(S) EXT",
"WRITE DMA EXT",
"WRITE DMA QUEUED EXT",
"SET MAX ADDRESS EXT",
"CFA WRITE SECTORS WITHOUT ERASE",
"WRITE MULTIPLE EXT",
"WRITE STREAM DMA",
"WRITE STREAM PIO",
"WRITE VERIFY [OBS-4]",
"WRITE DMA FUA EXT",
"WRITE DMA QUEUED FUA EXT",
"WRITE LOG EXT",
/*-------------------------------------------------- 40h-4Fh -----*/
"READ VERIFY SECTOR(S)",
"READ VERIFY SECTOR(S) [OBS-5]",
"READ VERIFY SECTOR(S) EXT",
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
/*-------------------------------------------------- 50h-5Fh -----*/
"FORMAT TRACK [OBS-4]",
"CONFIGURE STREAM",
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
/*-------------------------------------------------- 60h-6Fh -----*/
cmd_reserved_sa,
cmd_reserved_sa,
cmd_reserved_sa,
cmd_reserved_sa,
cmd_reserved_sa,
cmd_reserved_sa,
cmd_reserved_sa,
cmd_reserved_sa,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
/*-------------------------------------------------- 70h-7Fh -----*/
"SEEK [OBS-7]",
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
cmd_seek_ret4,
/*-------------------------------------------------- 80h-8Fh -----*/
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
"CFA TRANSLATE SECTOR [VS IF NO CFA]",
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
/*-------------------------------------------------- 90h-9Fh -----*/
"EXECUTE DEVICE DIAGNOSTIC",
"INITIALIZE DEVICE PARAMETERS [OBS-6]",
"DOWNLOAD MICROCODE",
cmd_reserved,
"STANDBY IMMEDIATE [RET-4]",
"IDLE IMMEDIATE [RET-4]",
"STANDBY [RET-4]",
"IDLE [RET-4]",
"CHECK POWER MODE [RET-4]",
"SLEEP [RET-4]",
cmd_vendor_specific,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
/*-------------------------------------------------- A0h-AFh -----*/
"PACKET",
"IDENTIFY PACKET DEVICE",
"SERVICE",
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
/*-------------------------------------------------- B0h-BFh -----*/
"SMART",
"DEVICE CONFIGURATION",
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved_cf,
cmd_reserved_cf,
cmd_reserved_cf,
cmd_reserved_cf,
cmd_reserved_cf,
cmd_reserved_cf,
cmd_reserved_cf,
cmd_reserved_cf,
/*-------------------------------------------------- C0h-CFh -----*/
"CFA ERASE SECTORS [VS IF NO CFA]",
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
"READ MULTIPLE",
"WRITE MULTIPLE",
"SET MULTIPLE MODE",
"READ DMA QUEUED",
"READ DMA",
"READ DMA [OBS-5]",
"WRITE DMA",
"WRITE DMA [OBS-5]",
"WRITE DMA QUEUED",
"CFA WRITE MULTIPLE WITHOUT ERASE",
"WRITE MULTIPLE FUA EXT",
cmd_reserved,
/*-------------------------------------------------- D0h-DFh -----*/
cmd_reserved,
"CHECK MEDIA CARD TYPE",
cmd_reserved_mcpt,
cmd_reserved_mcpt,
cmd_reserved_mcpt,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
cmd_reserved,
"GET MEDIA STATUS",
"ACKNOWLEDGE MEDIA CHANGE [RET-4]",
"BOOT POST-BOOT [RET-4]",
"BOOT PRE-BOOT [RET-4]",
"MEDIA LOCK",
"MEDIA UNLOCK",
/*-------------------------------------------------- E0h-EFh -----*/
"STANDBY IMMEDIATE",
"IDLE IMMEDIATE",
"STANDBY",
"IDLE",
"READ BUFFER",
"CHECK POWER MODE",
"SLEEP",
"FLUSH CACHE",
"WRITE BUFFER",
"WRITE SAME [RET-4]", /* Warning! This command is retired but the value of
f_reg is used in look_up_ata_command(). If this
command code is reclaimed in a future standard then
be sure to update look_up_ata_command(). */
"FLUSH CACHE EXIT",
cmd_reserved,
"IDENTIFY DEVICE",
"MEDIA EJECT",
"IDENTIFY DEVICE DMA [OBS-4]",
"SET FEATURES",
/*-------------------------------------------------- F0h-FFh -----*/
cmd_vendor_specific,
"SECURITY SET PASSWORD",
"SECURITY UNLOCK",
"SECURITY ERASE PREPARE",
"SECURITY ERASE UNIT",
"SECURITY FREEZE LOCK",
"SECURITY DISABLE PASSWORD",
cmd_vendor_specific,
"READ NATIVE MAX ADDRESS",
"SET MAX",
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific,
cmd_vendor_specific
};
/* Returns the name of the command (and possibly sub-command) with the given
command code and feature register values. For most command codes this
simply returns the corresponding entry in the command_table array, but for
others the value of the feature register specifies a subcommand or
distinguishes commands. */
const char *look_up_ata_command(unsigned char c_code, unsigned char f_reg) {
// check that command table not messed up. The compiler will issue
// warnings if there are too many array elements, but won't issue
// warnings if there are not enough of them.
if (sizeof(command_table) != sizeof(char *)*COMMAND_TABLE_SIZE){
fprintf(stderr,
"Problem in atacmdnames.c. Command Table command_table[] does\n"
"not have %d entries! It has %d entries. Please fix it.\n",
COMMAND_TABLE_SIZE, (int)(sizeof(command_table)/sizeof(char *)));
abort();
}
switch (c_code) {
case 0x00: /* NOP */
switch (f_reg) {
case 0x00:
return "NOP [Abort queued commands]";
case 0x01:
return "NOP [Don't abort queued commands]";
default:
return "NOP [Reserved subcommand]";
}
case 0x92: /* DOWNLOAD MICROCODE */
switch (f_reg) {
case 0x01:
return "DOWNLOAD MICROCODE [Temporary]";
case 0x07:
return "DOWNLOAD MICROCODE [Save]";
default:
return "DOWNLOAD MICROCODE [Reserved subcommand]";
}
case 0xB0: /* SMART */
switch (f_reg) {
case 0xD0:
return "SMART READ DATA";
case 0xD1:
return "SMART READ ATTRIBUTE THRESHOLDS [OBS-4]";
case 0xD2:
return "SMART ENABLE/DISABLE ATTRIBUTE AUTOSAVE";
case 0xD3:
return "SMART SAVE ATTRIBUTE VALUES [OBS-6]";
case 0xD4:
return "SMART EXECUTE OFF-LINE IMMEDIATE";
case 0xD5:
return "SMART READ LOG";
case 0xD6:
return "SMART WRITE LOG";
case 0xD7:
return "SMART WRITE ATTRIBUTE THRESHOLDS [NS, OBS-4]";
case 0xD8:
return "SMART ENABLE OPERATIONS";
case 0xD9:
return "SMART DISABLE OPERATIONS";
case 0xDA:
return "SMART RETURN STATUS";
case 0xDB:
return "SMART EN/DISABLE AUTO OFFLINE [NS (SFF-8035i)]";
default:
if (f_reg >= 0xE0)
return "[Vendor specific SMART command]";
else
return "[Reserved SMART command]";
}
case 0xB1: /* DEVICE CONFIGURATION */
switch (f_reg) {
case 0xC0:
return "DEVICE CONFIGURATION RESTORE";
case 0xC1:
return "DEVICE CONFIGURATION FREEZE LOCK";
case 0xC2:
return "DEVICE CONFIGURATION IDENTIFY";
case 0xC3:
return "DEVICE CONFIGURATION SET";
default:
return "DEVICE CONFIGURATION [Reserved command]";
}
case 0xE9: /* WRITE SAME */
switch (f_reg) {
case 0x22:
return "WRITE SAME [Start specified] [RET-4]";
case 0xDD:
return "WRITE SAME [Start unspecified] [RET-4]";
default:
return "WRITE SAME [Invalid subcommand] [RET-4]";
}
case 0xEF: /* SET FEATURES */
switch (f_reg) {
case 0x01:
return "SET FEATURES [Enable 8-bit PIO]";
case 0x02:
return "SET FEATURES [Enable write cache]";
case 0x03:
return "SET FEATURES [Set transfer mode]";
case 0x04:
return "SET FEATURES [Enable auto DR] [OBS-4]";
case 0x05:
return "SET FEATURES [Enable APM]";
case 0x06:
return "SET FEATURES [Enable Pwr-Up In Standby]";
case 0x07:
return "SET FEATURES [Set device spin-up]";
case 0x09:
return "SET FEATURES [Reserved (address offset)]";
case 0x0A:
return "SET FEATURES [Enable CFA power mode 1]";
case 0x10:
return "SET FEATURES [Reserved for Serial ATA]";
case 0x20:
return "SET FEATURES [Set Time-ltd R/W WCT]";
case 0x21:
return "SET FEATURES [Set Time-ltd R/W EH]";
case 0x31:
return "SET FEATURES [Disable Media Status Notf]";
case 0x33:
return "SET FEATURES [Disable retry] [OBS-4]";
case 0x42:
return "SET FEATURES [Enable AAM]";
case 0x43:
return "SET FEATURES [Set Max Host I/F S Times]";
case 0x44:
return "SET FEATURES [Length of VS data] [OBS-4]";
case 0x54:
return "SET FEATURES [Set cache segs] [OBS-4]";
case 0x55:
return "SET FEATURES [Disable read look-ahead]";
case 0x5D:
return "SET FEATURES [Enable release interrupt]";
case 0x5E:
return "SET FEATURES [Enable SERVICE interrupt]";
case 0x66:
return "SET FEATURES [Disable revert defaults]";
case 0x77:
return "SET FEATURES [Disable ECC] [OBS-4]";
case 0x81:
return "SET FEATURES [Disable 8-bit PIO]";
case 0x82:
return "SET FEATURES [Disable write cache]";
case 0x84:
return "SET FEATURES [Disable auto DR] [OBS-4]";
case 0x85:
return "SET FEATURES [Disable APM]";
case 0x86:
return "SET FEATURES [Disable Pwr-Up In Standby]";
case 0x88:
return "SET FEATURES [Disable ECC] [OBS-4]";
case 0x89:
return "SET FEATURES [Reserved (address offset)]";
case 0x8A:
return "SET FEATURES [Disable CFA power mode 1]";
case 0x90:
return "SET FEATURES [Reserved for Serial ATA]";
case 0x95:
return "SET FEATURES [Enable Media Status Notf]";
case 0x99:
return "SET FEATURES [Enable retries] [OBS-4]";
case 0x9A:
return "SET FEATURES [Set max avg curr] [OBS-4]";
case 0xAA:
return "SET FEATURES [Enable read look-ahead]";
case 0xAB:
return "SET FEATURES [Set max prefetch] [OBS-4]";
case 0xBB:
return "SET FEATURES [4 bytes VS data] [OBS-4]";
case 0xC2:
return "SET FEATURES [Disable AAM]";
case 0xCC:
return "SET FEATURES [Enable revert to defaults]";
case 0xDD:
return "SET FEATURES [Disable release interrupt]";
case 0xDE:
return "SET FEATURES [Disable SERVICE interrupt]";
case 0xE0:
return "SET FEATURES [Obsolete subcommand]";
default:
if (f_reg >= 0xF0)
return "SET FEATURES [Reserved for CFA]";
else
return "SET FEATURES [Reserved subcommand]";
}
case 0xF9: /* SET MAX */
switch (f_reg) {
case 0x00:
return "SET MAX ADDRESS [OBS-6]";
case 0x01:
return "SET MAX SET PASSWORD";
case 0x02:
return "SET MAX LOCK";
case 0x03:
return "SET MAX UNLOCK";
case 0x04:
return "SET MAX FREEZE LOCK";
default:
return "[Reserved SET MAX command]";
}
default:
return command_table[c_code];
}
}
This diff is collapsed.
This diff is collapsed.
/*
* knowndrives.c
*
* Home page of code is: http://smartmontools.sourceforge.net
* Address of support mailing list: smartmontools-support@lists.sourceforge.net
*
* Copyright (C) 2003 Philip Williams, Bruce Allen
*
* 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.
*
*/
#include <stdio.h>
#include <regex.h>
#include "atacmds.h"
#include "ataprint.h"
#include "extern.h"
#include "knowndrives.h"
#include "utility.h"
#include "config.h"
const char *knowndrives_c_cvsid="$Id: knowndrives.cpp,v 1.48 2003/10/15 05:35:51 ballen4705 Exp $"
ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID KNOWNDRIVES_H_CVSID UTILITY_H_CVSID;
#define MODEL_STRING_LENGTH 40
#define FIRMWARE_STRING_LENGTH 8
#define TABLEPRINTWIDTH 19
// See vendorattributeargs[] array in atacmds.c for definitions.
#define PRESET_9_MINUTES { 9, 1 }
#define PRESET_9_TEMP { 9, 2 }
#define PRESET_9_SECONDS { 9, 3 }
#define PRESET_9_HALFMINUTES { 9, 4 }
#define PRESET_192_EMERGENCYRETRACTCYCLECT { 192, 1 }
#define PRESET_193_LOADUNLOAD { 193, 1 }
#define PRESET_194_10XCELSIUS { 194, 1 }
#define PRESET_194_UNKNOWN { 194, 2 }
#define PRESET_198_OFFLINESCANUNCSECTORCT { 198, 1 }
#define PRESET_200_WRITEERRORCOUNT { 200, 1 }
#define PRESET_201_DETECTEDTACOUNT { 201, 1 }
#define PRESET_220_TEMP { 220, 1 }
/* Arrays of preset vendor-specific attribute options for use in
* knowndrives[]. */
extern long long bytes;
// to hold onto exit code for atexit routine
extern int exitstatus;
// These two are common to several models.
const unsigned char vendoropts_9_minutes[][2] = {
PRESET_9_MINUTES,
{0,0}
};
const unsigned char vendoropts_9_seconds[][2] = {
PRESET_9_SECONDS,
{0,0}
};
const unsigned char vendoropts_Maxtor_4D080H4[][2] = {
PRESET_9_MINUTES,
PRESET_194_UNKNOWN,
{0,0}
};
const unsigned char vendoropts_Fujitsu_MHS2020AT[][2] = {
PRESET_9_SECONDS,
PRESET_192_EMERGENCYRETRACTCYCLECT,
PRESET_198_OFFLINESCANUNCSECTORCT,
PRESET_200_WRITEERRORCOUNT,
PRESET_201_DETECTEDTACOUNT,
{0,0}
};
const unsigned char vendoropts_Fujitsu_MHR2040AT[][2] = {
PRESET_9_SECONDS,
PRESET_192_EMERGENCYRETRACTCYCLECT,
PRESET_198_OFFLINESCANUNCSECTORCT,
PRESET_200_WRITEERRORCOUNT,
{0,0}
};
const unsigned char vendoropts_Samsung_SV4012H[][2] = {
PRESET_9_HALFMINUTES,
{0,0}
};
const unsigned char vendoropts_Samsung_SV1204H[][2] = {
PRESET_9_HALFMINUTES,
PRESET_194_10XCELSIUS,
{0,0}
};
const unsigned char vendoropts_Hitachi_DK23EA[][2] = {
PRESET_9_MINUTES,
PRESET_193_LOADUNLOAD,
{0,0}
};
const char same_as_minus_F[]="Fixes byte order in some SMART data (same as -F samsung)";
const char same_as_minus_F2[]="Fixes byte order in some SMART data (same as -F samsung2)";
const char may_need_minus_F_disabled[]="Contact developers at " PACKAGE_BUGREPORT "; may need -F samsung disabled";
const char may_need_minus_F2_disabled[]="Contact developers at " PACKAGE_BUGREPORT "; may need -F samsung2 disabled";
/* Special-purpose functions for use in knowndrives[]. */
void specialpurpose_reverse_samsung(smartmonctrl *con)
{
con->fixfirmwarebug = FIX_SAMSUNG;
}
void specialpurpose_reverse_samsung2(smartmonctrl *con)
{
con->fixfirmwarebug = FIX_SAMSUNG2;
}
/* Table of settings for known drives terminated by an element containing all
* zeros. The drivesettings structure is described in knowndrives.h. Note
* that lookupdrive() will search knowndrives[] from the start to end or
* until it finds the first match, so the order in knowndrives[] is important
* for distinct entries that could match the same drive. */
// Note that the table just below uses EXTENDED REGULAR EXPRESSIONS.
// A good on-line reference for these is:
// http://www.zeus.com/extra/docsystem/docroot/apps/web/docs/modules/access/regex.html
const drivesettings knowndrives[] = {
{ // IBM Deskstar 60GXP series
"IC35L0[12346]0AVER07",
".*",
"IBM Deskstar 60GXP drives may need upgraded SMART firmware.\n"
"Please see http://www.geocities.com/dtla_update/index.html#rel",
NULL, NULL, NULL
},
{ // IBM Deskstar 40GV & 75GXP series
"(IBM-)?DTLA-30[57]0[123467][05]$",
".*",
"IBM Deskstar 40GV and 75GXP drives may need upgraded SMART firmware.\n"
"Please see http://www.geocities.com/dtla_update/",
NULL, NULL, NULL
},
{ // Fujitsu MPD and MPE series
"^FUJITSU MP[DE]....A[HT]$",
".*",
NULL,
vendoropts_9_seconds,
NULL, NULL
},
{ // Fujitsu MHN2300AT
"^FUJITSU MHN2300AT$",
".*",
NULL,
vendoropts_9_seconds,
NULL, NULL
},
{ // Fujitsu MHR2040AT
"^FUJITSU MHR2040AT$",
".*", // Tested on 40BA
NULL,
vendoropts_Fujitsu_MHR2040AT,
NULL, NULL
},
{ // Fujitsu MHS2020AT
"^FUJITSU MHS2020AT$",
".*", // Tested on 8004
NULL,
vendoropts_Fujitsu_MHS2020AT,
NULL, NULL
},
{ // Samsung SV4012H (known firmware)
"^SAMSUNG SV4012H$",
"^RM100-08$",
NULL,
vendoropts_Samsung_SV4012H,
specialpurpose_reverse_samsung,
same_as_minus_F
},
{ // Samsung SV4012H (match revision *-23 firmware)
"^SAMSUNG .*$",
".*-23$",
may_need_minus_F2_disabled,
vendoropts_Samsung_SV4012H,
specialpurpose_reverse_samsung2,
same_as_minus_F2
},
{ // Samsung SV4012H (all other firmware)
"^SAMSUNG SV4012H$",
".*",
may_need_minus_F_disabled,
vendoropts_Samsung_SV4012H,
specialpurpose_reverse_samsung,
same_as_minus_F
},
{ // Samsung SV1204H (known firmware)
"^SAMSUNG SV1204H$",
"^RK100-1[3-5]$",
NULL,
vendoropts_Samsung_SV1204H,
specialpurpose_reverse_samsung,
same_as_minus_F
},
{ //Samsung SV1204H (all other firmware)
"^SAMSUNG SV1204H$",
".*",
may_need_minus_F_disabled,
vendoropts_Samsung_SV1204H,
specialpurpose_reverse_samsung,
same_as_minus_F
},
{ // Samsung SV0412H (known firmware)
"^SAMSUNG SV0412H$",
"^SK100-01$",
NULL,
vendoropts_Samsung_SV1204H,
specialpurpose_reverse_samsung,
same_as_minus_F
},
{ // Samsung SV0412H (all other firmware)
"^SAMSUNG SV0412H$",
".*",
may_need_minus_F_disabled,
vendoropts_Samsung_SV1204H,
specialpurpose_reverse_samsung,
same_as_minus_F
},
{ //Samsung SP1604N, tested with FW TM100-23
"^SAMSUNG SP1604N$",
".*",
NULL,
vendoropts_Samsung_SV4012H,
NULL,NULL
},
{ //SAMSUNG SV0322A with FW JK200-35
"^SAMSUNG SV0322A$",
".*",
NULL,
NULL,
NULL,
NULL
},
{ // Samsung ALL OTHER DRIVES
"^SAMSUNG.*",
".*",
"Contact developers at " PACKAGE_BUGREPORT "; may need -F samsung[2] enabled.\n",
NULL, NULL, NULL
},
{ // Maxtor 6L080J4 and 4K080H4
"^MAXTOR (6L080J4|4K080H4)$",
".*",
NULL, NULL, NULL, NULL
},
{ // Maxtor 4D080H4
"^Maxtor (4D080H4|4G120J6)$",
".*",
NULL,
vendoropts_Maxtor_4D080H4,
NULL, NULL
},
{ // Maxtor 4R080J0
"^Maxtor (4R080J0|4R080L0|6Y0[6|8]0L0|6Y1[2|6]0P0)$",
".*",
NULL,
vendoropts_9_minutes,
NULL, NULL
},
{ // Maxtor 6Y120P0 (known firmware)
"^Maxtor 6Y120P0$",
"^YAR41VW0$",
NULL,
vendoropts_9_minutes,
NULL, NULL
},
{ // Maxtor 6Y120P0 (any other firmware)
"^Maxtor 6Y120P0$",
".*",
"Contact developers at " PACKAGE_BUGREPORT "; may need -v 9,minutes enabled.\n",
NULL,
NULL, NULL
},
{ // HITACHI_DK23BA-20
"^HITACHI_DK23BA-20$",
".*",
NULL,
vendoropts_9_minutes,
NULL, NULL
},
{ // HITACHI_DK23EA-30
"^HITACHI_DK23EA-30$",
".*",
NULL,
vendoropts_Hitachi_DK23EA,
NULL, NULL
},
{ // IBM GXP-180
"^IC35L120AVV207-[01]$",
".*",
NULL, NULL, NULL, NULL
},
{
// IBM Deskstar 120GXP [Phil -- use for testing]
"^IC35L060AVVA07-[01]$",
".*",
NULL,
NULL,
NULL,
NULL,
},
{
// TOSHIBA MK6021GAS [Bruce -- use for testing on laptop]
"^TOSHIBA MK6021GAS$",
".*",
NULL,
NULL,
NULL,
NULL,
},
/*------------------------------------------------------------
* End of table. Do not add entries below this marker.
*------------------------------------------------------------ */
{NULL, NULL, NULL, NULL, NULL, NULL}
};
// Searches knowndrives[] for a drive with the given model number and firmware
// string. If either the drive's model or firmware strings are not set by the
// manufacturer then values of NULL may be used. Returns the index of the
// first match in knowndrives[] or -1 if no match if found.
int lookupdrive(const char *model, const char *firmware)
{
regex_t regex;
int i, index;
const char *empty = "";
model = model ? model : empty;
firmware = firmware ? firmware : empty;
for (i = 0, index = -1; index == -1 && knowndrives[i].modelregexp; i++) {
// Attempt to compile regular expression.
if (compileregex(&regex, knowndrives[i].modelregexp, REG_EXTENDED))
goto CONTINUE;
// Check whether model matches the regular expression in knowndrives[i].
if (!regexec(&regex, model, 0, NULL, 0)) {
// model matches, now check firmware.
if (!knowndrives[i].firmwareregexp)
// The firmware regular expression in knowndrives[i] is NULL, which is
// considered a match.
index = i;
else {
// Compare firmware against the regular expression in knowndrives[i].
regfree(&regex); // Recycle regex.
if (compileregex(&regex, knowndrives[i].firmwareregexp, REG_EXTENDED))
goto CONTINUE;
if (!regexec(&regex, firmware, 0, NULL, 0))
index = i;
}
}
CONTINUE:
regfree(&regex);
}
return index;
}
// Shows all presets for drives in knowndrives[].
void showonepreset(const drivesettings *drivetable){
const unsigned char (* presets)[2] = drivetable->vendoropts;
int first_preset = 1;
// Basic error check
if (!drivetable || !drivetable->modelregexp){
pout("Null known drive table pointer. Please report\n"
"this error to smartmontools developers at " PACKAGE_BUGREPORT ".\n");
return;
}
// print model and firmware regular expressions
pout("%-*s %s\n", TABLEPRINTWIDTH, "MODEL REGEXP:", drivetable->modelregexp);
pout("%-*s %s\n", TABLEPRINTWIDTH, "FIRMWARE REGEXP:", drivetable->firmwareregexp ?
drivetable->firmwareregexp : "");
// if there are any presets, then show them
if (presets && (*presets)[0]) while (1) {
char out[256];
const int attr = (*presets)[0], val = (*presets)[1];
unsigned char fakearray[MAX_ATTRIBUTE_NUM];
// if we are at the end of the attribute list, break out
if (!attr)
break;
// This is a hack. ataPrintSmartAttribName() needs a pointer to an
// "array" to dereference, so we provide such a pointer.
fakearray[attr]=val;
ataPrintSmartAttribName(out, attr, fakearray);
// Use leading zeros instead of spaces so that everything lines up.
out[0] = (out[0] == ' ') ? '0' : out[0];
out[1] = (out[1] == ' ') ? '0' : out[1];
pout("%-*s %s\n", TABLEPRINTWIDTH, first_preset ? "ATTRIBUTE OPTIONS:" : "", out);
first_preset = 0;
presets++;
}
else
pout("%-*s %s\n", TABLEPRINTWIDTH, "ATTRIBUTE OPTIONS:", "None preset; no -v options are required.");
// Is a special purpose function defined? If so, describe it
if (drivetable->specialpurpose){
pout("%-*s ", TABLEPRINTWIDTH, "OTHER PRESETS:");
pout("%s\n", drivetable->functiondesc ?
drivetable->functiondesc : "A special purpose function "
"is defined for this drive");
}
// Print any special warnings
if (drivetable->warningmsg){
pout("%-*s ", TABLEPRINTWIDTH, "WARNINGS:");
pout("%s\n", drivetable->warningmsg);
}
return;
}
void showallpresets(void){
int i;
// loop over all entries in the knowndrives[] table, printing them
// out in a nice format
for (i=0; knowndrives[i].modelregexp; i++){
showonepreset(&knowndrives[i]);
pout("\n");
}
return;
}
// Shows the presets (if any) that are available for the given drive.
void showpresets(const struct ata_identify_device *drive){
int i;
char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1];
// get the drive's model/firmware strings
formatdriveidstring(model, drive->model, MODEL_STRING_LENGTH);
formatdriveidstring(firmware, drive->fw_rev, FIRMWARE_STRING_LENGTH);
// and search to see if they match values in the table
if ((i = lookupdrive(model, firmware)) < 0) {
// no matches found
pout("No presets are defined for this drive. Its identity strings:\n"
"MODEL: %s\n"
"FIRMWARE: %s\n"
"do not match any of the known regular expressions.\n"
"Use -P showall to list all known regular expressions.\n",
model, firmware);
return;
}
// We found a matching drive. Print out all information about it.
pout("Drive found in smartmontools Database. Drive identity strings:\n"
"%-*s %s\n"
"%-*s %s\n"
"match smartmontools Drive Database entry:\n",
TABLEPRINTWIDTH, "MODEL:", model, TABLEPRINTWIDTH, "FIRMWARE:", firmware);
showonepreset(&knowndrives[i]);
return;
}
// Sets preset vendor attribute options in opts by finding the entry
// (if any) for the given drive in knowndrives[]. Values that have
// already been set in opts will not be changed. Returns <0 if drive
// not recognized else index >=0 into drive database.
int applypresets(const struct ata_identify_device *drive, unsigned char **optsptr,
smartmonctrl *con) {
int i;
unsigned char *opts;
char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1];
if (*optsptr==NULL)
bytes+=MAX_ATTRIBUTE_NUM;
if (*optsptr==NULL && !(*optsptr=(unsigned char *)calloc(MAX_ATTRIBUTE_NUM,1))){
pout("Unable to allocate memory in applypresets()");
bytes-=MAX_ATTRIBUTE_NUM;
EXIT(1);
}
opts=*optsptr;
// get the drive's model/firmware strings
formatdriveidstring(model, drive->model, MODEL_STRING_LENGTH);
formatdriveidstring(firmware, drive->fw_rev, FIRMWARE_STRING_LENGTH);
// Look up the drive in knowndrives[] and check vendoropts is non-NULL.
if ((i = lookupdrive(model, firmware)) >= 0 && knowndrives[i].vendoropts) {
const unsigned char (* presets)[2];
// For each attribute in list of attribute/val pairs...
presets = knowndrives[i].vendoropts;
while (1) {
const int attr = (*presets)[0];
const int val = (*presets)[1];
if (!attr)
break;
// ... set attribute if user hasn't already done so.
if (!opts[attr])
opts[attr] = val;
presets++;
}
// If a function is defined for this drive then call it.
if (knowndrives[i].specialpurpose)
(*knowndrives[i].specialpurpose)(con);
}
// return <0 if drive wasn't recognized, or index>=0 into database
// if it was
return i;
}
/*
* os_freebsd.c
*
* Home page of code is: http://smartmontools.sourceforge.net
*
* Copyright (C) 2003 Eduard Martinescu <smartmontools-support@lists.sourceforge.net>
*
* 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 <sys/types.h>
#include <dirent.h>
#include <err.h>
#include <camlib.h>
#include <cam/scsi/scsi_message.h>
#include <sys/ata.h>
#include "config.h"
#include "atacmds.h"
#include "scsicmds.h"
#include "utility.h"
#include "os_freebsd.h"
const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp,v 1.18 2003/10/14 14:22:44 ballen4705 Exp $" \
ATACMDS_H_CVSID CONFIG_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
// to hold onto exit code for atexit routine
extern int exitstatus;
// Private table of open devices: guaranteed zero on startup since
// part of static data.
struct freebsd_dev_channel *devicetable[FREEBSD_MAXDEV];
// forward declaration
static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *ch);
// Like open(). Return positive integer handle, used by functions below only. mode=="ATA" or "SCSI".
int deviceopen (const char* dev, char* mode) {
struct freebsd_dev_channel *fdchan;
int parse_ok, i;
// Search table for a free entry
for (i=0; i<FREEBSD_MAXDEV; i++)
if (!devicetable[i])
break;
// If no free entry found, return error. We have max allowed number
// of "file descriptors" already allocated.
if (i==FREEBSD_MAXDEV) {
errno=EMFILE;
return -1;
}
fdchan = calloc(1,sizeof(struct freebsd_dev_channel));
if (fdchan == NULL) {
// errno already set by call to malloc()
return -1;
}
parse_ok = parse_ata_chan_dev (dev,fdchan);
if (parse_ok == GUESS_DEVTYPE_DONT_KNOW) {
free(fdchan);
errno = ENOTTY;
return -1; // can't handle what we don't know
}
if (parse_ok == GUESS_DEVTYPE_ATA) {
if ((fdchan->atacommand = open("/dev/ata",O_RDWR))<0) {
int myerror = errno; //preserve across free call
free (fdchan);
errno = myerror;
return -1;
}
}
if (parse_ok == GUESS_DEVTYPE_SCSI) {
// this is really a NO-OP, as the parse takes care
// of filling in correct details
}
// return pointer to "file descriptor" table entry, properly offset.
devicetable[i]=fdchan;
return i+FREEBSD_FDOFFSET;
}
// Returns 1 if device not available/open/found else 0. Also shifts fd into valid range.
static int isnotopen(int *fd, struct freebsd_dev_channel** fdchan) {
// put valid "file descriptor" into range 0...FREEBSD_MAXDEV-1
*fd -= FREEBSD_FDOFFSET;
// check for validity of "file descriptor".
if (*fd<0 || *fd>=FREEBSD_MAXDEV || !((*fdchan)=devicetable[*fd])) {
errno = ENODEV;
return 1;
}
return 0;
}
// Like close(). Acts on handles returned by above function.
int deviceclose (int fd) {
struct freebsd_dev_channel *fdchan;
int failed = 0;
// check for valid file descriptor
if (isnotopen(&fd, &fdchan))
return -1;
// did we allocate a SCSI device name?
if (fdchan->devname)
free(fdchan->devname);
// close device, if open
if (fdchan->atacommand)
failed=close(fdchan->atacommand);
if (fdchan->scsicontrol)
failed=close(fdchan->scsicontrol);
// if close succeeded, then remove from device list
// Eduard, should we also remove it from list if close() fails? I'm
// not sure. Here I only remove it from list if close() worked.
if (!failed) {
free(fdchan);
devicetable[fd]=NULL;
}
return failed;
}
#define NO_RETURN 0
#define BAD_SMART 1
#define NO_3WARE 2
#define BAD_KERNEL 3
#define MAX_MSG 3
// Utility function for printing warnings
void printwarning(int msgNo, const char* extra) {
static int printed[] = {0,0,0,0};
static const char* message[]={
"The SMART RETURN STATUS return value (smartmontools -H option/Directive)\n can not be retrieved with this version of ATAng, please do not rely on this value\n",
"Error SMART Status command failed\nPlease get assistance from \n" PROJECTHOME "\nRegister values returned from SMART Status command are:\n",
PACKAGE_STRING " does not currentlly support TWE devices (3ware Escalade)\n",
"ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"
};
if (msgNo >= 0 && msgNo <= MAX_MSG) {
if (!printed[msgNo]) {
printed[msgNo] = 1;
pout("%s", message[msgNo]);
if (extra)
pout("%s",extra);
}
}
return;
}
// Interface to ATA devices. See os_linux.c
int ata_command_interface(int fd, smart_command_set command, int select, char *data) {
struct freebsd_dev_channel* con;
int retval, copydata=0;
struct ata_cmd iocmd;
unsigned char buff[512];
// check that "file descriptor" is valid
if (isnotopen(&fd,&con))
return -1;
#ifndef ATAREQUEST
// sorry, but without ATAng, we can't do anything here
printwarning(OLD_KERNEL,NULL);
errno = ENOSYS;
return -;
#else
bzero(buff,512);
bzero(&iocmd,sizeof(struct ata_cmd));
bzero(buff,512);
iocmd.cmd=ATAREQUEST;
iocmd.channel=con->channel;
iocmd.device=con->device;
iocmd.u.request.u.ata.command=WIN_SMART;
iocmd.u.request.timeout=600;
switch (command){
case READ_VALUES:
iocmd.u.request.u.ata.feature=SMART_READ_VALUES;
iocmd.u.request.u.ata.lba=0xc24f<<8;
iocmd.u.request.flags=ATA_CMD_READ;
iocmd.u.request.data=buff;
iocmd.u.request.count=512;
copydata=1;
break;
case READ_THRESHOLDS:
iocmd.u.request.u.ata.feature=SMART_READ_THRESHOLDS;
iocmd.u.request.u.ata.count=1;
iocmd.u.request.u.ata.lba=1|(0xc24f<<8);
iocmd.u.request.flags=ATA_CMD_READ;
iocmd.u.request.data=buff;
iocmd.u.request.count=512;
copydata=1;
break;
case READ_LOG:
iocmd.u.request.u.ata.feature=SMART_READ_LOG_SECTOR;
iocmd.u.request.u.ata.lba=select|(0xc24f<<8);
iocmd.u.request.u.ata.count=1;
iocmd.u.request.flags=ATA_CMD_READ;
iocmd.u.request.data=buff;
iocmd.u.request.count=512;
copydata=1;
break;
case IDENTIFY:
iocmd.u.request.u.ata.command=WIN_IDENTIFY;
iocmd.u.request.flags=ATA_CMD_READ;
iocmd.u.request.data=buff;
iocmd.u.request.count=512;
copydata=1;
break;
case PIDENTIFY:
iocmd.u.request.u.ata.command=WIN_PIDENTIFY;
iocmd.u.request.flags=ATA_CMD_READ;
iocmd.u.request.data=buff;
iocmd.u.request.count=512;
copydata=1;
break;
case ENABLE:
iocmd.u.request.u.ata.feature=SMART_ENABLE;
iocmd.u.request.u.ata.lba=0xc24f<<8;
iocmd.u.request.flags=ATA_CMD_CONTROL;
break;
case DISABLE:
iocmd.u.request.u.ata.feature=SMART_DISABLE;
iocmd.u.request.u.ata.lba=0xc24f<<8;
iocmd.u.request.flags=ATA_CMD_CONTROL;
break;
case AUTO_OFFLINE:
// NOTE: According to ATAPI 4 and UP, this command is obsolete
iocmd.u.request.u.ata.feature=SMART_AUTO_OFFLINE;
iocmd.u.request.u.ata.lba=select|(0xc24f<<8);
iocmd.u.request.flags=ATA_CMD_CONTROL;
break;
case AUTOSAVE:
iocmd.u.request.u.ata.feature=SMART_AUTOSAVE;
iocmd.u.request.u.ata.count=0xf1; // to enable autosave
iocmd.u.request.u.ata.lba=0xc24f<<8;
iocmd.u.request.flags=ATA_CMD_CONTROL;
break;
case IMMEDIATE_OFFLINE:
iocmd.u.request.u.ata.feature=SMART_IMMEDIATE_OFFLINE;
iocmd.u.request.u.ata.lba = select|(0xc24f<<8); // put test in sector
iocmd.u.request.flags=ATA_CMD_CONTROL;
break;
case STATUS_CHECK: // same command, no HDIO in FreeBSD
case STATUS:
// this command only says if SMART is working. It could be
// replaced with STATUS_CHECK below.
iocmd.u.request.u.ata.feature=SMART_STATUS;
iocmd.u.request.u.ata.lba=0xc24f<<8;
iocmd.u.request.flags=ATA_CMD_CONTROL;
#ifdef ATA_CMD_READ_REG
// this is not offical ATAng code. Patch submitted, will remove
// once accepted and committed.
iocmd.u.request.flags |= ATA_CMD_READ_REG;
#endif
break;
default:
pout("Unrecognized command %d in ata_command_interface()\n"
"Please contact " PACKAGE_BUGREPORT "\n", command);
errno=ENOSYS;
return -1;
}
if (command==STATUS_CHECK){
unsigned const char normal_lo=0x4f, normal_hi=0xc2;
unsigned const char failed_lo=0xf4, failed_hi=0x2c;
unsigned char low,high;
if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)))
return -1;
#ifndef ATA_CMD_READ_REG
printwarning(NO_RETURN,NULL);
#endif
high = (iocmd.u.request.u.ata.lba >> 16) & 0xff;
low = (iocmd.u.request.u.ata.lba >> 8) & 0xff;
// Cyl low and Cyl high unchanged means "Good SMART status"
if (low==normal_lo && high==normal_hi)
return 0;
// These values mean "Bad SMART status"
if (low==failed_lo && high==failed_hi)
return 1;
// We haven't gotten output that makes sense; print out some debugging info
char buf[512];
sprintf(buf,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
(int)iocmd.u.request.u.ata.command,
(int)iocmd.u.request.u.ata.feature,
(int)iocmd.u.request.u.ata.count,
(int)((iocmd.u.request.u.ata.lba) & 0xff),
(int)((iocmd.u.request.u.ata.lba>>8) & 0xff),
(int)((iocmd.u.request.u.ata.lba>>16) & 0xff),
(int)iocmd.u.request.error);
printwarning(BAD_SMART,buf);
return 0;
}
if ((retval=ioctl(con->atacommand, IOCATA, &iocmd))) {
perror("Failed command: ");
return -1;
}
//
if (copydata)
memcpy(data, buff, 512);
return 0;
#endif
}
// Interface to SCSI devices. See os_linux.c
int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
{
struct freebsd_dev_channel* con = NULL;
struct cam_device* cam_dev = NULL;
union ccb *ccb;
if (report > 0) {
int k;
const unsigned char * ucp = iop->cmnd;
const char * np;
np = scsi_get_opcode_name(ucp[0]);
pout(" [%s: ", np ? np : "<unknown opcode>");
for (k = 0; k < iop->cmnd_len; ++k)
pout("%02x ", ucp[k]);
if ((report > 1) &&
(DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
int trunc = (iop->dxfer_len > 256) ? 1 : 0;
pout("]\n Outgoing data, len=%d%s:\n", (int)iop->dxfer_len,
(trunc ? " [only first 256 bytes shown]" : ""));
dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
}
else
pout("]");
}
// check that "file descriptor" is valid
if (isnotopen(&fd,&con))
return -ENOTTY;
if (!(cam_dev = cam_open_spec_device(con->devname,con->unitnum,O_RDWR,NULL))) {
warnx("%s",cam_errbuf);
return -1;
}
if (!(ccb = cam_getccb(cam_dev))) {
warnx("error allocating ccb");
return -ENOMEM;
}
// clear out structure, except for header that was filled in for us
bzero(&(&ccb->ccb_h)[1],
sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
cam_fill_csio(&ccb->csio,
/*retrires*/ 1,
/*cbfcnp*/ NULL,
/* flags */ (iop->dxfer_dir == DXFER_NONE ? CAM_DIR_NONE :(iop->dxfer_dir == DXFER_FROM_DEVICE ? CAM_DIR_IN : CAM_DIR_OUT)),
/* tagaction */ MSG_SIMPLE_Q_TAG,
/* dataptr */ iop->dxferp,
/* datalen */ iop->dxfer_len,
/* senselen */ iop->max_sense_len,
/* cdblen */ iop->cmnd_len,
/* timout */ iop->timeout);
memcpy(ccb->csio.cdb_io.cdb_bytes,iop->cmnd,iop->cmnd_len);
if (cam_send_ccb(cam_dev,ccb) < 0) {
warn("error sending SCSI ccb");
cam_error_print(cam_dev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
cam_freeccb(ccb);
return -1;
}
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
cam_error_print(cam_dev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
cam_freeccb(ccb);
return -1;
}
if (iop->sensep) {
memcpy(&(ccb->csio.sense_data),iop->sensep,sizeof(struct scsi_sense_data));
iop->resp_sense_len = sizeof(struct scsi_sense_data);
}
iop->scsi_status = ccb->csio.scsi_status;
cam_freeccb(ccb);
if (cam_dev)
cam_close_device(cam_dev);
if (report > 0) {
pout(" status=0\n");
int trunc = (iop->dxfer_len > 256) ? 1 : 0;
pout(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len,
(trunc ? " [only first 256 bytes shown]" : ""));
dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
}
return 0;
}
// Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
int escalade_command_interface(int fd, int disknum, smart_command_set command, int select, char *data) {
printwarning(NO_3WARE,NULL);
return -1;
}
static int get_ata_channel_unit ( const char* name, int* unit, int* dev) {
// there is no direct correlation between name 'ad0, ad1, ...' and
// channel/unit number. So we need to iterate through the possible
// channels and check each unit to see if we match names
struct ata_cmd iocmd;
int fd,maxunit;
bzero(&iocmd, sizeof(struct ata_cmd));
if ((fd = open("/dev/ata", O_RDWR)) < 0)
return -errno;
iocmd.cmd = ATAGMAXCHANNEL;
if (ioctl(fd, IOCATA, &iocmd) < 0) {
return -errno;
close(fd);
}
maxunit = iocmd.u.maxchan;
for (*unit = 0; *unit < maxunit; (*unit)++) {
iocmd.channel = *unit;
iocmd.device = -1;
iocmd.cmd = ATAGPARM;
if (ioctl(fd, IOCATA, &iocmd) < 0) {
close(fd);
return -errno;
}
if (iocmd.u.param.type[0] && !strcmp(name,iocmd.u.param.name[0])) {
*dev = 0;
break;
}
if (iocmd.u.param.type[1] && !strcmp(name,iocmd.u.param.name[1])) {
*dev = 1;
break;
}
}
close(fd);
if (*unit == maxunit)
return -1;
else
return 0;
}
// Guess device type (ata or scsi) based on device name (FreeBSD
// specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst,
// osst, nosst and sg.
static const char * fbsd_dev_prefix = "/dev/";
static const char * fbsd_dev_ata_disk_prefix = "ad";
static const char * fbsd_dev_scsi_disk_plus = "da";
static const char * fbsd_dev_scsi_tape1 = "sa";
static const char * fbsd_dev_scsi_tape2 = "nsa";
static const char * fbsd_dev_scsi_tape3 = "esa";
static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *chan) {
int len;
int dev_prefix_len = strlen(fbsd_dev_prefix);
// if dev_name null, or string length zero
if (!dev_name || !(len = strlen(dev_name)))
return GUESS_DEVTYPE_DONT_KNOW;
// Remove the leading /dev/... if it's there
if (!strncmp(fbsd_dev_prefix, dev_name, dev_prefix_len)) {
if (len <= dev_prefix_len)
// if nothing else in the string, unrecognized
return GUESS_DEVTYPE_DONT_KNOW;
// else advance pointer to following characters
dev_name += dev_prefix_len;
}
// form /dev/ad* or ad*
if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name,
strlen(fbsd_dev_ata_disk_prefix))) {
if (chan != NULL) {
if (get_ata_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) {
return GUESS_DEVTYPE_DONT_KNOW;
}
}
return GUESS_DEVTYPE_ATA;
}
// form /dev/da* or da*
if (!strncmp(fbsd_dev_scsi_disk_plus, dev_name,
strlen(fbsd_dev_scsi_disk_plus)))
goto handlescsi;
// form /dev/sa* or sa*
if (!strncmp(fbsd_dev_scsi_tape1, dev_name,
strlen(fbsd_dev_scsi_tape1)))
goto handlescsi;
// form /dev/nsa* or nsa*
if (!strncmp(fbsd_dev_scsi_tape2, dev_name,
strlen(fbsd_dev_scsi_tape2)))
goto handlescsi;
// form /dev/esa* or esa*
if (!strncmp(fbsd_dev_scsi_tape3, dev_name,
strlen(fbsd_dev_scsi_tape3)))
goto handlescsi;
// we failed to recognize any of the forms
return GUESS_DEVTYPE_DONT_KNOW;
handlescsi:
if (chan != NULL) {
if (!(chan->devname = calloc(1,DEV_IDLEN+1)))
return GUESS_DEVTYPE_DONT_KNOW;
if (cam_get_device(dev_name,chan->devname,DEV_IDLEN,&(chan->unitnum)) == -1)
return GUESS_DEVTYPE_DONT_KNOW;
}
return GUESS_DEVTYPE_SCSI;
}
int guess_device_type (const char* dev_name) {
return parse_ata_chan_dev(dev_name,NULL);
}
// global variable holding byte count of allocated memory
extern long long bytes;
void *FreeNonZero(void* address, int size);
// we are going to take advantage of the fact that FreeBSD's devfs will only
// have device entries for devices that exist. So if we get the equivilent of
// ls /dev/ad?, we have all the ATA devices on the system
int get_dev_names(char*** names, const char* prefix) {
DIR* dir;
struct dirent* dirent;
int n = 0;
char** mp;
// first, preallocate space for upto max number of ATA devices
if (!(mp = (char **)calloc(MAX_NUM_DEV,sizeof(char*))))
return -1;
bytes += (sizeof(char*)*MAX_NUM_DEV);
dir = opendir("/dev");
if (dir == NULL) {
int myerr = errno;
mp= FreeNonZero(mp,(sizeof (char*) * MAX_NUM_DEV));
errno = myerr;
return -1;
}
// now step through names
while ((dirent = readdir(dir)) && (n < MAX_NUM_DEV)) {
if (dirent->d_type == DT_CHR &&
(strstr(dirent->d_name,prefix) != NULL) &&
(dirent->d_namlen == 3)) {
mp[n++] = CustomStrDup(dirent->d_name,1,__LINE__);
}
}
closedir(dir);
mp = realloc(mp,n*(sizeof(char*))); // shrink to correct size
bytes -= (MAX_NUM_DEV-n)*(sizeof(char*)); // and correct allocated bytes
*names=mp;
return n;
}
int make_device_names (char*** devlist, const char* name) {
if (!strcmp(name,"SCSI"))
return get_dev_names(devlist,"da");
else if (!strcmp(name,"ATA"))
return get_dev_names(devlist,"ad");
else
return 0;
}
/*
* os_generic.c
*
* Home page of code is: http://smartmontools.sourceforge.net
*
* Copyright (C) 2003 NAME HERE <smartmontools-support@lists.sourceforge.net>
*
* 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/
*
*/
/* PORTING NOTES AND COMMENTS
To port smartmontools to the OS of your choice, you need to:
[0] Contact smartmontools-support@lists.sourceforge.net to check that
it's not already been done.
[1] Make copies of os_generic.[hc] called os_myOS.[hc]
[2] Modify configure.in so that case "${host}" include myOS
[3] Verify that ./autogen.sh && ./configure && make compiles the code.
If not, fix any compilation problems.
[4] Provide the functions defined in this file: flesh out the
skeletons below. Note that for Darwin much of this already
exists. See some partially developed but incomplete code at:
http://cvs.sourceforge.net/viewcvs.py/smartmontools/sm5_Darwin/
[5] Contact smartmontools-support@lists.sourceforge.net to see about
checking your code into the smartmontools CVS archive.
*/
// These are needed to define prototypes for the functions defined below
#include "atacmds.h"
#include "scsicmds.h"
#include "utility.h"
// This is to include whatever prototypes you define in os_solaris.h
#include "os_solaris.h"
// Needed by '-V' option (CVS versioning) of smartd/smartctl
const char *os_XXXX_c_cvsid="$Id: os_generic.cpp,v 1.2 2003/10/14 13:40:09 ballen4705 Exp $" \
ATACMDS_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
// tries to guess device type given the name (a path). See utility.h
// for return values.
int guess_device_type (const char* dev_name) {
return GUESS_DEVTYPE_DONT_KNOW;
}
// makes a list of ATA or SCSI devices for the DEVICESCAN directive of
// smartd. Returns number N of devices, or -1 if out of
// memory. Allocates N+1 arrays: one of N pointers (devlist), the
// others each contain null-terminated character strings.
int make_device_names (char*** devlist, const char* name) {
return 0;
}
// Like open(). Return positive integer handle, only used by
// functions below. type="ATA" or "SCSI". If you need to store extra
// information about your devices, create a private internal array
// within this file (see os_freebsd.c for an example).
int deviceopen(const char *pathname, char *type){
return -1;
}
// Like close(). Acts only on handles returned by above function.
int deviceclose(int fd){
return 0;
}
// Interface to ATA devices. See os_linux.c
int ata_command_interface(int fd, smart_command_set command, int select, char *data){
return -1;
}
// Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
int escalade_command_interface(int fd, int disknum, smart_command_set command, int select, char *data){
return -1;
}
#include <errno.h>
// Interface to SCSI devices. See os_linux.c
int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) {
return -ENOSYS;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment