Annotation of embedaddon/smartmontools/scsicmds.h, revision 1.1.1.2
1.1 misho 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:
1.1.1.2 ! misho 10: * Copyright (C) 2003-13 Douglas Gilbert <dgilbert@interlog.com>
1.1 misho 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
1.1.1.2 ! misho 18: * (for example COPYING); if not, write to the Free Software Foundation,
! 19: * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1.1 misho 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:
1.1.1.2 ! misho 35: #define SCSICMDS_H_CVSID "$Id: scsicmds.h 3783 2013-03-02 01:51:12Z dpgilbert $\n"
1.1 misho 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
1.1.1.2 ! misho 81: #ifndef READ_DEFECT_12
! 82: #define READ_DEFECT_12 0xb7
! 83: #endif
1.1 misho 84: #ifndef START_STOP_UNIT
85: #define START_STOP_UNIT 0x1b
86: #endif
87: #ifndef REPORT_LUNS
88: #define REPORT_LUNS 0xa0
89: #endif
90: #ifndef READ_CAPACITY_10
91: #define READ_CAPACITY_10 0x25
92: #endif
93: #ifndef READ_CAPACITY_16
94: #define READ_CAPACITY_16 0x9e
95: #endif
96: #ifndef SAI_READ_CAPACITY_16 /* service action for READ_CAPACITY_16 */
97: #define SAI_READ_CAPACITY_16 0x10
98: #endif
99:
100: #ifndef SAT_ATA_PASSTHROUGH_12
101: #define SAT_ATA_PASSTHROUGH_12 0xa1
102: #endif
103: #ifndef SAT_ATA_PASSTHROUGH_16
104: #define SAT_ATA_PASSTHROUGH_16 0x85
105: #endif
106:
107: typedef unsigned char UINT8;
108: typedef signed char INT8;
109: typedef unsigned int UINT32;
110: typedef int INT32;
111:
112: #define DXFER_NONE 0
113: #define DXFER_FROM_DEVICE 1
114: #define DXFER_TO_DEVICE 2
115:
116: struct scsi_cmnd_io
117: {
118: UINT8 * cmnd; /* [in]: ptr to SCSI command block (cdb) */
119: size_t cmnd_len; /* [in]: number of bytes in SCSI command */
1.1.1.2 ! misho 120: int dxfer_dir; /* [in]: DXFER_NONE, DXFER_FROM_DEVICE, or
1.1 misho 121: DXFER_TO_DEVICE */
122: UINT8 * dxferp; /* [in]: ptr to outgoing or incoming data buffer */
123: size_t dxfer_len; /* [in]: bytes to be transferred to/from dxferp */
1.1.1.2 ! misho 124: UINT8 * sensep; /* [in]: ptr to sense buffer, filled when
1.1 misho 125: CHECK CONDITION status occurs */
126: size_t max_sense_len; /* [in]: max number of bytes to write to sensep */
127: unsigned timeout; /* [in]: seconds, 0-> default timeout (60 seconds?) */
128: size_t resp_sense_len; /* [out]: sense buffer length written */
129: UINT8 scsi_status; /* [out]: 0->ok, 2->CHECK CONDITION, etc ... */
130: int resid; /* [out]: Number of bytes requested to be transferred
131: less actual number transferred (0 if not
132: supported) */
133: };
134:
135: struct scsi_sense_disect {
1.1.1.2 ! misho 136: UINT8 resp_code;
1.1 misho 137: UINT8 sense_key;
1.1.1.2 ! misho 138: UINT8 asc;
1.1 misho 139: UINT8 ascq;
1.1.1.2 ! misho 140: int progress; /* -1 -> N/A, 0-65535 -> available */
1.1 misho 141: };
142:
143: /* Useful data from Informational Exception Control mode page (0x1c) */
144: #define SCSI_IECMP_RAW_LEN 64
145: struct scsi_iec_mode_page {
146: UINT8 requestedCurrent;
147: UINT8 gotCurrent;
148: UINT8 requestedChangeable;
149: UINT8 gotChangeable;
150: UINT8 modese_len; /* 0 (don't know), 6 or 10 */
151: UINT8 raw_curr[SCSI_IECMP_RAW_LEN];
152: UINT8 raw_chg[SCSI_IECMP_RAW_LEN];
153: };
154:
155: /* Carrier for Error counter log pages (e.g. read, write, verify ...) */
156: struct scsiErrorCounter {
157: UINT8 gotPC[7];
158: UINT8 gotExtraPC;
159: uint64_t counter[8];
160: };
161:
162: /* Carrier for Non-medium error log page */
163: struct scsiNonMediumError {
164: UINT8 gotPC0;
165: UINT8 gotExtraPC;
166: uint64_t counterPC0;
167: UINT8 gotTFE_H;
168: uint64_t counterTFE_H; /* Track following errors [Hitachi] */
169: UINT8 gotPE_H;
170: uint64_t counterPE_H; /* Positioning errors [Hitachi] */
171: };
172:
173: /* SCSI Peripheral types (of interest) */
174: #define SCSI_PT_DIRECT_ACCESS 0x0
175: #define SCSI_PT_SEQUENTIAL_ACCESS 0x1
176: #define SCSI_PT_CDROM 0x5
177: #define SCSI_PT_MEDIUM_CHANGER 0x8
178: #define SCSI_PT_ENCLOSURE 0xd
179:
180: /* ANSI SCSI-3 Log Pages retrieved by LOG SENSE. */
181: #define SUPPORTED_LPAGES 0x00
182: #define BUFFER_OVERRUN_LPAGE 0x01
183: #define WRITE_ERROR_COUNTER_LPAGE 0x02
184: #define READ_ERROR_COUNTER_LPAGE 0x03
185: #define READ_REVERSE_ERROR_COUNTER_LPAGE 0x04
186: #define VERIFY_ERROR_COUNTER_LPAGE 0x05
187: #define NON_MEDIUM_ERROR_LPAGE 0x06
188: #define LAST_N_ERROR_LPAGE 0x07
189: #define FORMAT_STATUS_LPAGE 0x08
190: #define LB_PROV_LPAGE 0x0c /* SBC-3 */
191: #define TEMPERATURE_LPAGE 0x0d
192: #define STARTSTOP_CYCLE_COUNTER_LPAGE 0x0e
193: #define APPLICATION_CLIENT_LPAGE 0x0f
194: #define SELFTEST_RESULTS_LPAGE 0x10
195: #define SS_MEDIA_LPAGE 0x11 /* SBC-3 */
196: #define BACKGROUND_RESULTS_LPAGE 0x15 /* SBC-3 */
197: #define NONVOL_CACHE_LPAGE 0x17 /* SBC-3 */
198: #define PROTOCOL_SPECIFIC_LPAGE 0x18
199: #define IE_LPAGE 0x2f
200:
201: /* Seagate vendor specific log pages. */
202: #define SEAGATE_CACHE_LPAGE 0x37
203: #define SEAGATE_FACTORY_LPAGE 0x3e
204:
205: /* Log page response lengths */
206: #define LOG_RESP_SELF_TEST_LEN 0x194
207:
1.1.1.2 ! misho 208: /* See the SSC-2 document at www.t10.org . Earler note: From IBM
1.1 misho 209: Documentation, see http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */
210: #define TAPE_ALERTS_LPAGE 0x2e
211:
212: /* ANSI SCSI-3 Mode Pages */
213: #define VENDOR_UNIQUE_PAGE 0x00
214: #define READ_WRITE_ERROR_RECOVERY_PAGE 0x01
215: #define DISCONNECT_RECONNECT_PAGE 0x02
216: #define FORMAT_DEVICE_PAGE 0x03
217: #define RIGID_DISK_DRIVE_GEOMETRY_PAGE 0x04
218: #define FLEXIBLE_DISK_PAGE 0x05
219: #define VERIFY_ERROR_RECOVERY_PAGE 0x07
220: #define CACHING_PAGE 0x08
221: #define PERIPHERAL_DEVICE_PAGE 0x09
222: #define XOR_CONTROL_MODE_PAGE 0x10
223: #define CONTROL_MODE_PAGE 0x0a
224: #define MEDIUM_TYPES_SUPPORTED_PAGE 0x0b
225: #define NOTCH_PAGE 0x0c
226: #define CD_DEVICE_PAGE 0x0d
227: #define CD_AUDIO_CONTROL_PAGE 0x0e
228: #define DATA_COMPRESSION_PAGE 0x0f
229: #define ENCLOSURE_SERVICES_MANAGEMENT_PAGE 0x14
230: #define PROTOCOL_SPECIFIC_LUN_PAGE 0x18
231: #define PROTOCOL_SPECIFIC_PORT_PAGE 0x19
232: #define POWER_CONDITION_PAGE 0x1a
233: #define INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE 0x1c
234: #define FAULT_FAILURE_REPORTING_PAGE 0x1c
235:
236: /* Background control mode subpage is [0x1c,0x1] */
237: #define BACKGROUND_CONTROL_M_SUBPAGE 0x1 /* SBC-2 */
238:
239: #define ALL_MODE_PAGES 0x3f
240:
241: /* Mode page control field */
242: #define MPAGE_CONTROL_CURRENT 0
243: #define MPAGE_CONTROL_CHANGEABLE 1
244: #define MPAGE_CONTROL_DEFAULT 2
245: #define MPAGE_CONTROL_SAVED 3
246:
1.1.1.2 ! misho 247: /* SCSI Vital Product Data (VPD) pages */
! 248: #define SCSI_VPD_SUPPORTED_VPD_PAGES 0x0
! 249: #define SCSI_VPD_UNIT_SERIAL_NUMBER 0x80
! 250: #define SCSI_VPD_DEVICE_IDENTIFICATION 0x83
! 251: #define SCSI_VPD_EXTENDED_INQUIRY_DATA 0x86
! 252: #define SCSI_VPD_ATA_INFORMATION 0x89
! 253: #define SCSI_VPD_POWER_CONDITION 0x8a
! 254: #define SCSI_VPD_POWER_CONSUMPTION 0x8d
! 255: #define SCSI_VPD_BLOCK_LIMITS 0xb0
! 256: #define SCSI_VPD_BLOCK_DEVICE_CHARACTERISTICS 0xb1
! 257: #define SCSI_VPD_LOGICAL_BLOCK_PROVISIONING 0xb2
! 258:
1.1 misho 259: /* defines for useful SCSI Status codes */
260: #define SCSI_STATUS_CHECK_CONDITION 0x2
261:
262: /* defines for useful Sense Key codes */
263: #define SCSI_SK_NO_SENSE 0x0
264: #define SCSI_SK_RECOVERED_ERR 0x1
265: #define SCSI_SK_NOT_READY 0x2
266: #define SCSI_SK_MEDIUM_ERROR 0x3
267: #define SCSI_SK_HARDWARE_ERROR 0x4
268: #define SCSI_SK_ILLEGAL_REQUEST 0x5
269: #define SCSI_SK_UNIT_ATTENTION 0x6
270: #define SCSI_SK_ABORTED_COMMAND 0xb
271:
272: /* defines for useful Additional Sense Codes (ASCs) */
273: #define SCSI_ASC_NOT_READY 0x4 /* more info in ASCQ code */
274: #define SCSI_ASC_NO_MEDIUM 0x3a /* more info in ASCQ code */
275: #define SCSI_ASC_UNKNOWN_OPCODE 0x20
1.1.1.2 ! misho 276: #define SCSI_ASC_INVALID_FIELD 0x24
1.1 misho 277: #define SCSI_ASC_UNKNOWN_PARAM 0x26
278: #define SCSI_ASC_WARNING 0xb
279: #define SCSI_ASC_IMPENDING_FAILURE 0x5d
280:
281: #define SCSI_ASCQ_ATA_PASS_THROUGH 0x1d
282:
283: /* Simplified error code (negative values as per errno) */
284: #define SIMPLE_NO_ERROR 0
285: #define SIMPLE_ERR_NOT_READY 1
286: #define SIMPLE_ERR_BAD_OPCODE 2
287: #define SIMPLE_ERR_BAD_FIELD 3 /* in cbd */
288: #define SIMPLE_ERR_BAD_PARAM 4 /* in data */
289: #define SIMPLE_ERR_BAD_RESP 5 /* response fails sanity */
290: #define SIMPLE_ERR_NO_MEDIUM 6 /* no medium present */
291: #define SIMPLE_ERR_BECOMING_READY 7 /* device will be ready soon */
292: #define SIMPLE_ERR_TRY_AGAIN 8 /* some warning, try again */
293: #define SIMPLE_ERR_MEDIUM_HARDWARE 9 /* medium or hardware error */
294: #define SIMPLE_ERR_UNKNOWN 10 /* unknown sense value */
295: #define SIMPLE_ERR_ABORTED_COMMAND 11 /* most likely transport error */
296:
297:
298: /* defines for functioncode parameter in SENDDIAGNOSTIC function */
299: #define SCSI_DIAG_NO_SELF_TEST 0x00
300: #define SCSI_DIAG_DEF_SELF_TEST 0xff
301: #define SCSI_DIAG_BG_SHORT_SELF_TEST 0x01
302: #define SCSI_DIAG_BG_EXTENDED_SELF_TEST 0x02
303: #define SCSI_DIAG_FG_SHORT_SELF_TEST 0x05
304: #define SCSI_DIAG_FG_EXTENDED_SELF_TEST 0x06
305: #define SCSI_DIAG_ABORT_SELF_TEST 0x04
306:
307:
308: /* SCSI command timeout values (units are seconds) */
309: #define SCSI_TIMEOUT_DEFAULT 20 // should be longer than the spin up time
310: // of a disk in standby mode.
311: #define SCSI_TIMEOUT_SELF_TEST (5 * 60 * 60) /* allow max 5 hours for */
312: /* extended foreground self test */
313:
314:
315:
316: #define LOGPAGEHDRSIZE 4
317:
318: class scsi_device;
319:
1.1.1.2 ! misho 320: // Set of supported SCSI VPD pages. Constructor fetches Supported VPD pages
! 321: // VPD page and remembers the response for later queries.
! 322: class supported_vpd_pages
! 323: {
! 324: public:
! 325: supported_vpd_pages(scsi_device * device);
! 326: ~supported_vpd_pages() { num_valid = 0; }
! 327:
! 328: bool is_supported(int vpd_page_num) const;
! 329:
! 330: /* Returns 0 or less for VPD pages not supported or error */
! 331: int num_pages() const { return num_valid; }
! 332:
! 333: private:
! 334: int num_valid; /* 0 or less for invalid */
! 335: unsigned char pages[256];
! 336: };
! 337:
! 338: extern supported_vpd_pages * supported_vpd_pages_p;
! 339:
! 340:
1.1 misho 341: // Print SCSI debug messages?
342: extern unsigned char scsi_debugmode;
343:
344: void scsi_do_sense_disect(const struct scsi_cmnd_io * in,
345: struct scsi_sense_disect * out);
346:
347: int scsiSimpleSenseFilter(const struct scsi_sense_disect * sinfo);
348:
349: const char * scsiErrString(int scsiErr);
350:
351: int scsi_vpd_dev_id_iter(const unsigned char * initial_desig_desc,
352: int page_len, int * off, int m_assoc,
353: int m_desig_type, int m_code_set);
354:
355: int scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s,
356: int slen, int * transport);
357:
358:
359: /* STANDARD SCSI Commands */
360: int scsiTestUnitReady(scsi_device * device);
361:
362: int scsiStdInquiry(scsi_device * device, UINT8 *pBuf, int bufLen);
363:
364: int scsiInquiryVpd(scsi_device * device, int vpd_page, UINT8 *pBuf, int bufLen);
365:
366: int scsiLogSense(scsi_device * device, int pagenum, int subpagenum, UINT8 *pBuf,
367: int bufLen, int known_resp_len);
368:
369: int scsiLogSelect(scsi_device * device, int pcr, int sp, int pc, int pagenum,
370: int subpagenum, UINT8 *pBuf, int bufLen);
371:
372: int scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc,
373: UINT8 *pBuf, int bufLen);
374:
375: int scsiModeSelect(scsi_device * device, int sp, UINT8 *pBuf, int bufLen);
376:
377: int scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc,
378: UINT8 *pBuf, int bufLen);
379:
380: int scsiModeSelect10(scsi_device * device, int sp, UINT8 *pBuf, int bufLen);
381:
382: int scsiModePageOffset(const UINT8 * resp, int len, int modese_len);
383:
384: int scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info);
385:
386: int scsiSendDiagnostic(scsi_device * device, int functioncode, UINT8 *pBuf, int bufLen);
387:
388: int scsiReceiveDiagnostic(scsi_device * device, int pcv, int pagenum, UINT8 *pBuf,
389: int bufLen);
390:
391: int scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, int dl_format,
392: UINT8 *pBuf, int bufLen);
393:
1.1.1.2 ! misho 394: int scsiReadDefect12(scsi_device * device, int req_plist, int req_glist,
! 395: int dl_format, int addrDescIndex, UINT8 *pBuf, int bufLen);
! 396:
1.1 misho 397: int scsiReadCapacity10(scsi_device * device, unsigned int * last_lbp,
398: unsigned int * lb_sizep);
399:
400: int scsiReadCapacity16(scsi_device * device, UINT8 *pBuf, int bufLen);
401:
402: /* SMART specific commands */
403: int scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage, UINT8 *asc,
404: UINT8 *ascq, UINT8 *currenttemp, UINT8 *triptemp);
405:
406: int scsiFetchIECmpage(scsi_device * device, struct scsi_iec_mode_page *iecp,
407: int modese_len);
408: int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp);
409: int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp);
410: int scsiSetExceptionControlAndWarning(scsi_device * device, int enabled,
411: const struct scsi_iec_mode_page *iecp);
412: void scsiDecodeErrCounterPage(unsigned char * resp,
413: struct scsiErrorCounter *ecp);
414: void scsiDecodeNonMediumErrPage(unsigned char * resp,
415: struct scsiNonMediumError *nmep);
416: int scsiFetchExtendedSelfTestTime(scsi_device * device, int * durationSec,
417: int modese_len);
418: int scsiCountFailedSelfTests(scsi_device * device, int noisy);
419: int scsiSelfTestInProgress(scsi_device * device, int * inProgress);
420: int scsiFetchControlGLTSD(scsi_device * device, int modese_len, int current);
421: int scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len);
422: int scsiFetchTransportProtocol(scsi_device * device, int modese_len);
1.1.1.2 ! misho 423: int scsiGetRPM(scsi_device * device, int modese_len, int * form_factorp);
! 424: int scsiGetSetCache(scsi_device * device, int modese_len, short int * wce,
! 425: short int * rcd);
! 426: uint64_t scsiGetSize(scsi_device * device, unsigned int * lb_sizep,
! 427: int * lb_per_pb_expp);
! 428: int scsiGetProtPBInfo(scsi_device * device, unsigned char * rc16_12_31p);
1.1 misho 429:
430: /* T10 Standard IE Additional Sense Code strings taken from t10.org */
431: const char* scsiGetIEString(UINT8 asc, UINT8 ascq);
432: int scsiGetTemp(scsi_device * device, UINT8 *currenttemp, UINT8 *triptemp);
433:
434:
435: int scsiSmartIBMOfflineTest(scsi_device * device);
436:
437: int scsiSmartDefaultSelfTest(scsi_device * device);
438: int scsiSmartShortSelfTest(scsi_device * device);
439: int scsiSmartExtendSelfTest(scsi_device * device);
440: int scsiSmartShortCapSelfTest(scsi_device * device);
441: int scsiSmartExtendCapSelfTest(scsi_device * device);
442: int scsiSmartSelfTestAbort(scsi_device * device);
443:
444: const char * scsiTapeAlertsTapeDevice(unsigned short code);
445: const char * scsiTapeAlertsChangerDevice(unsigned short code);
446:
447: const char * scsi_get_opcode_name(UINT8 opcode);
1.1.1.2 ! misho 448: void scsi_format_id_string(char * out, const unsigned char * in, int n);
! 449:
1.1 misho 450: void dStrHex(const char* str, int len, int no_ascii);
451: inline void dStrHex(const unsigned char* str, int len, int no_ascii)
452: { dStrHex((const char *)str, len, no_ascii); }
453:
1.1.1.2 ! misho 454: /* Attempt to find the first SCSI sense data descriptor that matches the
! 455: given 'desc_type'. If found return pointer to start of sense data
! 456: descriptor; otherwise (including fixed format sense data) returns NULL. */
! 457: const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep,
! 458: int sense_len, int desc_type);
! 459:
1.1 misho 460:
461: /* SCSI command transmission interface function declaration. Its
462: * definition is target OS specific (see os_<OS>.c file).
463: * Returns 0 if SCSI command successfully launched and response
464: * received. Even when 0 is returned the caller should check
465: * scsi_cmnd_io::scsi_status for SCSI defined errors and warnings
466: * (e.g. CHECK CONDITION). If the SCSI command could not be issued
467: * (e.g. device not present or not a SCSI device) or some other problem
468: * arises (e.g. timeout) then returns a negative errno value. */
469: // Moved to C++ interface
470: //int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report);
471:
472:
473:
474: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>