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