File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / smartmontools / scsicmds.h
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:32:16 2012 UTC (12 years, 4 months ago) by misho
Branches: smartmontools, elwix, MAIN
CVS tags: v5_43, v5_42, HEAD
smartmontools

    1: /*
    2:  * scsicmds.h
    3:  *
    4:  * Home page of code is: http://smartmontools.sourceforge.net
    5:  *
    6:  * Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
    7:  * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
    8:  *
    9:  * Additional SCSI work:
   10:  * Copyright (C) 2003-11 Douglas Gilbert <dgilbert@interlog.com>
   11:  *
   12:  * This program is free software; you can redistribute it and/or modify
   13:  * it under the terms of the GNU General Public License as published by
   14:  * the Free Software Foundation; either version 2, or (at your option)
   15:  * any later version.
   16:  *
   17:  * You should have received a copy of the GNU General Public License
   18:  * (for example COPYING); if not, write to the Free
   19:  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   20:  *
   21:  * This code was originally developed as a Senior Thesis by Michael Cornwell
   22:  * at the Concurrent Systems Laboratory (now part of the Storage Systems
   23:  * Research Center), Jack Baskin School of Engineering, University of
   24:  * California, Santa Cruz. http://ssrc.soe.ucsc.edu/
   25:  *
   26:  * N.B. What was formerly known as "SMART" are now called "informational
   27:  * exceptions" in recent t10.org drafts (i.e. recent SCSI).
   28:  *
   29:  */
   30: 
   31: 
   32: #ifndef SCSICMDS_H_
   33: #define SCSICMDS_H_
   34: 
   35: #define SCSICMDS_H_CVSID "$Id: scsicmds.h,v 1.1.1.1 2012/02/21 16:32:16 misho Exp $\n"
   36: 
   37: #include <stdio.h>
   38: #include <stdlib.h>
   39: #include <string.h>
   40: 
   41: /* #define SCSI_DEBUG 1 */ /* Comment out to disable command debugging */
   42: 
   43: /* Following conditional defines just in case OS already has them defined.
   44:  * If they are defined we hope they are defined correctly (for SCSI). */
   45: #ifndef TEST_UNIT_READY
   46: #define TEST_UNIT_READY 0x0
   47: #endif
   48: #ifndef LOG_SELECT
   49: #define LOG_SELECT 0x4c
   50: #endif
   51: #ifndef LOG_SENSE
   52: #define LOG_SENSE 0x4d
   53: #endif
   54: #ifndef MODE_SENSE
   55: #define MODE_SENSE 0x1a
   56: #endif
   57: #ifndef MODE_SENSE_10
   58: #define MODE_SENSE_10 0x5a
   59: #endif
   60: #ifndef MODE_SELECT
   61: #define MODE_SELECT 0x15
   62: #endif
   63: #ifndef MODE_SELECT_10
   64: #define MODE_SELECT_10 0x55
   65: #endif
   66: #ifndef INQUIRY
   67: #define INQUIRY 0x12
   68: #endif
   69: #ifndef REQUEST_SENSE
   70: #define REQUEST_SENSE  0x03
   71: #endif
   72: #ifndef RECEIVE_DIAGNOSTIC
   73: #define RECEIVE_DIAGNOSTIC  0x1c
   74: #endif
   75: #ifndef SEND_DIAGNOSTIC
   76: #define SEND_DIAGNOSTIC  0x1d
   77: #endif
   78: #ifndef READ_DEFECT_10
   79: #define READ_DEFECT_10  0x37
   80: #endif
   81: #ifndef START_STOP_UNIT
   82: #define START_STOP_UNIT  0x1b
   83: #endif
   84: #ifndef REPORT_LUNS
   85: #define REPORT_LUNS  0xa0
   86: #endif
   87: #ifndef READ_CAPACITY_10
   88: #define READ_CAPACITY_10  0x25
   89: #endif
   90: #ifndef READ_CAPACITY_16
   91: #define READ_CAPACITY_16  0x9e
   92: #endif
   93: #ifndef SAI_READ_CAPACITY_16    /* service action for READ_CAPACITY_16 */
   94: #define SAI_READ_CAPACITY_16  0x10
   95: #endif
   96: 
   97: #ifndef SAT_ATA_PASSTHROUGH_12
   98: #define SAT_ATA_PASSTHROUGH_12 0xa1
   99: #endif
  100: #ifndef SAT_ATA_PASSTHROUGH_16
  101: #define SAT_ATA_PASSTHROUGH_16 0x85
  102: #endif
  103: 
  104: typedef unsigned char UINT8;
  105: typedef signed char INT8;
  106: typedef unsigned int UINT32;
  107: typedef int INT32;
  108: 
  109: #define DXFER_NONE        0
  110: #define DXFER_FROM_DEVICE 1
  111: #define DXFER_TO_DEVICE   2
  112: 
  113: struct scsi_cmnd_io
  114: {
  115:     UINT8 * cmnd;       /* [in]: ptr to SCSI command block (cdb) */
  116:     size_t  cmnd_len;   /* [in]: number of bytes in SCSI command */
  117:     int dxfer_dir;      /* [in]: DXFER_NONE, DXFER_FROM_DEVICE, or 
  118:                                  DXFER_TO_DEVICE */
  119:     UINT8 * dxferp;     /* [in]: ptr to outgoing or incoming data buffer */
  120:     size_t dxfer_len;   /* [in]: bytes to be transferred to/from dxferp */
  121:     UINT8 * sensep;     /* [in]: ptr to sense buffer, filled when 
  122:                                  CHECK CONDITION status occurs */
  123:     size_t max_sense_len; /* [in]: max number of bytes to write to sensep */
  124:     unsigned timeout;   /* [in]: seconds, 0-> default timeout (60 seconds?) */
  125:     size_t resp_sense_len;  /* [out]: sense buffer length written */
  126:     UINT8 scsi_status;  /* [out]: 0->ok, 2->CHECK CONDITION, etc ... */
  127:     int resid;          /* [out]: Number of bytes requested to be transferred
  128:                                   less actual number transferred (0 if not
  129:                                    supported) */
  130: };
  131: 
  132: struct scsi_sense_disect {
  133:     UINT8 error_code;
  134:     UINT8 sense_key;
  135:     UINT8 asc; 
  136:     UINT8 ascq;
  137: };
  138: 
  139: /* Useful data from Informational Exception Control mode page (0x1c) */
  140: #define SCSI_IECMP_RAW_LEN 64
  141: struct scsi_iec_mode_page {
  142:     UINT8 requestedCurrent;
  143:     UINT8 gotCurrent;
  144:     UINT8 requestedChangeable;
  145:     UINT8 gotChangeable;
  146:     UINT8 modese_len;   /* 0 (don't know), 6 or 10 */
  147:     UINT8 raw_curr[SCSI_IECMP_RAW_LEN];
  148:     UINT8 raw_chg[SCSI_IECMP_RAW_LEN];
  149: };
  150: 
  151: /* Carrier for Error counter log pages (e.g. read, write, verify ...) */
  152: struct scsiErrorCounter {
  153:     UINT8 gotPC[7];
  154:     UINT8 gotExtraPC;
  155:     uint64_t counter[8];
  156: };
  157: 
  158: /* Carrier for Non-medium error log page */
  159: struct scsiNonMediumError {
  160:     UINT8 gotPC0;
  161:     UINT8 gotExtraPC;
  162:     uint64_t counterPC0;
  163:     UINT8 gotTFE_H;
  164:     uint64_t counterTFE_H; /* Track following errors [Hitachi] */
  165:     UINT8 gotPE_H;
  166:     uint64_t counterPE_H;  /* Positioning errors [Hitachi] */
  167: };
  168: 
  169: /* SCSI Peripheral types (of interest) */
  170: #define SCSI_PT_DIRECT_ACCESS           0x0
  171: #define SCSI_PT_SEQUENTIAL_ACCESS       0x1
  172: #define SCSI_PT_CDROM                   0x5
  173: #define SCSI_PT_MEDIUM_CHANGER          0x8
  174: #define SCSI_PT_ENCLOSURE               0xd
  175: 
  176: /* ANSI SCSI-3 Log Pages retrieved by LOG SENSE. */
  177: #define SUPPORTED_LPAGES                        0x00
  178: #define BUFFER_OVERRUN_LPAGE                    0x01
  179: #define WRITE_ERROR_COUNTER_LPAGE               0x02
  180: #define READ_ERROR_COUNTER_LPAGE                0x03
  181: #define READ_REVERSE_ERROR_COUNTER_LPAGE        0x04
  182: #define VERIFY_ERROR_COUNTER_LPAGE              0x05
  183: #define NON_MEDIUM_ERROR_LPAGE                  0x06
  184: #define LAST_N_ERROR_LPAGE                      0x07
  185: #define FORMAT_STATUS_LPAGE                     0x08
  186: #define LB_PROV_LPAGE                           0x0c   /* SBC-3 */
  187: #define TEMPERATURE_LPAGE                       0x0d
  188: #define STARTSTOP_CYCLE_COUNTER_LPAGE           0x0e
  189: #define APPLICATION_CLIENT_LPAGE                0x0f
  190: #define SELFTEST_RESULTS_LPAGE                  0x10
  191: #define SS_MEDIA_LPAGE                          0x11   /* SBC-3 */
  192: #define BACKGROUND_RESULTS_LPAGE                0x15   /* SBC-3 */
  193: #define NONVOL_CACHE_LPAGE                      0x17   /* SBC-3 */
  194: #define PROTOCOL_SPECIFIC_LPAGE                 0x18
  195: #define IE_LPAGE                                0x2f
  196: 
  197: /* Seagate vendor specific log pages. */
  198: #define SEAGATE_CACHE_LPAGE                     0x37
  199: #define SEAGATE_FACTORY_LPAGE                   0x3e
  200: 
  201: /* Log page response lengths */
  202: #define LOG_RESP_SELF_TEST_LEN 0x194
  203: 
  204: /* See the SSC-2 document at www.t10.org . Earler note: From IBM 
  205: Documentation, see http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */
  206: #define TAPE_ALERTS_LPAGE                        0x2e
  207: 
  208: /* ANSI SCSI-3 Mode Pages */
  209: #define VENDOR_UNIQUE_PAGE                       0x00
  210: #define READ_WRITE_ERROR_RECOVERY_PAGE           0x01
  211: #define DISCONNECT_RECONNECT_PAGE                0x02
  212: #define FORMAT_DEVICE_PAGE                       0x03
  213: #define RIGID_DISK_DRIVE_GEOMETRY_PAGE           0x04
  214: #define FLEXIBLE_DISK_PAGE                       0x05
  215: #define VERIFY_ERROR_RECOVERY_PAGE               0x07
  216: #define CACHING_PAGE                             0x08
  217: #define PERIPHERAL_DEVICE_PAGE                   0x09
  218: #define XOR_CONTROL_MODE_PAGE                    0x10
  219: #define CONTROL_MODE_PAGE                        0x0a
  220: #define MEDIUM_TYPES_SUPPORTED_PAGE              0x0b
  221: #define NOTCH_PAGE                               0x0c
  222: #define CD_DEVICE_PAGE                           0x0d
  223: #define CD_AUDIO_CONTROL_PAGE                    0x0e
  224: #define DATA_COMPRESSION_PAGE                    0x0f
  225: #define ENCLOSURE_SERVICES_MANAGEMENT_PAGE       0x14
  226: #define PROTOCOL_SPECIFIC_LUN_PAGE               0x18
  227: #define PROTOCOL_SPECIFIC_PORT_PAGE              0x19
  228: #define POWER_CONDITION_PAGE                     0x1a
  229: #define INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE    0x1c
  230: #define FAULT_FAILURE_REPORTING_PAGE             0x1c
  231: 
  232: /* Background control mode subpage is [0x1c,0x1] */
  233: #define BACKGROUND_CONTROL_M_SUBPAGE             0x1   /* SBC-2 */
  234: 
  235: #define ALL_MODE_PAGES                           0x3f
  236: 
  237: /* Mode page control field */
  238: #define MPAGE_CONTROL_CURRENT               0
  239: #define MPAGE_CONTROL_CHANGEABLE            1
  240: #define MPAGE_CONTROL_DEFAULT               2
  241: #define MPAGE_CONTROL_SAVED                 3
  242: 
  243: /* defines for useful SCSI Status codes */
  244: #define SCSI_STATUS_CHECK_CONDITION     0x2
  245: 
  246: /* defines for useful Sense Key codes */
  247: #define SCSI_SK_NO_SENSE                0x0
  248: #define SCSI_SK_RECOVERED_ERR           0x1
  249: #define SCSI_SK_NOT_READY               0x2
  250: #define SCSI_SK_MEDIUM_ERROR            0x3
  251: #define SCSI_SK_HARDWARE_ERROR          0x4
  252: #define SCSI_SK_ILLEGAL_REQUEST         0x5
  253: #define SCSI_SK_UNIT_ATTENTION          0x6
  254: #define SCSI_SK_ABORTED_COMMAND         0xb
  255: 
  256: /* defines for useful Additional Sense Codes (ASCs) */
  257: #define SCSI_ASC_NOT_READY              0x4     /* more info in ASCQ code */
  258: #define SCSI_ASC_NO_MEDIUM              0x3a    /* more info in ASCQ code */
  259: #define SCSI_ASC_UNKNOWN_OPCODE         0x20
  260: #define SCSI_ASC_UNKNOWN_FIELD          0x24
  261: #define SCSI_ASC_UNKNOWN_PARAM          0x26
  262: #define SCSI_ASC_WARNING                0xb
  263: #define SCSI_ASC_IMPENDING_FAILURE      0x5d
  264: 
  265: #define SCSI_ASCQ_ATA_PASS_THROUGH      0x1d
  266: 
  267: /* Simplified error code (negative values as per errno) */
  268: #define SIMPLE_NO_ERROR                 0
  269: #define SIMPLE_ERR_NOT_READY            1
  270: #define SIMPLE_ERR_BAD_OPCODE           2
  271: #define SIMPLE_ERR_BAD_FIELD            3       /* in cbd */
  272: #define SIMPLE_ERR_BAD_PARAM            4       /* in data */
  273: #define SIMPLE_ERR_BAD_RESP             5       /* response fails sanity */
  274: #define SIMPLE_ERR_NO_MEDIUM            6       /* no medium present */
  275: #define SIMPLE_ERR_BECOMING_READY       7       /* device will be ready soon */
  276: #define SIMPLE_ERR_TRY_AGAIN            8       /* some warning, try again */
  277: #define SIMPLE_ERR_MEDIUM_HARDWARE      9       /* medium or hardware error */
  278: #define SIMPLE_ERR_UNKNOWN              10      /* unknown sense value */
  279: #define SIMPLE_ERR_ABORTED_COMMAND      11      /* most likely transport error */
  280: 
  281: 
  282: /* defines for functioncode parameter in SENDDIAGNOSTIC function */
  283: #define SCSI_DIAG_NO_SELF_TEST          0x00
  284: #define SCSI_DIAG_DEF_SELF_TEST         0xff
  285: #define SCSI_DIAG_BG_SHORT_SELF_TEST    0x01
  286: #define SCSI_DIAG_BG_EXTENDED_SELF_TEST 0x02
  287: #define SCSI_DIAG_FG_SHORT_SELF_TEST    0x05
  288: #define SCSI_DIAG_FG_EXTENDED_SELF_TEST 0x06
  289: #define SCSI_DIAG_ABORT_SELF_TEST       0x04
  290: 
  291: 
  292: /* SCSI command timeout values (units are seconds) */
  293: #define SCSI_TIMEOUT_DEFAULT    20  // should be longer than the spin up time
  294:                                     // of a disk in standby mode.
  295: #define SCSI_TIMEOUT_SELF_TEST  (5 * 60 * 60)   /* allow max 5 hours for */
  296:                                             /* extended foreground self test */
  297: 
  298: 
  299: 
  300: #define LOGPAGEHDRSIZE  4
  301: 
  302: class scsi_device;
  303: 
  304: // Print SCSI debug messages?
  305: extern unsigned char scsi_debugmode;
  306: 
  307: void scsi_do_sense_disect(const struct scsi_cmnd_io * in,
  308:                           struct scsi_sense_disect * out);
  309: 
  310: int scsiSimpleSenseFilter(const struct scsi_sense_disect * sinfo);
  311: 
  312: const char * scsiErrString(int scsiErr);
  313: 
  314: int scsi_vpd_dev_id_iter(const unsigned char * initial_desig_desc,
  315:                          int page_len, int * off, int m_assoc,
  316:                          int m_desig_type, int m_code_set);
  317: 
  318: int scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s,
  319:                           int slen, int * transport);
  320: 
  321: 
  322: /* STANDARD SCSI Commands  */
  323: int scsiTestUnitReady(scsi_device * device);
  324: 
  325: int scsiStdInquiry(scsi_device * device, UINT8 *pBuf, int bufLen);
  326: 
  327: int scsiInquiryVpd(scsi_device * device, int vpd_page, UINT8 *pBuf, int bufLen);
  328: 
  329: int scsiLogSense(scsi_device * device, int pagenum, int subpagenum, UINT8 *pBuf,
  330:                  int bufLen, int known_resp_len);
  331: 
  332: int scsiLogSelect(scsi_device * device, int pcr, int sp, int pc, int pagenum,
  333:                   int subpagenum, UINT8 *pBuf, int bufLen);
  334: 
  335: int scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc,
  336:                   UINT8 *pBuf, int bufLen);
  337: 
  338: int scsiModeSelect(scsi_device * device, int sp, UINT8 *pBuf, int bufLen);
  339: 
  340: int scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc,
  341:                     UINT8 *pBuf, int bufLen);
  342: 
  343: int scsiModeSelect10(scsi_device * device, int sp, UINT8 *pBuf, int bufLen);
  344: 
  345: int scsiModePageOffset(const UINT8 * resp, int len, int modese_len);
  346: 
  347: int scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info);
  348: 
  349: int scsiSendDiagnostic(scsi_device * device, int functioncode, UINT8 *pBuf, int bufLen);
  350: 
  351: int scsiReceiveDiagnostic(scsi_device * device, int pcv, int pagenum, UINT8 *pBuf,
  352:                       int bufLen);
  353: 
  354: int scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, int dl_format,
  355:                      UINT8 *pBuf, int bufLen);
  356: 
  357: int scsiReadCapacity10(scsi_device * device, unsigned int * last_lbp,
  358:                        unsigned int * lb_sizep);
  359: 
  360: int scsiReadCapacity16(scsi_device * device, UINT8 *pBuf, int bufLen);
  361: 
  362: uint64_t scsiGetSize(scsi_device * device, unsigned int * lb_sizep);
  363: 
  364: 
  365: /* SMART specific commands */
  366: int scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage, UINT8 *asc,
  367:                 UINT8 *ascq, UINT8 *currenttemp, UINT8 *triptemp);
  368: 
  369: int scsiFetchIECmpage(scsi_device * device, struct scsi_iec_mode_page *iecp,
  370:                       int modese_len);
  371: int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp);
  372: int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp);
  373: int scsiSetExceptionControlAndWarning(scsi_device * device, int enabled,
  374:                             const struct scsi_iec_mode_page *iecp);
  375: void scsiDecodeErrCounterPage(unsigned char * resp,
  376:                               struct scsiErrorCounter *ecp);
  377: void scsiDecodeNonMediumErrPage(unsigned char * resp,
  378:                                 struct scsiNonMediumError *nmep);
  379: int scsiFetchExtendedSelfTestTime(scsi_device * device, int * durationSec,
  380:                                   int modese_len);
  381: int scsiCountFailedSelfTests(scsi_device * device, int noisy);
  382: int scsiSelfTestInProgress(scsi_device * device, int * inProgress);
  383: int scsiFetchControlGLTSD(scsi_device * device, int modese_len, int current);
  384: int scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len);
  385: int scsiFetchTransportProtocol(scsi_device * device, int modese_len);
  386: 
  387: 
  388: /* T10 Standard IE Additional Sense Code strings taken from t10.org */
  389: const char* scsiGetIEString(UINT8 asc, UINT8 ascq);
  390: int scsiGetTemp(scsi_device * device, UINT8 *currenttemp, UINT8 *triptemp);
  391: 
  392: 
  393: int scsiSmartIBMOfflineTest(scsi_device * device);
  394: 
  395: int scsiSmartDefaultSelfTest(scsi_device * device);
  396: int scsiSmartShortSelfTest(scsi_device * device);
  397: int scsiSmartExtendSelfTest(scsi_device * device);
  398: int scsiSmartShortCapSelfTest(scsi_device * device);
  399: int scsiSmartExtendCapSelfTest(scsi_device * device);
  400: int scsiSmartSelfTestAbort(scsi_device * device);
  401: 
  402: const char * scsiTapeAlertsTapeDevice(unsigned short code);
  403: const char * scsiTapeAlertsChangerDevice(unsigned short code);
  404: 
  405: const char * scsi_get_opcode_name(UINT8 opcode);
  406: void dStrHex(const char* str, int len, int no_ascii);
  407: inline void dStrHex(const unsigned char* str, int len, int no_ascii)
  408:   { dStrHex((const char *)str, len, no_ascii); }
  409: 
  410: 
  411: /* SCSI command transmission interface function declaration. Its
  412:  * definition is target OS specific (see os_<OS>.c file).
  413:  * Returns 0 if SCSI command successfully launched and response
  414:  * received. Even when 0 is returned the caller should check
  415:  * scsi_cmnd_io::scsi_status for SCSI defined errors and warnings
  416:  * (e.g. CHECK CONDITION). If the SCSI command could not be issued
  417:  * (e.g. device not present or not a SCSI device) or some other problem
  418:  * arises (e.g. timeout) then returns a negative errno value. */
  419: // Moved to C++ interface
  420: //int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report);
  421: 
  422: 
  423: 
  424: #endif
  425: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>