[BACK]Return to atactl.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sbin / atactl

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sbin/atactl/atactl.c between version 1.66.8.3 and 1.67

version 1.66.8.3, 2014/08/20 00:02:24 version 1.67, 2012/10/19 17:09:07
Line 44  __RCSID("$NetBSD$");
Line 44  __RCSID("$NetBSD$");
 #include <err.h>  #include <err.h>
 #include <errno.h>  #include <errno.h>
 #include <fcntl.h>  #include <fcntl.h>
 #include <pwd.h>  
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
Line 145  static const struct command device_comma
Line 144  static const struct command device_comma
         { "smart",          { "smart",
                 "enable|disable|status|offline #|error-log|selftest-log",                  "enable|disable|status|offline #|error-log|selftest-log",
                                                 device_smart },                                                  device_smart },
         { "security",          { "security",   "freeze|status",        device_security },
                 "status|freeze|[setpass|unlock|disable|erase] [user|master]",  
                                                 device_security },  
         { NULL,         NULL,                   NULL },          { NULL,         NULL,                   NULL },
 };  };
   
Line 191  static const struct bitinfo ata_cmd_set1
Line 188  static const struct bitinfo ata_cmd_set1
         { WDC_CMD1_HPA, "Host Protected Area feature set" },          { WDC_CMD1_HPA, "Host Protected Area feature set" },
         { WDC_CMD1_DVRST, "DEVICE RESET command" },          { WDC_CMD1_DVRST, "DEVICE RESET command" },
         { WDC_CMD1_SRV, "SERVICE interrupt" },          { WDC_CMD1_SRV, "SERVICE interrupt" },
         { WDC_CMD1_RLSE, "Release interrupt" },          { WDC_CMD1_RLSE, "release interrupt" },
         { WDC_CMD1_AHEAD, "Look-ahead" },          { WDC_CMD1_AHEAD, "look-ahead" },
         { WDC_CMD1_CACHE, "Write cache" },          { WDC_CMD1_CACHE, "write cache" },
         { WDC_CMD1_PKT, "PACKET command feature set" },          { WDC_CMD1_PKT, "PACKET command feature set" },
         { WDC_CMD1_PM, "Power Management feature set" },          { WDC_CMD1_PM, "Power Management feature set" },
         { WDC_CMD1_REMOV, "Removable Media feature set" },          { WDC_CMD1_REMOV, "Removable Media feature set" },
Line 239  static const struct bitinfo ata_cmd_ext[
Line 236  static const struct bitinfo ata_cmd_ext[
 static const struct bitinfo ata_sata_caps[] = {  static const struct bitinfo ata_sata_caps[] = {
         { SATA_SIGNAL_GEN1, "1.5Gb/s signaling" },          { SATA_SIGNAL_GEN1, "1.5Gb/s signaling" },
         { SATA_SIGNAL_GEN2, "3.0Gb/s signaling" },          { SATA_SIGNAL_GEN2, "3.0Gb/s signaling" },
         { SATA_SIGNAL_GEN3, "6.0Gb/s signaling" },  
         { SATA_NATIVE_CMDQ, "Native Command Queuing" },          { SATA_NATIVE_CMDQ, "Native Command Queuing" },
         { SATA_HOST_PWR_MGMT, "Host-Initiated Interface Power Management" },          { SATA_HOST_PWR_MGMT, "Host-Initiated Interface Power Management" },
         { SATA_PHY_EVNT_CNT, "PHY Event Counters" },          { SATA_PHY_EVNT_CNT, "PHY Event Counters" },
Line 273  static const struct {
Line 269  static const struct {
         {  11,          "Calibration retry count", NULL },          {  11,          "Calibration retry count", NULL },
         {  12,          "Device power cycle count", NULL },          {  12,          "Device power cycle count", NULL },
         {  13,          "Soft read error rate", NULL },          {  13,          "Soft read error rate", NULL },
         { 184,          "End-to-end error", NULL },  
         { 187,          "Reported uncorrect", NULL },          { 187,          "Reported uncorrect", NULL },
         { 189,          "High Fly Writes", NULL },          { 189,          "High Fly Writes", NULL },
         { 190,          "Airflow Temperature",          device_smart_temp },          { 190,          "Airflow Temperature",          device_smart_temp },
Line 307  static const struct {
Line 302  static const struct {
         { 228,          "Power-off retract count", NULL },          { 228,          "Power-off retract count", NULL },
         { 230,          "GMR head amplitude", NULL },          { 230,          "GMR head amplitude", NULL },
         { 231,          "Temperature",                  device_smart_temp },          { 231,          "Temperature",                  device_smart_temp },
         { 232,          "Available reserved space", NULL },  
         { 233,          "Media wearout indicator", NULL },  
         { 240,          "Head flying hours", NULL },          { 240,          "Head flying hours", NULL },
         { 250,          "Read error retry rate", NULL },          { 250,          "Read error retry rate", NULL },
         {   0,          "Unknown", NULL },          {   0,          "Unknown", NULL },
Line 521  print_smart_status(void *vbuf, void *tbu
Line 514  print_smart_status(void *vbuf, void *tbu
         }          }
   
         printf("id value thresh crit collect reliability description"          printf("id value thresh crit collect reliability description"
             "                 raw\n");              "\t\t\traw\n");
         for (i = 0; i < 256; i++) {          for (i = 0; i < 256; i++) {
                 int thresh = 0;                  int thresh = 0;
   
Line 549  print_smart_status(void *vbuf, void *tbu
Line 542  print_smart_status(void *vbuf, void *tbu
   
                 flags = le16toh(attr->flags);                  flags = le16toh(attr->flags);
   
                 printf("%3d %3d  %3d     %-3s %-7s %stive    %-27s ",                  printf("%3d %3d  %3d     %-3s %-7s %stive    %-24s\t",
                     i, attr->value, thresh,                      i, attr->value, thresh,
                     flags & WDSM_ATTR_ADVISORY ? "yes" : "no",                      flags & WDSM_ATTR_ADVISORY ? "yes" : "no",
                     flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline",                      flags & WDSM_ATTR_COLLECTIVE ? "online" : "offline",
Line 577  static const struct {
Line 570  static const struct {
         { 127, "Abort off-line test" },          { 127, "Abort off-line test" },
         { 129, "Short captive" },          { 129, "Short captive" },
         { 130, "Extended captive" },          { 130, "Extended captive" },
         { 256, "Unknown test" }, /* larger than uint8_t */          { 256, "Unknown test" }, /* larger then uint8_t */
         { 0, NULL }          { 0, NULL }
 };  };
   
Line 858  extract_string(char *buf, size_t bufmax,
Line 851  extract_string(char *buf, size_t bufmax,
         buf[j] = '\0';          buf[j] = '\0';
 }  }
   
 static void  
 compute_capacity(const struct ataparams *inqbuf, uint64_t *capacityp,  
     uint64_t *sectorsp, uint32_t *secsizep)  
 {  
         uint64_t capacity;  
         uint64_t sectors;  
         uint32_t secsize;  
   
         if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff &&  
             inqbuf->atap_cmd2_en & ATA_CMD2_LBA48) {  
                 sectors =  
                     ((uint64_t)inqbuf->atap_max_lba[3] << 48) |  
                     ((uint64_t)inqbuf->atap_max_lba[2] << 32) |  
                     ((uint64_t)inqbuf->atap_max_lba[1] << 16) |  
                     ((uint64_t)inqbuf->atap_max_lba[0] <<  0);  
         } else if (inqbuf->atap_capabilities1 & WDC_CAP_LBA) {  
                 sectors = (inqbuf->atap_capacity[1] << 16) |  
                     inqbuf->atap_capacity[0];  
         } else {  
                 sectors = inqbuf->atap_cylinders *  
                     inqbuf->atap_heads * inqbuf->atap_sectors;  
         }  
   
         secsize = 512;  
   
         if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {  
                 if (inqbuf->atap_secsz & ATA_SECSZ_LLS) {  
                         secsize = 2 *           /* words to bytes */  
                             (inqbuf->atap_lls_secsz[1] << 16 |  
                             inqbuf->atap_lls_secsz[0] <<  0);  
                 }  
         }  
   
         capacity = sectors * secsize;  
   
         if (capacityp)  
                 *capacityp = capacity;  
         if (sectorsp)  
                 *sectorsp = sectors;  
         if (secsizep)  
                 *secsizep = secsize;  
 }  
   
 /*  /*
  * DEVICE COMMANDS   * DEVICE COMMANDS
  */   */
Line 947  device_identify(int argc, char *argv[])
Line 897  device_identify(int argc, char *argv[])
          * Mitsumi ATAPI devices           * Mitsumi ATAPI devices
          */           */
   
         if (!(inqbuf->atap_config != WDC_CFG_CFA_MAGIC &&          if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI &&
               (inqbuf->atap_config & WDC_CFG_ATAPI) &&  
               ((inqbuf->atap_model[0] == 'N' &&                ((inqbuf->atap_model[0] == 'N' &&
                   inqbuf->atap_model[1] == 'E') ||                    inqbuf->atap_model[1] == 'E') ||
                (inqbuf->atap_model[0] == 'F' &&                 (inqbuf->atap_model[0] == 'F' &&
Line 981  device_identify(int argc, char *argv[])
Line 930  device_identify(int argc, char *argv[])
                     ((uint64_t)inqbuf->atap_wwn[2] << 16) |                      ((uint64_t)inqbuf->atap_wwn[2] << 16) |
                     ((uint64_t)inqbuf->atap_wwn[3] <<  0));                      ((uint64_t)inqbuf->atap_wwn[3] <<  0));
   
         printf("Device type: %s",          printf("Device type: %s, %s\n", inqbuf->atap_config & WDC_CFG_ATAPI ?
                 inqbuf->atap_config == WDC_CFG_CFA_MAGIC ? "CF-ATA" :                 "ATAPI" : "ATA", inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" :
                  (inqbuf->atap_config & WDC_CFG_ATAPI ? "ATAPI" : "ATA"));                 "removable");
         if (inqbuf->atap_config != WDC_CFG_CFA_MAGIC)  
                 printf(", %s",          if (inqbuf->atap_cmd2_en != 0 && inqbuf->atap_cmd2_en != 0xffff &&
                  inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : "removable");              inqbuf->atap_cmd2_en & ATA_CMD2_LBA48) {
         printf("\n");                  sectors =
                       ((uint64_t)inqbuf->atap_max_lba[3] << 48) |
                       ((uint64_t)inqbuf->atap_max_lba[2] << 32) |
                       ((uint64_t)inqbuf->atap_max_lba[1] << 16) |
                       ((uint64_t)inqbuf->atap_max_lba[0] <<  0);
           } else if (inqbuf->atap_capabilities1 & WDC_CAP_LBA) {
                   sectors = (inqbuf->atap_capacity[1] << 16) |
                       inqbuf->atap_capacity[0];
           } else {
                   sectors = inqbuf->atap_cylinders *
                       inqbuf->atap_heads * inqbuf->atap_sectors;
           }
   
           secsize = 512;
   
         compute_capacity(inqbuf, &capacity, &sectors, &secsize);          if ((inqbuf->atap_secsz & ATA_SECSZ_VALID_MASK) == ATA_SECSZ_VALID) {
                   if (inqbuf->atap_secsz & ATA_SECSZ_LLS) {
                           secsize = 2 *           /* words to bytes */
                               (inqbuf->atap_lls_secsz[1] << 16 |
                               inqbuf->atap_lls_secsz[0] <<  0);
                   }
           }
   
           capacity = sectors * secsize;
   
         humanize_number(hnum, sizeof(hnum), capacity, "bytes",          humanize_number(hnum, sizeof(hnum), capacity, "bytes",
                 HN_AUTOSCALE, HN_DIVISOR_1000);                  HN_AUTOSCALE, HN_DIVISOR_1000);
Line 1072  device_identify(int argc, char *argv[])
Line 1042  device_identify(int argc, char *argv[])
                             inqbuf->atap_sata_features_supp, ata_sata_feat);                              inqbuf->atap_sata_features_supp, ata_sata_feat);
         }          }
   
         if ((inqbuf->atap_ata_major & WDC_VER_ATA7) &&          if ((inqbuf->atap_ata_major & WDC_VER_ATA8) &&
             (inqbuf->support_dsm & ATA_SUPPORT_DSM_TRIM))              (inqbuf->support_dsm & ATA_SUPPORT_DSM_TRIM))
                 printf("TRIM supported\n");                  printf("TRIM supported\n");
   
Line 1398  device_security(int argc, char *argv[])
Line 1368  device_security(int argc, char *argv[])
 {  {
         struct atareq req;          struct atareq req;
         const struct ataparams *inqbuf;          const struct ataparams *inqbuf;
         unsigned char data[DEV_BSIZE];  
         char *pass;  
   
         /* need subcommand */          /* need subcommand */
         if (argc < 1)          if (argc < 1)
                 usage();                  usage();
   
         memset(&req, 0, sizeof(req));          if (strcmp(argv[0], "freeze") == 0) {
         if (strcmp(argv[0], "status") == 0) {                  memset(&req, 0, sizeof(req));
                 inqbuf = getataparams();  
                 print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);  
         } else if (strcmp(argv[0], "freeze") == 0) {  
                 req.command = WDCC_SECURITY_FREEZE;                  req.command = WDCC_SECURITY_FREEZE;
                 req.timeout = 1000;                  req.timeout = 1000;
                 ata_command(&req);                  ata_command(&req);
         } else if ((strcmp(argv[0], "setpass") == 0) ||          } else if (strcmp(argv[0], "status") == 0) {
             (strcmp(argv[0], "unlock") == 0) ||                  inqbuf = getataparams();
             (strcmp(argv[0], "disable") == 0) ||                  print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);
             (strcmp(argv[0], "erase") == 0)) {          } else
                 if (argc != 2)  
                         usage();  
                 if (strcmp(argv[1], "user") != 0) {  
                         if (strcmp(argv[1], "master") == 0) {  
                                 fprintf(stderr,  
                                     "Master passwords not supported\n");  
                                 exit(1);  
                         } else {  
                                 usage();  
                         }  
                 }  
   
                 pass = getpass("Password:");  
                 if (strlen(pass) > 32) {  
                         fprintf(stderr, "Password must be <=32 characters\n");  
                         exit(1);  
                 }  
   
                 req.flags |= ATACMD_WRITE;  
                 req.timeout = 1000;  
                 req.databuf = data;  
                 req.datalen = sizeof(data);  
                 memset(data, 0, sizeof(data));  
                 strlcpy((void *)&data[2], pass, 32 + 1);  
   
                 if (strcmp(argv[0], "setpass") == 0) {  
                         char orig[32 + 1];  
                         strlcpy(orig, pass, 32 + 1);  
                         pass = getpass("Confirm password:");  
                         if (0 != strcmp(orig, pass)) {  
                                 fprintf(stderr, "Passwords do not match\n");  
                                 exit(1);  
                         }  
                         req.command = WDCC_SECURITY_SET_PASSWORD;  
                 } else if (strcmp(argv[0], "unlock") == 0) {  
                         req.command = WDCC_SECURITY_UNLOCK;  
                 } else if (strcmp(argv[0], "disable") == 0) {  
                         req.command = WDCC_SECURITY_DISABLE_PASSWORD;  
                 } else if (strcmp(argv[0], "erase") == 0) {  
                         struct atareq prepare;  
   
                         inqbuf = getataparams();  
   
                         /*  
                          * XXX Any way to lock the device to make sure  
                          * this really is the command preceding the  
                          * SECURITY ERASE UNIT command?  This would  
                          * probably have to be moved into the kernel to  
                          * do that.  
                          */  
                         memset(&prepare, 0, sizeof(prepare));  
                         prepare.command = WDCC_SECURITY_ERASE_PREPARE;  
                         prepare.timeout = 1000;  
                         ata_command(&prepare);  
   
                         req.command = WDCC_SECURITY_ERASE_UNIT;  
   
                         /*  
                          * Enable enhanced erase if it's supported.  
                          *  
                          * XXX should be a command-line option  
                          */  
                         if (inqbuf->atap_sec_st & WDC_SEC_ESE_SUPP) {  
                                 data[0] |= 0x2;  
                                 req.timeout = (inqbuf->atap_eseu_time & 0xff)  
                                     * 2 * 60 * 1000;  
                         } else {  
                                 req.timeout = (inqbuf->atap_seu_time & 0xff)  
                                     * 2 * 60 * 1000;  
                         }  
   
                         /*  
                          * If the estimated time was 0xff (* 2 * 60 *  
                          * 1000 = 30600000), that means `>508 minutes'.  
                          * Estimate that we can handle 16 MB/sec, a  
                          * rate I just pulled out of my arse.  
                          */  
                         if (req.timeout == 30600000) {  
                                 uint64_t bytes, timeout;  
                                 compute_capacity(inqbuf, &bytes, NULL, NULL);  
                                 timeout = (bytes / (16 * 1024 * 1024)) * 1000;  
                                 if (timeout > (uint64_t)INT_MAX)  
                                         req.timeout = INT_MAX;  
                                 else  
                                         req.timeout = timeout;  
                         }  
   
                         printf("Erasing may take up to %dh %dm %ds...\n",  
                             (req.timeout / 1000 / 60) / 60,  
                             (req.timeout / 1000 / 60) % 60,  
                             req.timeout % 60);  
                 } else {  
                         abort();  
                 }  
   
                 ata_command(&req);  
         } else {  
                 usage();                  usage();
         }  
           return;
 }  }
   
 /*  /*

Legend:
Removed from v.1.66.8.3  
changed lines
  Added in v.1.67

CVSweb <webmaster@jp.NetBSD.org>