atacmds.cpp 86.3 KB
Newer Older
ballen4705's avatar
ballen4705 committed
1
/*
chrfranke's avatar
chrfranke committed
2
 * atacmds.cpp
3
4
 * 
 * Home page of code is: http://smartmontools.sourceforge.net
ballen4705's avatar
ballen4705 committed
5
 *
6
7
 * Copyright (C) 2002-10 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 * Copyright (C) 2008-10 Christian Franke <smartmontools-support@lists.sourceforge.net>
ballen4705's avatar
ballen4705 committed
8
9
10
11
12
13
14
15
16
17
18
 * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
 * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * You should have received a copy of the GNU General Public License
 * (for example COPYING); if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
ballen4705's avatar
ballen4705 committed
19
20
21
22
23
24
 *
 * 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/
 * 
ballen4705's avatar
ballen4705 committed
25
26
27
28
 */

#include <stdio.h>
#include <string.h>
29
#include <errno.h>
30
#include <stdlib.h>
31
#include <ctype.h>
32
33

#include "config.h"
34
#include "int64.h"
35
#include "atacmds.h"
36
#include "extern.h"
37
#include "utility.h"
38
#include "dev_ata_cmd_set.h" // for parsed_ata_device
39

40
41
const char * atacmds_cpp_cvsid = "$Id$"
                                 ATACMDS_H_CVSID;
42

43
44
// for passing global control variables
extern smartmonctrl *con;
ballen4705's avatar
ballen4705 committed
45

46
47
48
#define SMART_CYL_LOW  0x4F
#define SMART_CYL_HI   0xC2

49
50
51
52
53
54
55
// SMART RETURN STATUS yields SMART_CYL_HI,SMART_CYL_LOW to indicate drive
// is healthy and SRET_STATUS_HI_EXCEEDED,SRET_STATUS_MID_EXCEEDED to
// indicate that a threshhold exceeded condition has been detected.
// Those values (byte pairs) are placed in ATA register "LBA 23:8".
#define SRET_STATUS_HI_EXCEEDED 0x2C
#define SRET_STATUS_MID_EXCEEDED 0xF4

56
57
58
59
60
// These Drive Identity tables are taken from hdparm 5.2, and are also
// given in the ATA/ATAPI specs for the IDENTIFY DEVICE command.  Note
// that SMART was first added into the ATA/ATAPI-3 Standard with
// Revision 3 of the document, July 25, 1995.  Look at the "Document
// Status" revision commands at the beginning of
61
62
// http://www.t13.org/Documents/UploadedDocuments/project/d2008r7b-ATA-3.pdf
// to see this.
63
64
#define NOVAL_0                 0x0000
#define NOVAL_1                 0xffff
65
/* word 81: minor version number */
66
#define MINOR_MAX 0x22
67
static const char * const minor_str[] = {       /* word 81 value: */
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
  "Device does not report version",             /* 0x0000       */
  "ATA-1 X3T9.2 781D prior to revision 4",      /* 0x0001       */
  "ATA-1 published, ANSI X3.221-1994",          /* 0x0002       */
  "ATA-1 X3T9.2 781D revision 4",               /* 0x0003       */
  "ATA-2 published, ANSI X3.279-1996",          /* 0x0004       */
  "ATA-2 X3T10 948D prior to revision 2k",      /* 0x0005       */
  "ATA-3 X3T10 2008D revision 1",               /* 0x0006       */ /* SMART NOT INCLUDED */
  "ATA-2 X3T10 948D revision 2k",               /* 0x0007       */
  "ATA-3 X3T10 2008D revision 0",               /* 0x0008       */ 
  "ATA-2 X3T10 948D revision 3",                /* 0x0009       */
  "ATA-3 published, ANSI X3.298-199x",          /* 0x000a       */
  "ATA-3 X3T10 2008D revision 6",               /* 0x000b       */ /* 1st VERSION WITH SMART */
  "ATA-3 X3T13 2008D revision 7 and 7a",        /* 0x000c       */
  "ATA/ATAPI-4 X3T13 1153D revision 6",         /* 0x000d       */
  "ATA/ATAPI-4 T13 1153D revision 13",          /* 0x000e       */
  "ATA/ATAPI-4 X3T13 1153D revision 7",         /* 0x000f       */
  "ATA/ATAPI-4 T13 1153D revision 18",          /* 0x0010       */
  "ATA/ATAPI-4 T13 1153D revision 15",          /* 0x0011       */
  "ATA/ATAPI-4 published, ANSI NCITS 317-1998", /* 0x0012       */
  "ATA/ATAPI-5 T13 1321D revision 3",           /* 0x0013       */
  "ATA/ATAPI-4 T13 1153D revision 14",          /* 0x0014       */
  "ATA/ATAPI-5 T13 1321D revision 1",           /* 0x0015       */
  "ATA/ATAPI-5 published, ANSI NCITS 340-2000", /* 0x0016       */
  "ATA/ATAPI-4 T13 1153D revision 17",          /* 0x0017       */
  "ATA/ATAPI-6 T13 1410D revision 0",           /* 0x0018       */
  "ATA/ATAPI-6 T13 1410D revision 3a",          /* 0x0019       */
  "ATA/ATAPI-7 T13 1532D revision 1",           /* 0x001a       */
  "ATA/ATAPI-6 T13 1410D revision 2",           /* 0x001b       */
  "ATA/ATAPI-6 T13 1410D revision 1",           /* 0x001c       */
97
  "ATA/ATAPI-7 published, ANSI INCITS 397-2005",/* 0x001d       */
98
99
100
101
102
  "ATA/ATAPI-7 T13 1532D revision 0",           /* 0x001e       */
  "reserved",                                   /* 0x001f       */
  "reserved",                                   /* 0x0020       */
  "ATA/ATAPI-7 T13 1532D revision 4a",          /* 0x0021       */
  "ATA/ATAPI-6 published, ANSI INCITS 361-2002" /* 0x0022       */
103
104
};

105
106
107
108
109
// NOTE ATA/ATAPI-4 REV 4 was the LAST revision where the device
// attribute structures were NOT completely vendor specific.  So any
// disk that is ATA/ATAPI-4 or above can not be trusted to show the
// vendor values in sensible format.

110
// Negative values below are because it doesn't support SMART
111
static const int actual_ver[] = { 
112
  /* word 81 value: */
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
  0,            /* 0x0000       WARNING:        */
  1,            /* 0x0001       WARNING:        */
  1,            /* 0x0002       WARNING:        */
  1,            /* 0x0003       WARNING:        */
  2,            /* 0x0004       WARNING:   This array           */
  2,            /* 0x0005       WARNING:   corresponds          */
  -3, /*<== */  /* 0x0006       WARNING:   *exactly*            */
  2,            /* 0x0007       WARNING:   to the ATA/          */
  -3, /*<== */  /* 0x0008       WARNING:   ATAPI version        */
  2,            /* 0x0009       WARNING:   listed in            */
  3,            /* 0x000a       WARNING:   the                  */
  3,            /* 0x000b       WARNING:   minor_str            */
  3,            /* 0x000c       WARNING:   array                */
  4,            /* 0x000d       WARNING:   above.               */
  4,            /* 0x000e       WARNING:                        */
  4,            /* 0x000f       WARNING:   If you change        */
  4,            /* 0x0010       WARNING:   that one,            */
  4,            /* 0x0011       WARNING:   change this one      */
  4,            /* 0x0012       WARNING:   too!!!               */
  5,            /* 0x0013       WARNING:        */
  4,            /* 0x0014       WARNING:        */
  5,            /* 0x0015       WARNING:        */
  5,            /* 0x0016       WARNING:        */
  4,            /* 0x0017       WARNING:        */
  6,            /* 0x0018       WARNING:        */
  6,            /* 0x0019       WARNING:        */
  7,            /* 0x001a       WARNING:        */
  6,            /* 0x001b       WARNING:        */
  6,            /* 0x001c       WARNING:        */
142
  7,            /* 0x001d       WARNING:        */
143
144
145
146
147
  7,            /* 0x001e       WARNING:        */
  0,            /* 0x001f       WARNING:        */
  0,            /* 0x0020       WARNING:        */
  7,            /* 0x0021       WARNING:        */
  6             /* 0x0022       WARNING:        */
148
149
};

150
151
// Get ID and increase flag of current pending or offline
// uncorrectable attribute.
152
unsigned char get_unc_attr_id(bool offline, const ata_vendor_attr_defs & defs,
153
154
155
                              bool & increase)
{
  unsigned char id = (!offline ? 197 : 198);
156
  increase = !!(defs[id].flags & ATTRFLAG_INCREASING);
157
158
159
  return id;
}

160
#if 0 // TODO: never used
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
// This are the meanings of the Self-test failure checkpoint byte.
// This is in the self-test log at offset 4 bytes into the self-test
// descriptor and in the SMART READ DATA structure at byte offset
// 371. These codes are not well documented.  The meanings returned by
// this routine are used (at least) by Maxtor and IBM. Returns NULL if
// not recognized.  Currently the maximum length is 15 bytes.
const char *SelfTestFailureCodeName(unsigned char which){
  
  switch (which) {
  case 0:
    return "Write_Test";
  case 1:
    return "Servo_Basic";
  case 2:
    return "Servo_Random";
  case 3:
    return "G-list_Scan";
  case 4:
    return "Handling_Damage";
  case 5:
    return "Read_Scan";
  default:
    return NULL;
  }
}
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#endif


// Table of raw print format names
struct format_name_entry
{
  const char * name;
  ata_attr_raw_format format;
};

const format_name_entry format_names[] = {
  {"raw8"           , RAWFMT_RAW8},
  {"raw16"          , RAWFMT_RAW16},
  {"raw48"          , RAWFMT_RAW48},
200
  {"hex48"          , RAWFMT_HEX48},
201
  {"raw64"          , RAWFMT_RAW64},
202
  {"hex64"          , RAWFMT_HEX64},
203
204
205
206
207
208
209
210
211
  {"raw16(raw16)"   , RAWFMT_RAW16_OPT_RAW16},
  {"raw16(avg16)"   , RAWFMT_RAW16_OPT_AVG16},
  {"raw24/raw24"    , RAWFMT_RAW24_RAW24},
  {"sec2hour"       , RAWFMT_SEC2HOUR},
  {"min2hour"       , RAWFMT_MIN2HOUR},
  {"halfmin2hour"   , RAWFMT_HALFMIN2HOUR},
  {"tempminmax"     , RAWFMT_TEMPMINMAX},
  {"temp10x"        , RAWFMT_TEMP10X},
};
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
const unsigned num_format_names = sizeof(format_names)/sizeof(format_names[0]);

// Table to map old to new '-v' option arguments
const char * map_old_vendor_opts[][2] = {
  {  "9,halfminutes"              , "9,halfmin2hour,Power_On_Half_Minutes"},
  {  "9,minutes"                  , "9,min2hour,Power_On_Minutes"},
  {  "9,seconds"                  , "9,sec2hour,Power_On_Seconds"},
  {  "9,temp"                     , "9,tempminmax,Temperature_Celsius"},
  {"192,emergencyretractcyclect"  , "192,raw48,Emerg_Retract_Cycle_Ct"},
  {"193,loadunload"               , "193,raw24/raw24"},
  {"194,10xCelsius"               , "194,temp10x,Temperature_Celsius_x10"},
  {"194,unknown"                  , "194,raw48,Unknown_Attribute"},
  {"197,increasing"               , "197,raw48+,Total_Pending_Sectors"}, // '+' sets flag
  {"198,offlinescanuncsectorct"   , "198,raw48,Offline_Scan_UNC_SectCt"},
  {"198,increasing"               , "198,raw48+,Total_Offl_Uncorrectabl"}, // '+' sets flag
  {"200,writeerrorcount"          , "200,raw48,Write_Error_Count"},
  {"201,detectedtacount"          , "201,raw48,Detected_TA_Count"},
  {"220,temp"                     , "220,raw48,Temperature_Celsius"},
};

const unsigned num_old_vendor_opts = sizeof(map_old_vendor_opts)/sizeof(map_old_vendor_opts[0]);

// Parse vendor attribute display def (-v option).
// Return false on error.
bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs,
                         ata_vendor_def_prior priority)
239
{
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  // Map old -> new options
  unsigned i;
  for (i = 0; i < num_old_vendor_opts; i++) {
    if (!strcmp(opt, map_old_vendor_opts[i][0])) {
      opt = map_old_vendor_opts[i][1];
      break;
    }
  }

  // Parse option
  int len = strlen(opt);
  int id = 0, n1 = -1, n2 = -1;
  char fmtname[32+1], attrname[32+1];
  if (opt[0] == 'N') {
    // "N,format"
255
256
    if (!(   sscanf(opt, "N,%32[^,]%n,%32[^,]%n", fmtname, &n1, attrname, &n2) >= 1
          && (n1 == len || n2 == len)))
257
      return false;
258
259
  }
  else {
260
261
262
263
    // "id,format[+][,name]"
    if (!(   sscanf(opt, "%d,%32[^,]%n,%32[^,]%n", &id, fmtname, &n1, attrname, &n2) >= 2
          && 1 <= id && id <= 255 && (n1 == len || n2 == len)))
      return false;
264
  }
265
266
  if (n1 == len)
    attrname[0] = 0;
267

268
269
270
271
272
273
274
  unsigned flags = 0;
  // For "-v 19[78],increasing" above
  if (fmtname[strlen(fmtname)-1] == '+') {
    fmtname[strlen(fmtname)-1] = 0;
    flags = ATTRFLAG_INCREASING;
  }

275
276
277
278
279
280
281
282
283
284
285
286
287
  // Split "format[:byteorder]"
  char byteorder[8+1] = "";
  if (strchr(fmtname, ':')) {
    if (!(   sscanf(fmtname, "%*[^:]%n:%8[012345rvwz]%n", &n1, byteorder, &n2) >= 1
          && n2 == (int)strlen(fmtname)))
      return false;
    fmtname[n1] = 0;
    if (strchr(byteorder, 'v'))
      flags |= (ATTRFLAG_NO_NORMVAL|ATTRFLAG_NO_WORSTVAL);
    if (strchr(byteorder, 'w'))
      flags |= ATTRFLAG_NO_WORSTVAL;
  }

288
  // Find format name
289
  for (i = 0; ; i++) {
290
291
292
    if (i >= num_format_names)
      return false; // Not found
    if (!strcmp(fmtname, format_names[i].name))
293
      break;
294
  }
295
  ata_attr_raw_format format = format_names[i].format;
296

297
298
299
  // 64-bit formats use the normalized and worst value bytes.
  if (!*byteorder && (format == RAWFMT_RAW64 || format == RAWFMT_HEX64))
    flags |= (ATTRFLAG_NO_NORMVAL|ATTRFLAG_NO_WORSTVAL);
300

301
  if (!id) {
302
    // "N,format" -> set format for all entries
303
304
    for (i = 0; i < MAX_ATTRIBUTE_NUM; i++) {
      if (defs[i].priority >= priority)
305
        continue;
306
      if (attrname[0])
307
308
309
310
        defs[i].name = attrname;
      defs[i].priority = priority;
      defs[i].raw_format = format;
      defs[i].flags = flags;
311
      strcpy(defs[i].byteorder, byteorder);
312
313
314
315
316
317
318
319
320
    }
  }
  else if (defs[id].priority <= priority) {
    // "id,format[,name]"
    if (attrname[0])
      defs[id].name = attrname;
    defs[id].raw_format = format;
    defs[id].priority = priority;
    defs[id].flags = flags;
321
    strcpy(defs[id].byteorder, byteorder);
322
323
  }

324
  return true;
325
326
}

327

328
329
// Return a multiline string containing a list of valid arguments for
// parse_attribute_def().  The strings are preceeded by tabs and followed
330
// (except for the last) by newlines.
331
332
333
std::string create_vendor_attribute_arg_list()
{
  std::string s;
334
335
  unsigned i;
  for (i = 0; i < num_format_names; i++)
336
    s += strprintf("%s\tN,%s[:012345rvwz][,ATTR_NAME]",
337
338
339
      (i>0 ? "\n" : ""), format_names[i].name);
  for (i = 0; i < num_old_vendor_opts; i++)
    s += strprintf("\n\t%s", map_old_vendor_opts[i][0]);
340
341
  return s;
}
342

343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
// swap two bytes.  Point to low address
void swap2(char *location){
  char tmp=*location;
  *location=*(location+1);
  *(location+1)=tmp;
  return;
}

// swap four bytes.  Point to low address
void swap4(char *location){
  char tmp=*location;
  *location=*(location+3);
  *(location+3)=tmp;
  swap2(location+1);
  return;
}
ballen4705's avatar
ballen4705 committed
359

360
361
362
363
364
365
366
367
368
369
370
// swap eight bytes.  Points to low address
void swap8(char *location){
  char tmp=*location;
  *location=*(location+7);
  *(location+7)=tmp;
  tmp=*(location+1);
  *(location+1)=*(location+6);
  *(location+6)=tmp;
  swap4(location+2);
  return;
}
371

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
// Invalidate serial number and adjust checksum in IDENTIFY data
static void invalidate_serno(ata_identify_device * id){
  unsigned char sum = 0;
  for (unsigned i = 0; i < sizeof(id->serial_no); i++) {
    sum += id->serial_no[i]; sum -= id->serial_no[i] = 'X';
  }
#ifndef __NetBSD__
  bool must_swap = !!isbigendian();
  if (must_swap)
    swapx(id->words088_255+255-88);
#endif
  if ((id->words088_255[255-88] & 0x00ff) == 0x00a5)
    id->words088_255[255-88] += sum << 8;
#ifndef __NetBSD__
  if (must_swap)
    swapx(id->words088_255+255-88);
#endif
}

391
static const char * const commandstrings[]={
392
393
394
395
396
397
398
399
400
401
402
  "SMART ENABLE",
  "SMART DISABLE",
  "SMART AUTOMATIC ATTRIBUTE SAVE",
  "SMART IMMEDIATE OFFLINE",
  "SMART AUTO OFFLINE",
  "SMART STATUS",
  "SMART STATUS CHECK",
  "SMART READ ATTRIBUTE VALUES",
  "SMART READ ATTRIBUTE THRESHOLDS",
  "SMART READ LOG",
  "IDENTIFY DEVICE",
403
404
  "IDENTIFY PACKET DEVICE",
  "CHECK POWER MODE",
405
  "SMART WRITE LOG",
406
  "WARNING (UNDEFINED COMMAND -- CONTACT DEVELOPERS AT " PACKAGE_BUGREPORT ")\n"
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

static const char * preg(const ata_register & r, char * buf)
{
  if (!r.is_set())
    //return "n/a ";
    return "....";
  sprintf(buf, "0x%02x", r.val()); return buf;
}

void print_regs(const char * prefix, const ata_in_regs & r, const char * suffix = "\n")
{
  char bufs[7][4+1+13];
  pout("%s FR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, CMD=%s%s", prefix,
    preg(r.features, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]),
    preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]),
    preg(r.command, bufs[6]), suffix);
}

void print_regs(const char * prefix, const ata_out_regs & r, const char * suffix = "\n")
{
  char bufs[7][4+1+13];
  pout("%sERR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, STS=%s%s", prefix,
    preg(r.error, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]),
    preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]),
433
    preg(r.status, bufs[6]), suffix);
434
435
}

436
static void prettyprint(const unsigned char *p, const char *name){
ballen4705's avatar
ballen4705 committed
437
  pout("\n===== [%s] DATA START (BASE-16) =====\n", name);
438
  for (int i=0; i<512; i+=16, p+=16)
439
#define P(n) (isprint((int)(p[n]))?(int)(p[n]):'.')
440
441
    // print complete line to avoid slow tty output and extra lines in syslog.
    pout("%03d-%03d: %02x %02x %02x %02x %02x %02x %02x %02x "
442
443
444
                    "%02x %02x %02x %02x %02x %02x %02x %02x"
                    " |%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c|"
         "%c",
445
446
         i, i+16-1,
         p[ 0], p[ 1], p[ 2], p[ 3], p[ 4], p[ 5], p[ 6], p[ 7],
447
448
449
450
451
         p[ 8], p[ 9], p[10], p[11], p[12], p[13], p[14], p[15], 
         P( 0), P( 1), P( 2), P( 3), P( 4), P( 5), P( 6), P( 7),
         P( 8), P( 9), P(10), P(11), P(12), P(13), P(14), P(15),
         '\n');
#undef P
ballen4705's avatar
ballen4705 committed
452
  pout("===== [%s] DATA END (512 Bytes) =====\n\n", name);
453
454
}

455
456
457
// This function provides the pretty-print reporting for SMART
// commands: it implements the various -r "reporting" options for ATA
// ioctls.
458
459
int smartcommandhandler(ata_device * device, smart_command_set command, int select, char *data){
  // TODO: Rework old stuff below
ballen4705's avatar
ballen4705 committed
460
461
  // This conditional is true for commands that return data
  int getsdata=(command==PIDENTIFY || 
462
463
464
                command==IDENTIFY || 
                command==READ_LOG || 
                command==READ_THRESHOLDS || 
465
                command==READ_VALUES ||
466
                command==CHECK_POWER_MODE);
467
468

  int sendsdata=(command==WRITE_LOG);
469
470
471
  
  // If reporting is enabled, say what the command will be before it's executed
  if (con->reportataioctl){
472
473
474
475
          // conditional is true for commands that use parameters
          int usesparam=(command==READ_LOG || 
                         command==AUTO_OFFLINE || 
                         command==AUTOSAVE || 
476
477
                         command==IMMEDIATE_OFFLINE ||
                         command==WRITE_LOG);
478
                  
479
    pout("\nREPORT-IOCTL: Device=%s Command=%s", device->get_dev_name(), commandstrings[command]);
ballen4705's avatar
ballen4705 committed
480
    if (usesparam)
481
482
483
484
485
      pout(" InputParameter=%d\n", select);
    else
      pout("\n");
  }
  
486
  if ((getsdata || sendsdata) && !data){
487
    pout("REPORT-IOCTL: Unable to execute command %s : data destination address is NULL\n", commandstrings[command]);
488
489
490
    return -1;
  }
  
491
492
493
  // The reporting is cleaner, and we will find coding bugs faster, if
  // the commands that failed clearly return empty (zeroed) data
  // structures
494
495
496
497
498
499
  if (getsdata) {
    if (command==CHECK_POWER_MODE)
      data[0]=0;
    else
      memset(data, '\0', 512);
  }
500

501

502
503
  // if requested, pretty-print the input data structure
  if (con->reportataioctl>1 && sendsdata)
504
    //pout("REPORT-IOCTL: Device=%s Command=%s\n", device->get_dev_name(), commandstrings[command]);
505
    prettyprint((unsigned char *)data, commandstrings[command]);
506

507
  // now execute the command
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
  int retval = -1;
  {
    ata_cmd_in in;
    // Set common register values
    switch (command) {
      default: // SMART commands
        in.in_regs.command = ATA_SMART_CMD;
        in.in_regs.lba_high = SMART_CYL_HI; in.in_regs.lba_mid = SMART_CYL_LOW;
        break;
      case IDENTIFY: case PIDENTIFY: case CHECK_POWER_MODE: // Non SMART commands
        break;
    }
    // Set specific values
    switch (command) {
      case IDENTIFY:
        in.in_regs.command = ATA_IDENTIFY_DEVICE;
524
        in.set_data_in(data, 1);
525
526
527
        break;
      case PIDENTIFY:
        in.in_regs.command = ATA_IDENTIFY_PACKET_DEVICE;
528
        in.set_data_in(data, 1);
529
530
531
532
533
534
535
        break;
      case CHECK_POWER_MODE:
        in.in_regs.command = ATA_CHECK_POWER_MODE;
        in.out_needed.sector_count = true; // Powermode returned here
        break;
      case READ_VALUES:
        in.in_regs.features = ATA_SMART_READ_VALUES;
536
        in.set_data_in(data, 1);
537
538
539
540
        break;
      case READ_THRESHOLDS:
        in.in_regs.features = ATA_SMART_READ_THRESHOLDS;
        in.in_regs.lba_low = 1; // TODO: CORRECT ???
541
        in.set_data_in(data, 1);
542
543
544
545
        break;
      case READ_LOG:
        in.in_regs.features = ATA_SMART_READ_LOG_SECTOR;
        in.in_regs.lba_low = select;
546
        in.set_data_in(data, 1);
547
548
549
550
        break;
      case WRITE_LOG:
        in.in_regs.features = ATA_SMART_WRITE_LOG_SECTOR;
        in.in_regs.lba_low = select;
551
        in.set_data_out(data, 1);
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
        break;
      case ENABLE:
        in.in_regs.features = ATA_SMART_ENABLE;
        in.in_regs.lba_low = 1; // TODO: CORRECT ???
        break;
      case DISABLE:
        in.in_regs.features = ATA_SMART_DISABLE;
        in.in_regs.lba_low = 1;  // TODO: CORRECT ???
        break;
      case STATUS_CHECK:
        in.out_needed.lba_high = in.out_needed.lba_mid = true; // Status returned here
      case STATUS:
        in.in_regs.features = ATA_SMART_STATUS;
        break;
      case AUTO_OFFLINE:
        in.in_regs.features = ATA_SMART_AUTO_OFFLINE;
        in.in_regs.sector_count = select;  // Caution: Non-DATA command!
        break;
      case AUTOSAVE:
        in.in_regs.features = ATA_SMART_AUTOSAVE;
        in.in_regs.sector_count = select;  // Caution: Non-DATA command!
        break;
      case IMMEDIATE_OFFLINE:
        in.in_regs.features = ATA_SMART_IMMEDIATE_OFFLINE;
        in.in_regs.lba_low = select;
        break;
      default:
        pout("Unrecognized command %d in smartcommandhandler()\n"
             "Please contact " PACKAGE_BUGREPORT "\n", command);
        device->set_err(ENOSYS);
        errno = ENOSYS;
        return -1;
    }

    if (con->reportataioctl)
      print_regs(" Input:  ", in.in_regs,
        (in.direction==ata_cmd_in::data_in ? " IN\n":
         in.direction==ata_cmd_in::data_out ? " OUT\n":"\n"));

    ata_cmd_out out;
    bool ok = device->ata_pass_through(in, out);

    if (con->reportataioctl && out.out_regs.is_set())
      print_regs(" Output: ", out.out_regs);

    if (ok) switch (command) {
      default:
        retval = 0;
        break;
      case CHECK_POWER_MODE:
        data[0] = out.out_regs.sector_count;
        retval = 0;
        break;
      case STATUS_CHECK:
        // Cyl low and Cyl high unchanged means "Good SMART status"
607
608
        if ((out.out_regs.lba_high == SMART_CYL_HI) &&
            (out.out_regs.lba_mid == SMART_CYL_LOW))
609
610
          retval = 0;
        // These values mean "Bad SMART status"
611
612
613
614
615
616
617
618
619
        else if ((out.out_regs.lba_high == SRET_STATUS_HI_EXCEEDED) &&
                 (out.out_regs.lba_mid == SRET_STATUS_MID_EXCEEDED))
          retval = 1;
        else if (out.out_regs.lba_mid == SMART_CYL_LOW) {
          retval = 0;
          if (con->reportataioctl)
            pout("SMART STATUS RETURN: half healthy response sequence, "
                 "probable SAT/USB truncation\n");
          } else if (out.out_regs.lba_mid == SRET_STATUS_MID_EXCEEDED) {
620
          retval = 1;
621
622
623
624
          if (con->reportataioctl)
            pout("SMART STATUS RETURN: half unhealthy response sequence, "
                 "probable SAT/USB truncation\n");
        } else {
625
          // We haven't gotten output that makes sense; print out some debugging info
626
627
628
629
          pout("Error SMART Status command failed\n");
          pout("Please get assistance from %s\n", PACKAGE_HOMEPAGE);
          pout("Register values returned from SMART Status command are:\n");
          print_regs(" ", out.out_regs);
630
631
632
633
634
          errno = EIO;
          retval = -1;
        }
        break;
    }
635
636
  }

637
638
639
640
  // If requested, invalidate serial number before any printing is done
  if ((command == IDENTIFY || command == PIDENTIFY) && !retval && con->dont_print_serial)
    invalidate_serno((ata_identify_device *)data);

641
642
  // If reporting is enabled, say what output was produced by the command
  if (con->reportataioctl){
643
644
645
646
    if (device->get_errno())
      pout("REPORT-IOCTL: Device=%s Command=%s returned %d errno=%d [%s]\n",
           device->get_dev_name(), commandstrings[command], retval,
           device->get_errno(), device->get_errmsg());
647
    else
648
649
      pout("REPORT-IOCTL: Device=%s Command=%s returned %d\n",
           device->get_dev_name(), commandstrings[command], retval);
650
    
651
    // if requested, pretty-print the output data structure
652
653
    if (con->reportataioctl>1 && getsdata) {
      if (command==CHECK_POWER_MODE)
654
	pout("Sector Count Register (BASE-16): %02x\n", (unsigned char)(*data));
655
656
657
      else
	prettyprint((unsigned char *)data, commandstrings[command]);
    }
658
  }
659
660

  errno = device->get_errno(); // TODO: Callers should not call syserror()
661
662
663
  return retval;
}

664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
// Get number of sectors from IDENTIFY sector. If the drive doesn't
// support LBA addressing or has no user writable sectors
// (eg, CDROM or DVD) then routine returns zero.
uint64_t get_num_sectors(const ata_identify_device * drive)
{
  unsigned short command_set_2  = drive->command_set_2;
  unsigned short capabilities_0 = drive->words047_079[49-47];
  unsigned short sects_16       = drive->words047_079[60-47];
  unsigned short sects_32       = drive->words047_079[61-47];
  unsigned short lba_16         = drive->words088_255[100-88];
  unsigned short lba_32         = drive->words088_255[101-88];
  unsigned short lba_48         = drive->words088_255[102-88];
  unsigned short lba_64         = drive->words088_255[103-88];

  // LBA support?
  if (!(capabilities_0 & 0x0200))
    return 0; // No

  // if drive supports LBA addressing, determine 32-bit LBA capacity
  uint64_t lba32 = (unsigned int)sects_32 << 16 |
                   (unsigned int)sects_16 << 0  ;

  uint64_t lba64 = 0;
  // if drive supports 48-bit addressing, determine THAT capacity
  if ((command_set_2 & 0xc000) == 0x4000 && (command_set_2 & 0x0400))
      lba64 = (uint64_t)lba_64 << 48 |
              (uint64_t)lba_48 << 32 |
              (uint64_t)lba_32 << 16 |
              (uint64_t)lba_16 << 0  ;

  // return the larger of the two possible capacities
  return (lba32 > lba64 ? lba32 : lba64);
}
697

698
699
700
// This function computes the checksum of a single disk sector (512
// bytes).  Returns zero if checksum is OK, nonzero if the checksum is
// incorrect.  The size (512) is correct for all SMART structures.
701
unsigned char checksum(const void * data)
702
{
703
704
705
  unsigned char sum = 0;
  for (int i = 0; i < 512; i++)
    sum += ((const unsigned char *)data)[i];
706
707
708
  return sum;
}

709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
// Copies n bytes (or n-1 if n is odd) from in to out, but swaps adjacents
// bytes.
static void swapbytes(char * out, const char * in, size_t n)
{
  for (size_t i = 0; i < n; i += 2) {
    out[i]   = in[i+1];
    out[i+1] = in[i];
  }
}

// Copies in to out, but removes leading and trailing whitespace.
static void trim(char * out, const char * in)
{
  // Find the first non-space character (maybe none).
  int first = -1;
  int i;
  for (i = 0; in[i]; i++)
    if (!isspace((int)in[i])) {
      first = i;
      break;
    }

  if (first == -1) {
    // There are no non-space characters.
    out[0] = '\0';
    return;
  }

  // Find the last non-space character.
  for (i = strlen(in)-1; i >= first && isspace((int)in[i]); i--)
    ;
  int last = i;

  strncpy(out, in+first, last-first+1);
  out[last-first+1] = '\0';
}

// Convenience function for formatting strings from ata_identify_device
747
void format_ata_string(char * out, const char * in, int n, bool fix_swap)
748
{
749
  bool must_swap = !fix_swap;
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
#ifdef __NetBSD__
  /* NetBSD kernel delivers IDENTIFY data in host byte order (but all else is LE) */
  if (isbigendian())
    must_swap = !must_swap;
#endif

  char tmp[65];
  n = n > 64 ? 64 : n;
  if (!must_swap)
    strncpy(tmp, in, n);
  else
    swapbytes(tmp, in, n);
  tmp[n] = '\0';
  trim(out, tmp);
}

766
767
768
769
770
771
// returns -1 if command fails or the device is in Sleep mode, else
// value of Sector Count register.  Sector Count result values:
//   00h device is in Standby mode. 
//   80h device is in Idle mode.
//   FFh device is in Active mode or Idle mode.

772
int ataCheckPowerMode(ata_device * device) {
773
774
  unsigned char result;

775
  if ((smartcommandhandler(device, CHECK_POWER_MODE, 0, (char *)&result)))
776
777
778
779
780
781
782
783
784
785
786
    return -1;

  if (result!=0 && result!=0x80 && result!=0xff)
    pout("ataCheckPowerMode(): ATA CHECK POWER MODE returned unknown Sector Count Register value %02x\n", result);

  return (int)result;
}




787
788
// Reads current Device Identity info (512 bytes) into buf.  Returns 0
// if all OK.  Returns -1 if no ATA Device identity can be
789
790
791
792
// established.  Returns >0 if Device is ATA Packet Device (not SMART
// capable).  The value of the integer helps identify the type of
// Packet device, which is useful so that the user can connect the
// formal device number with whatever object is inside their computer.
793
int ataReadHDIdentity (ata_device * device, struct ata_identify_device *buf){
794
795
  unsigned short *rawshort=(unsigned short *)buf;
  unsigned char  *rawbyte =(unsigned char  *)buf;
796

797
798
799
  // See if device responds either to IDENTIFY DEVICE or IDENTIFY
  // PACKET DEVICE
  if ((smartcommandhandler(device, IDENTIFY, 0, (char *)buf))){
800
    if (smartcommandhandler(device, PIDENTIFY, 0, (char *)buf)){
801
802
      return -1; 
    }
803
  }
804

805
#ifndef __NetBSD__
806
  // if machine is big-endian, swap byte order as needed
807
  // NetBSD kernel delivers IDENTIFY data in host byte order
808
809
810
811
  if (isbigendian()){
    int i;
    
    // swap various capability words that are needed
812
813
814
    for (i=0; i<33; i++)
      swap2((char *)(buf->words047_079+i));
    
815
    for (i=80; i<=87; i++)
816
      swap2((char *)(rawshort+i));
817
818
819
    
    for (i=0; i<168; i++)
      swap2((char *)(buf->words088_255+i));
820
  }
821
#endif
822
  
823
  // If there is a checksum there, validate it
824
  if ((rawshort[255] & 0x00ff) == 0x00a5 && checksum(rawbyte))
825
    checksumwarning("Drive Identity Structure");
826
  
827
828
829
830
  // If this is a PACKET DEVICE, return device type
  if (rawbyte[1] & 0x80)
    return 1+(rawbyte[1] & 0x1f);
  
831
  // Not a PACKET DEVICE
832
  return 0;
833
}
ballen4705's avatar
ballen4705 committed
834

835
836
837
838
// Returns ATA version as an integer, and a pointer to a string
// describing which revision.  Note that Revision 0 of ATA-3 does NOT
// support SMART.  For this one case we return -3 rather than +3 as
// the version number.  See notes above.
839
840
int ataVersionInfo(const char ** description, const ata_identify_device * drive, unsigned short * minor)
{
841
842
843
844
  // check that arrays at the top of this file are defined
  // consistently
  if (sizeof(minor_str) != sizeof(char *)*(1+MINOR_MAX)){
    pout("Internal error in ataVersionInfo().  minor_str[] size %d\n"
845
846
         "is not consistent with value of MINOR_MAX+1 = %d\n", 
         (int)(sizeof(minor_str)/sizeof(char *)), MINOR_MAX+1);
847
848
849
850
851
    fflush(NULL);
    abort();
  }
  if (sizeof(actual_ver) != sizeof(int)*(1+MINOR_MAX)){
    pout("Internal error in ataVersionInfo().  actual_ver[] size %d\n"
852
853
         "is not consistent with value of MINOR_MAX = %d\n",
         (int)(sizeof(actual_ver)/sizeof(int)), MINOR_MAX+1);
854
855
856
857
    fflush(NULL);
    abort();
  }

858
  // get major and minor ATA revision numbers
859
  unsigned short major = drive->major_rev_num;
ballen4705's avatar
ballen4705 committed
860
  *minor=drive->minor_rev_num;
861
862
863
864
  
  // First check if device has ANY ATA version information in it
  if (major==NOVAL_0 || major==NOVAL_1) {
    *description=NULL;
865
    return 0; // No info found
866
867
868
  }
  
  // The minor revision number has more information - try there first
869
870
  if (*minor && (*minor<=MINOR_MAX)){
    int std = actual_ver[*minor];
871
    if (std) {
872
      *description=minor_str[*minor];
873
874
875
      return std;
    }
  }
876

877
  // Try new ATA-8 minor revision numbers (Table 31 of T13/1699-D Revision 6)
878
879
880
881
  // (not in actual_ver/minor_str to avoid large sparse tables)
  const char *desc;
  switch (*minor) {
    case 0x0027: desc = "ATA-8-ACS revision 3c"; break;
882
    case 0x0028: desc = "ATA-8-ACS revision 6"; break;
883
    case 0x0029: desc = "ATA-8-ACS revision 4"; break;
884
    case 0x0033: desc = "ATA-8-ACS revision 3e"; break;
885
    case 0x0039: desc = "ATA-8-ACS revision 4c"; break;
886
887
888
889
890
891
892
893
894
895
    case 0x0042: desc = "ATA-8-ACS revision 3f"; break;
    case 0x0052: desc = "ATA-8-ACS revision 3b"; break;
    case 0x0107: desc = "ATA-8-ACS revision 2d"; break;
    default:     desc = 0; break;
  }
  if (desc) {
    *description = desc;
    return 8;
  }

896
897
898
  // HDPARM has a very complicated algorithm from here on. Since SMART only
  // exists on ATA-3 and later standards, let's punt on this.  If you don't
  // like it, please fix it.  The code's in CVS.
899
  int i;
900
  for (i=15; i>0; i--)
901
    if (major & (0x1<<i))
902
903
904
905
906
907
      break;
  
  *description=NULL; 
  if (i==0)
    return 1;
  else
908
    return i;
ballen4705's avatar
ballen4705 committed
909
910
}

911
// returns 1 if SMART supported, 0 if SMART unsupported, -1 if can't tell
912
913
int ataSmartSupport(const ata_identify_device * drive)
{
914
915
  unsigned short word82=drive->command_set_1;
  unsigned short word83=drive->command_set_2;
916
917
918
919
920
921
922
923
  
  // check if words 82/83 contain valid info
  if ((word83>>14) == 0x01)
    // return value of SMART support bit 
    return word82 & 0x0001;
  
  // since we can're rely on word 82, we don't know if SMART supported
  return -1;
ballen4705's avatar
ballen4705 committed
924
925
}

926
// returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell
927
928
int ataIsSmartEnabled(const ata_identify_device * drive)
{
929
930
  unsigned short word85=drive->cfs_enable_1;
  unsigned short word87=drive->csf_default;
931
  
932
933
934
  // check if words 85/86/87 contain valid info
  if ((word87>>14) == 0x01)
    // return value of SMART enabled bit
935
936
937
938
939
940
941
942
    return word85 & 0x0001;
  
  // Since we can't rely word85, we don't know if SMART is enabled.
  return -1;
}


// Reads SMART attributes into *data
943
int ataReadSmartValues(ata_device * device, struct ata_smart_values *data){
ballen4705's avatar
ballen4705 committed
944
  
945
  if (smartcommandhandler(device, READ_VALUES, 0, (char *)data)){
ballen4705's avatar
ballen4705 committed
946
    syserror("Error SMART Values Read failed");
ballen4705's avatar
ballen4705 committed
947
948
    return -1;
  }
949

ballen4705's avatar
ballen4705 committed
950
  // compute checksum
951
  if (checksum(data))
ballen4705's avatar
ballen4705 committed
952
    checksumwarning("SMART Attribute Data Structure");
ballen4705's avatar
ballen4705 committed
953
  
954
  // swap endian order if needed
955
956
957
958
959
960
961
  if (isbigendian()){
    int i;
    swap2((char *)&(data->revnumber));
    swap2((char *)&(data->total_time_to_complete_off_line));
    swap2((char *)&(data->smart_capability));
    for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){
      struct ata_smart_attribute *x=data->vendor_attributes+i;
962
      swap2((char *)&(x->flags));
963
964
    }
  }
ballen4705's avatar
ballen4705 committed
965

966
  return 0;
ballen4705's avatar
ballen4705 committed
967
968
969
}


970
971
// This corrects some quantities that are byte reversed in the SMART
// SELF TEST LOG
972
973
static void fixsamsungselftestlog(ata_smart_selftestlog * data)
{
ballen4705's avatar
ballen4705 committed
974
975
  // bytes 508/509 (numbered from 0) swapped (swap of self-test index
  // with one byte of reserved.
976
977
  swap2((char *)&(data->mostrecenttest));

ballen4705's avatar
ballen4705 committed
978
979
980
981
  // LBA low register (here called 'selftestnumber", containing
  // information about the TYPE of the self-test) is byte swapped with
  // Self-test execution status byte.  These are bytes N, N+1 in the
  // entries.
982
  for (int i = 0; i < 21; i++)
983
984
985
986
    swap2((char *)&(data->selftest_struct[i].selftestnumber));

  return;
}
ballen4705's avatar
ballen4705 committed
987

988
// Reads the Self Test Log (log #6)
989
990
991
int ataReadSelfTestLog (ata_device * device, ata_smart_selftestlog * data,
                        unsigned char fix_firmwarebug)
{
ballen4705's avatar
ballen4705 committed
992

993
  // get data from device
994
  if (smartcommandhandler(device, READ_LOG, 0x06, (char *)data)){
ballen4705's avatar
ballen4705 committed
995
    syserror("Error SMART Error Self-Test Log Read failed");
996
997
    return -1;
  }
998

999
  // compute its checksum, and issue a warning if needed
1000
  if (checksum(data))