"Fossies" - the Fresh Open Source Software Archive

Member "hdparm-9.65/hdparm.c" (6 Sep 2022, 103201 Bytes) of package /linux/misc/hdparm-9.65.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "hdparm.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 9.64_vs_9.65.

A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.


    1 /*
    2  * hdparm.c - Command line interface to get/set hard disk parameters.
    3  *          - by Mark Lord (C) 1994-2022 -- freely distributable.
    4  */
    5 #define HDPARM_VERSION "v9.65"
    6 
    7 #define _LARGEFILE64_SOURCE /*for lseek64*/
    8 #define _BSD_SOURCE /* for strtoll() */
    9 #include <unistd.h>
   10 #include <stdlib.h>
   11 #include <stdio.h>
   12 #define __USE_GNU   /* for O_DIRECT */
   13 #include <string.h>
   14 #include <fcntl.h>
   15 #include <errno.h>
   16 #include <ctype.h>
   17 #include <endian.h>
   18 #include <sys/ioctl.h>
   19 #include <sys/stat.h>
   20 #include <sys/sysmacros.h>
   21 #include <sys/time.h>
   22 #include <sys/times.h>
   23 #include <sys/types.h>
   24 #include <sys/mount.h>
   25 #include <sys/mman.h>
   26 #include <sys/user.h>
   27 #include <linux/types.h>
   28 #ifndef FSCONFIG_SET_FLAG
   29 #include <linux/fs.h>
   30 #endif
   31 #include <linux/major.h>
   32 #include <endian.h>
   33 #include <asm/byteorder.h>
   34 
   35 #include "hdparm.h"
   36 #include "sgio.h"
   37 
   38 static int    argc;
   39 static char **argv;
   40 static char  *argp;
   41 static int    num_flags_processed = 0;
   42 
   43 extern const char *minor_str[];
   44 
   45 #ifndef O_DIRECT
   46 #define O_DIRECT    040000  /* direct disk access, not easily obtained from headers */
   47 #endif
   48 
   49 #ifndef CDROM_SELECT_SPEED  /* already defined in 2.3.xx kernels and above */
   50 #define CDROM_SELECT_SPEED  0x5322
   51 #endif
   52 
   53 #define TIMING_BUF_MB       2
   54 #define TIMING_BUF_BYTES    (TIMING_BUF_MB * 1024 * 1024)
   55 
   56 char *progname;
   57 int verbose = 0;
   58 int prefer_ata12 = 0;
   59 static int do_defaults = 0, do_flush = 0, do_ctimings, do_timings = 0;
   60 static int do_identity = 0, get_geom = 0, noisy = 1, quiet = 0;
   61 static int do_flush_wcache = 0;
   62 
   63 static int set_wdidle3  = 0, get_wdidle3 = 0, wdidle3 = 0;
   64 static int   set_timings_offset = 0;
   65 static __u64 timings_offset = 0;
   66 static int set_fsreadahead= 0, get_fsreadahead= 0, fsreadahead= 0;
   67 static int set_readonly = 0, get_readonly = 0, readonly = 0;
   68 static int set_unmask   = 0, get_unmask   = 0, unmask   = 0;
   69 static int set_mult     = 0, get_mult     = 0, mult     = 0;
   70 static int set_dma      = 0, get_dma      = 0, dma      = 0;
   71 static int set_dma_q      = 0, get_dma_q    = 0, dma_q    = 0;
   72 static int set_nowerr   = 0, get_nowerr   = 0, nowerr   = 0;
   73 static int set_keep     = 0, get_keep     = 0, keep     = 0;
   74 static int set_io32bit  = 0, get_io32bit  = 0, io32bit  = 0;
   75 static int set_piomode  = 0, get_piomode= 0, piomode = 0;
   76 static int set_dkeep    = 0, get_dkeep    = 0, dkeep    = 0;
   77 static int set_standby  = 0, get_standby  = 0, standby= 0;
   78 static int set_xfermode = 0, get_xfermode = 0;
   79 static int xfermode_requested= 0;
   80 static int set_lookahead= 0, get_lookahead= 0, lookahead= 0;
   81 static int set_prefetch = 0, get_prefetch = 0, prefetch = 0;
   82 static int set_defects  = 0, get_defects  = 0, defects  = 0;
   83 static int set_wcache   = 0, get_wcache   = 0, wcache   = 0;
   84 static int set_doorlock = 0, get_doorlock = 0, doorlock = 0;
   85 static int set_seagate  = 0, get_seagate  = 0;
   86 static int get_idleimmediate = 0, set_idleimmediate = 0;
   87 static int get_idleunload = 0, set_idleunload = 0;
   88 static int set_standbynow = 0, get_standbynow = 0;
   89 static int set_sleepnow   = 0, get_sleepnow   = 0;
   90 static int set_powerup_in_standby = 0, get_powerup_in_standby = 0, powerup_in_standby = 0;
   91 static int get_hitachi_temp = 0, set_hitachi_temp = 0;
   92 static int security_prompt_for_password = 0;
   93 static int security_freeze   = 0;
   94 static int security_master = 0, security_mode = 0;
   95 static int enhanced_erase = 0;
   96 static int set_security   = 0;
   97 static int do_dco_freeze = 0, do_dco_restore = 0, do_dco_identify = 0, do_dco_setmax = 0;
   98 static unsigned int security_command = ATA_OP_SECURITY_UNLOCK;
   99 
  100 static char security_password[33], *fwpath, *raw_identify_path;
  101 
  102 static int do_sanitize = 0;
  103 static __u16 sanitize_feature = 0;
  104 static __u64 sanitize_overwrite_passes = 0;
  105 static __u32 ow_pattern = 0;
  106 static const char *sanitize_states_str[SANITIZE_STATE_NUMBER] = {
  107     "SD0 Sanitize Idle",
  108     "SD1 Sanitize Frozen",
  109     "SD2 Sanitize operation In Process",
  110     "SD3 Sanitize Operation Failed",
  111     "SD4 Sanitize Operation succeeded"
  112 };
  113 static const char *sanitize_err_reason_str[SANITIZE_ERR_NUMBER] = {
  114     "Reason not reported",
  115     "Last Sanitize Command completed unsuccessfully",
  116     "Unsupported command",
  117     "Device in FROZEN state",
  118     "Antifreeze lock enabled"
  119 };
  120 
  121 static int get_powermode  = 0, set_powermode = 0;
  122 static int set_apmmode = 0, get_apmmode= 0, apmmode = 0;
  123 static int get_cdromspeed = 0, set_cdromspeed = 0, cdromspeed = 0;
  124 static int do_IDentity = 0, drq_hsm_error = 0;
  125 static int do_fwdownload = 0, xfer_mode = 0;
  126 static int  set_busstate = 0, get_busstate = 0, busstate = 0;
  127 static int  set_reread_partn = 0, get_reread_partn;
  128 static int  set_acoustic = 0, get_acoustic = 0, acoustic = 0;
  129 static int write_read_verify = 0, get_write_read_verify = 0, set_write_read_verify = 0;
  130 
  131 static int   make_bad_sector = 0, make_bad_sector_flagged;
  132 static __u64 make_bad_sector_addr = ~0ULL;
  133 
  134 #ifdef FORMAT_AND_ERASE
  135 static int   format_track = 0;
  136 static __u64 format_track_addr = ~0ULL;
  137 
  138 static int   erase_sectors = 0;
  139 static __u64 erase_sectors_addr = ~0ULL;
  140 #endif
  141 
  142 static struct sector_range_s *trim_sector_ranges = NULL;
  143 static int   trim_sector_ranges_count = 0;
  144 static int   trim_from_stdin = 0;
  145 static int   do_set_sector_size = 0;
  146 static __u64 new_sector_size = 0;
  147 #define SET_SECTOR_SIZE "set-sector-size"
  148 
  149 static int   write_sector = 0;
  150 static __u64 write_sector_addr = ~0ULL;
  151 
  152 static int   read_sector = 0;
  153 static __u64 read_sector_addr = ~0ULL;
  154 
  155 static int   set_max_sectors = 0, set_max_permanent, get_native_max_sectors = 0;
  156 static __u64 set_max_addr = 0;
  157 
  158 static int  get_doreset = 0, set_doreset = 0;
  159 static int  i_know_what_i_am_doing = 0;
  160 static int  please_destroy_my_drive = 0;
  161 
  162 const int timeout_15secs = 15;
  163 const int timeout_60secs = 60;
  164 const int timeout_5mins  = (5 * 60);
  165 const int timeout_2hrs   = (2 * 60 * 60);
  166 
  167 static int open_flags = O_RDONLY|O_NONBLOCK;
  168 
  169 // Historically, if there was no HDIO_OBSOLETE_IDENTITY, then
  170 // then the HDIO_GET_IDENTITY only returned 142 bytes.
  171 // Otherwise, HDIO_OBSOLETE_IDENTITY returns 142 bytes,
  172 // and HDIO_GET_IDENTITY returns 512 bytes.  But the latest
  173 // 2.5.xx kernels no longer define HDIO_OBSOLETE_IDENTITY
  174 // (which they should, but they should just return -EINVAL).
  175 //
  176 // So.. we must now assume that HDIO_GET_IDENTITY returns 512 bytes.
  177 // On a really old system, it will not, and we will be confused.
  178 // Too bad, really.
  179 
  180 const char *cfg_str[] =
  181 {   "",         " HardSect",   " SoftSect",  " NotMFM",
  182     " HdSw>15uSec", " SpinMotCtl", " Fixed",     " Removable",
  183     " DTR<=5Mbs",   " DTR>5Mbs",   " DTR>10Mbs", " RotSpdTol>.5%",
  184     " dStbOff",     " TrkOff",     " FmtGapReq", " nonMagnetic"
  185 };
  186 
  187 const char *SlowMedFast[]   = {"slow", "medium", "fast", "eide", "ata"};
  188 const char *BuffType[4]     = {"unknown", "1Sect", "DualPort", "DualPortCache"};
  189 
  190 #define YN(b)   (((b)==0)?"no":"yes")
  191 
  192 static void on_off (unsigned int value)
  193 {
  194     printf(value ? " (on)\n" : " (off)\n");
  195 }
  196 
  197 #ifndef ENOIOCTLCMD
  198 #define ENOIOCTLCMD ENOTTY
  199 #endif
  200 
  201 #define DCO_CHECKSUM_WORDS  154
  202 // the DCO spec says that the checksum is the 2's compelement of the sum of all bytes in words 0-154 + byte 511. 
  203 static __u8 dco_verify_checksum(__u16 *dcobuffer)
  204 {
  205     __u8 csum = 0;
  206     int i;
  207 
  208     for(i = 0; i < DCO_CHECKSUM_WORDS; i++) {
  209         csum += (dcobuffer[i] & 0xFF);
  210         csum += (dcobuffer[i] >> 8);
  211     }
  212     // The INTEL drives have a byte OUTSIDE of the valid checksum area,
  213     //  and they erroneously include it in the checksum! WARNING: KLUDGE!
  214     if (dcobuffer[208] != 0) {
  215         csum += (dcobuffer[208] & 0xFF);
  216         csum += (dcobuffer[208] >> 8);
  217     }
  218     // get the signature byte
  219     csum += (dcobuffer[255] & 0xFF);
  220     return (0-csum);
  221 }
  222 
  223 static void flush_buffer_cache (int fd)
  224 {
  225     sync();
  226     fsync(fd);              /* flush buffers */
  227     fdatasync(fd);              /* flush buffers */
  228     sync();
  229     if (ioctl(fd, BLKFLSBUF, NULL))     /* do it again, big time */
  230         perror("BLKFLSBUF failed");
  231     else
  232         do_drive_cmd(fd, NULL, 0);  /* IDE: await completion */
  233     sync();
  234 }
  235 
  236 static int seek_to_zero (int fd)
  237 {
  238     if (lseek(fd, (off_t) 0, SEEK_SET)) {
  239         perror("lseek() failed");
  240         return 1;
  241     }
  242     return 0;
  243 }
  244 
  245 static int read_big_block (int fd, char *buf)
  246 {
  247     int i, rc;
  248     if ((rc = read(fd, buf, TIMING_BUF_BYTES)) != TIMING_BUF_BYTES) {
  249         if (rc) {
  250             if (rc == -1)
  251                 perror("read() failed");
  252             else
  253                 fprintf(stderr, "read(%u) returned %u bytes\n", TIMING_BUF_BYTES, rc);
  254         } else {
  255             fputs ("read() hit EOF - device too small\n", stderr);
  256         }
  257         return EIO;
  258     }
  259     /* access all sectors of buf to ensure the read fully completed */
  260     for (i = 0; i < TIMING_BUF_BYTES; i += 512)
  261         buf[i] &= 1;
  262     return 0;
  263 }
  264 
  265 static void *prepare_timing_buf (unsigned int len)
  266 {
  267     unsigned int i;
  268     __u8 *buf;
  269 
  270     buf = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
  271     if (buf == MAP_FAILED) {
  272         perror("could not allocate timing buf");
  273         return NULL;
  274     }
  275     for (i = 0; i < len; i += 4096)
  276         buf[i] = 0; /* guarantee memory is present/assigned */
  277     if (-1 == mlock(buf, len)) {
  278         perror("mlock() failed on timing buf");
  279         munmap(buf, len);
  280         return NULL;
  281     }
  282     mlockall(MCL_CURRENT|MCL_FUTURE); // don't care if this fails on low-memory machines
  283     sync();
  284 
  285     /* give time for I/O to settle */
  286     sleep(3);
  287     return buf;
  288 }
  289 
  290 static void time_cache (int fd)
  291 {
  292     char *buf;
  293     struct itimerval e1, e2;
  294     double elapsed, elapsed2;
  295     unsigned int iterations, total_MB;
  296 
  297     buf = prepare_timing_buf(TIMING_BUF_BYTES);
  298     if (!buf)
  299         return;
  300 
  301     /*
  302      * getitimer() is used rather than gettimeofday() because
  303      * it is much more consistent (on my machine, at least).
  304      */
  305     setitimer(ITIMER_REAL, &(struct itimerval){{1000,0},{1000,0}}, NULL);
  306     if (seek_to_zero (fd)) return;
  307     if (read_big_block (fd, buf)) return;
  308     printf(" Timing %scached reads:   ", (open_flags & O_DIRECT) ? "O_DIRECT " : "");
  309     fflush(stdout);
  310 
  311     /* Clear out the device request queues & give them time to complete */
  312     flush_buffer_cache(fd);
  313     sleep(1);
  314 
  315     /* Now do the timing */
  316     iterations = 0;
  317     getitimer(ITIMER_REAL, &e1);
  318     do {
  319         ++iterations;
  320         if (seek_to_zero (fd) || read_big_block (fd, buf))
  321             goto quit;
  322         getitimer(ITIMER_REAL, &e2);
  323         elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec)
  324          + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0);
  325     } while (elapsed < 2.0);
  326     total_MB = iterations * TIMING_BUF_MB;
  327 
  328     elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec)
  329      + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0);
  330 
  331     /* Now remove the lseek() and getitimer() overheads from the elapsed time */
  332     getitimer(ITIMER_REAL, &e1);
  333     do {
  334         if (seek_to_zero (fd))
  335             goto quit;
  336         getitimer(ITIMER_REAL, &e2);
  337         elapsed2 = (e1.it_value.tv_sec - e2.it_value.tv_sec)
  338          + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0);
  339     } while (--iterations);
  340 
  341     elapsed -= elapsed2;
  342 
  343     if (total_MB >= elapsed)  /* more than 1MB/s */
  344         printf("%3u MB in %5.2f seconds = %6.2f MB/sec\n",
  345             total_MB, elapsed,
  346             total_MB / elapsed);
  347     else
  348         printf("%3u MB in %5.2f seconds = %6.2f kB/sec\n",
  349             total_MB, elapsed,
  350             total_MB / elapsed * 1024);
  351 
  352     flush_buffer_cache(fd);
  353     sleep(1);
  354 quit:
  355     munlockall();
  356     munmap(buf, TIMING_BUF_BYTES);
  357 }
  358 
  359 static int time_device (int fd)
  360 {
  361     char *buf;
  362     double elapsed;
  363     struct itimerval e1, e2;
  364     int err = 0;
  365     unsigned int max_iterations = 1024, total_MB, iterations;
  366 
  367     /*
  368      * get device size
  369      */
  370     if (do_ctimings || do_timings) {
  371         __u64 nsectors;
  372         do_flush = 1;
  373         err = get_dev_geometry(fd, NULL, NULL, NULL, NULL, &nsectors);
  374         if (!err)
  375             max_iterations = nsectors / (2 * 1024) / TIMING_BUF_MB;
  376         err = 0;
  377     }
  378     buf = prepare_timing_buf(TIMING_BUF_BYTES);
  379     if (!buf)
  380         err = ENOMEM;
  381     if (err)
  382         goto quit;
  383 
  384     printf(" Timing %s disk reads", (open_flags & O_DIRECT) ? "O_DIRECT" : "buffered");
  385     if (set_timings_offset)
  386         printf(" (offset %llu GB)", timings_offset / 0x40000000ULL);
  387     printf(": ");
  388     fflush(stdout);
  389 
  390     if (set_timings_offset && lseek64(fd, timings_offset, SEEK_SET) == (off64_t)-1) {
  391         err = errno;
  392         perror("lseek() failed");
  393         goto quit;
  394     }
  395 
  396     /*
  397      * getitimer() is used rather than gettimeofday() because
  398      * it is much more consistent (on my machine, at least).
  399      */
  400     setitimer(ITIMER_REAL, &(struct itimerval){{1000,0},{1000,0}}, NULL);
  401 
  402     /* Now do the timings for real */
  403     iterations = 0;
  404     getitimer(ITIMER_REAL, &e1);
  405     do {
  406         ++iterations;
  407         if ((err = read_big_block(fd, buf)))
  408             goto quit;
  409         getitimer(ITIMER_REAL, &e2);
  410         elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec)
  411          + ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0);
  412     } while (elapsed < 3.0 && iterations < max_iterations);
  413 
  414     total_MB = iterations * TIMING_BUF_MB;
  415     if ((total_MB / elapsed) > 1.0)  /* more than 1MB/s */
  416         printf("%3u MB in %5.2f seconds = %6.2f MB/sec\n",
  417             total_MB, elapsed, total_MB / elapsed);
  418     else
  419         printf("%3u MB in %5.2f seconds = %6.2f kB/sec\n",
  420             total_MB, elapsed, total_MB / elapsed * 1024);
  421 quit:
  422     munlockall();
  423     if (buf)
  424         munmap(buf, TIMING_BUF_BYTES);
  425     return err;
  426 }
  427 
  428 static void dmpstr (const char *prefix, unsigned int i, const char *s[], unsigned int maxi)
  429 {
  430     if (i > maxi)
  431         printf("%s%u", prefix, i);
  432     else
  433         printf("%s%s", prefix, s[i]);
  434 }
  435 
  436 static __u16 *id;
  437 
  438 #define SUPPORTS_ACS3(id) ((id)[80] & 0x400)
  439 #define SUPPORTS_AMAX_ADDR(id) (SUPPORTS_ACS3(id) && ((id)[119] & (1u << 8)))
  440 #define SUPPORTS_48BIT_ADDR(id) ((((id)[83] & 0xc400) == 0x4400) && ((id)[86] & 0x0400))
  441 
  442 static void get_identify_data (int fd);
  443 
  444 static __u64 get_lba_capacity (__u16 *idw)
  445 {
  446     __u64 nsects = ((__u32)idw[58] << 16) | idw[57];
  447 
  448     if (idw[49] & 0x200) {
  449         nsects = ((__u32)idw[61] << 16) | idw[60];
  450         if ((idw[83] & 0xc000) == 0x4000 && (idw[86] & 0x0400)) {
  451             nsects = (__u64)idw[103] << 48 | (__u64)idw[102] << 32 |
  452                      (__u64)idw[101] << 16 | idw[100];
  453         }
  454     }
  455     return nsects;
  456 }
  457 
  458 static char *strip (char *s)
  459 {
  460     char *e;
  461 
  462     while (*s == ' ') ++s;
  463     if (*s)
  464         for (e = s + strlen(s); *--e == ' '; *e = '\0');
  465     return s;
  466 }
  467 
  468 static void dump_identity (__u16 *idw)
  469 {
  470     int i;
  471     char pmodes[64] = {0,}, dmodes[128]={0,}, umodes[128]={0,};
  472     char *model = strip(strndup((char *)&idw[27], 40));
  473     char *fwrev = strip(strndup((char *)&idw[23],  8));
  474     char *serno = strip(strndup((char *)&idw[10], 20));
  475     __u8 tPIO;
  476 
  477     printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s", model, fwrev, serno);
  478     printf("\n Config={");
  479     for (i = 0; i <= 15; i++) {
  480         if (idw[0] & (1<<i))
  481             printf("%s", cfg_str[i]);
  482     }
  483     printf(" }\n");
  484     printf(" RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n",
  485         idw[1], idw[3], idw[6], idw[4], idw[5], idw[22]);
  486     dmpstr(" BuffType=", idw[20], BuffType, 3);
  487     if (idw[21] && idw[21] != 0xffff)
  488         printf(", BuffSize=%ukB", idw[21] / 2);
  489     else
  490         printf(", BuffSize=unknown");
  491     printf(", MaxMultSect=%u", idw[47] & 0xff);
  492     if ((idw[47] & 0xff)) {
  493         printf(", MultSect=");
  494         if (!(idw[59] & 0x100))
  495             printf("?%u?", idw[59] & 0xff);
  496         else if (idw[59] & 0xff)
  497             printf("%u", idw[59] & 0xff);
  498         else
  499             printf("off");
  500     }
  501     putchar('\n');
  502     tPIO = idw[51] >> 8;
  503     if (tPIO <= 5) {
  504         strcat(pmodes, "pio0 ");
  505         if (tPIO >= 1) strcat(pmodes, "pio1 ");
  506         if (tPIO >= 2) strcat(pmodes, "pio2 ");
  507     }
  508     if (!(idw[53] & 1))
  509         printf(" (maybe):");
  510     printf(" CurCHS=%u/%u/%u, CurSects=%u", idw[54], idw[55], idw[56], idw[57] | (idw[58] << 16));
  511     printf(", LBA=%s", YN(idw[49] & 0x200));
  512     if (idw[49] & 0x200)
  513         printf(", LBAsects=%llu", get_lba_capacity(idw));
  514 
  515     if (idw[49] & 0x100) {
  516         if (idw[62] | idw[63]) {
  517             if (idw[62] & 0x100)    strcat(dmodes,"*");
  518             if (idw[62] & 1)    strcat(dmodes,"sdma0 ");
  519             if (idw[62] & 0x200)    strcat(dmodes,"*");
  520             if (idw[62] & 2)    strcat(dmodes,"sdma1 ");
  521             if (idw[62] & 0x400)    strcat(dmodes,"*");
  522             if (idw[62] & 4)    strcat(dmodes,"sdma2 ");
  523             if (idw[62] & 0xf800)   strcat(dmodes,"*");
  524             if (idw[62] & 0xf8) strcat(dmodes,"sdma? ");
  525             if (idw[63] & 0x100)    strcat(dmodes,"*");
  526             if (idw[63] & 1)    strcat(dmodes,"mdma0 ");
  527             if (idw[63] & 0x200)    strcat(dmodes,"*");
  528             if (idw[63] & 2)    strcat(dmodes,"mdma1 ");
  529             if (idw[63] & 0x400)    strcat(dmodes,"*");
  530             if (idw[63] & 4)    strcat(dmodes,"mdma2 ");
  531             if (idw[63] & 0xf800)   strcat(dmodes,"*");
  532             if (idw[63] & 0xf8) strcat(dmodes,"mdma? ");
  533         }
  534     }
  535     printf("\n IORDY=");
  536     if (idw[49] & 0x800)
  537         printf((idw[49] & 0x400) ? "on/off" : "yes");
  538     else
  539         printf("no");
  540     if ((idw[49] & 0x800) || (idw[53] & 2)) {
  541         if ((idw[53] & 2)) {
  542             printf(", tPIO={min:%u,w/IORDY:%u}", idw[67], idw[68]);
  543             if (idw[64] & 1)    strcat(pmodes, "pio3 ");
  544             if (idw[64] & 2)    strcat(pmodes, "pio4 ");
  545             if (idw[64] &~3)    strcat(pmodes, "pio? ");
  546         }
  547         if (idw[53] & 4) {
  548             if (idw[88] & 0x100)    strcat(umodes,"*");
  549             if (idw[88] & 0x001)    strcat(umodes,"udma0 ");
  550             if (idw[88] & 0x200)    strcat(umodes,"*");
  551             if (idw[88] & 0x002)    strcat(umodes,"udma1 ");
  552             if (idw[88] & 0x400)    strcat(umodes,"*");
  553             if (idw[88] & 0x004)    strcat(umodes,"udma2 ");
  554             if (idw[88] & 0x800)    strcat(umodes,"*");
  555             if (idw[88] & 0x008)    strcat(umodes,"udma3 ");
  556             if (idw[88] & 0x1000)   strcat(umodes,"*");
  557             if (idw[88] & 0x010)    strcat(umodes,"udma4 ");
  558             if (idw[88] & 0x2000)   strcat(umodes,"*");
  559             if (idw[88] & 0x020)    strcat(umodes,"udma5 ");
  560             if (idw[88] & 0x4000)   strcat(umodes,"*");
  561             if (idw[88] & 0x040)    strcat(umodes,"udma6 ");
  562         }
  563     }
  564     if ((idw[49] & 0x100) && (idw[53] & 2))
  565         printf(", tDMA={min:%u,rec:%u}", idw[65], idw[66]);
  566     printf("\n PIO modes:  %s", pmodes);
  567     if (*dmodes)
  568         printf("\n DMA modes:  %s", dmodes);
  569     if (*umodes)
  570         printf("\n UDMA modes: %s", umodes);
  571 
  572     printf("\n AdvancedPM=%s",YN(idw[83]&8));
  573     if (idw[83] & 8) {
  574         if (!(idw[86]&8))
  575             printf(": disabled (255)");
  576         else if ((idw[91]&0xFF00)!=0x4000)
  577             printf(": unknown setting");
  578         else
  579             printf(": mode=0x%02X (%u)",idw[91]&0xFF,idw[91]&0xFF);
  580     }
  581     if (idw[82]&0x20)
  582         printf(" WriteCache=%s",(idw[85]&0x20) ? "enabled" : "disabled");
  583     if (idw[81] || idw[80]) {
  584         printf("\n Drive conforms to: ");
  585         if (idw[81] <= 31)
  586             printf("%s: ", minor_str[idw[81]]);
  587         else
  588             printf("unknown: ");
  589         if (idw[80] != 0x0000 &&  /* NOVAL_0 */
  590             idw[80] != 0xFFFF) {  /* NOVAL_1 */
  591             int count = 0;
  592             for (i=0; i <= 7; i++) {
  593                 if (idw[80] & (1<<i))
  594                     printf("%s%u", count++ ? "," : " ATA/ATAPI-", i);
  595             }
  596         }
  597     }
  598     printf("\n");
  599     printf("\n * signifies the current active mode\n");
  600     printf("\n");
  601 }
  602 
  603 static const char *busstate_str (unsigned int value)
  604 {
  605     static const char *states[4] = {"off", "on", "tristate", "unknown"};
  606 
  607     if (value > 3)
  608         value = 3;
  609     return states[value];
  610 }
  611 
  612 static void interpret_standby (void)
  613 {
  614     printf(" (");
  615     switch(standby) {
  616         case 0:     printf("off");
  617                 break;
  618         case 252:   printf("21 minutes");
  619                 break;
  620         case 253:   printf("vendor-specific");
  621                 break;
  622         case 254:   printf("?reserved");
  623                 break;
  624         case 255:   printf("21 minutes + 15 seconds");
  625                 break;
  626         default:
  627             if (standby <= 240) {
  628                 unsigned int secs = standby * 5;
  629                 unsigned int mins = secs / 60;
  630                 secs %= 60;
  631                 if (mins)     printf("%u minute%s", mins,
  632                              mins==1 ? "" : "s");
  633                 if (mins && secs) printf(" + ");
  634                 if (secs)     printf("%u seconds", secs);
  635             } else if (standby <= 251) {
  636                 unsigned int mins = (standby - 240) * 30;
  637                 unsigned int hrs  = mins / 60;
  638                 mins %= 60;
  639                 if (hrs)      printf("%u hour%s", hrs,
  640                              hrs==1 ? "" : "s");
  641                 if (hrs && mins)  printf(" + ");
  642                 if (mins)     printf("%u minutes", mins);
  643             } else {
  644                 printf("illegal value");
  645             }
  646             break;
  647     }
  648     printf(")\n");
  649 }
  650 
  651 struct xfermode_entry {
  652     int val;
  653     const char *name;
  654 };
  655 
  656 static const struct xfermode_entry xfermode_table[] = {
  657     { 8,    "pio0" },
  658     { 9,    "pio1" },
  659     { 10,   "pio2" },
  660     { 11,   "pio3" },
  661     { 12,   "pio4" },
  662     { 13,   "pio5" },
  663     { 14,   "pio6" },
  664     { 15,   "pio7" },
  665     { 16,   "sdma0" },
  666     { 17,   "sdma1" },
  667     { 18,   "sdma2" },
  668     { 19,   "sdma3" },
  669     { 20,   "sdma4" },
  670     { 21,   "sdma5" },
  671     { 22,   "sdma6" },
  672     { 23,   "sdma7" },
  673     { 32,   "mdma0" },
  674     { 33,   "mdma1" },
  675     { 34,   "mdma2" },
  676     { 35,   "mdma3" },
  677     { 36,   "mdma4" },
  678     { 37,   "mdma5" },
  679     { 38,   "mdma6" },
  680     { 39,   "mdma7" },
  681     { 64,   "udma0" },
  682     { 65,   "udma1" },
  683     { 66,   "udma2" },
  684     { 67,   "udma3" },
  685     { 68,   "udma4" },
  686     { 69,   "udma5" },
  687     { 70,   "udma6" },
  688     { 71,   "udma7" },
  689     { 0, NULL }
  690 };
  691 
  692 static int translate_xfermode(char * name)
  693 {
  694     const struct xfermode_entry *tmp;
  695     char *endptr;
  696     int val = -1;
  697 
  698     for (tmp = xfermode_table; tmp->name != NULL; ++tmp) {
  699         if (!strcmp(name, tmp->name))
  700             return tmp->val;
  701     }
  702     val = strtol(name, &endptr, 10);
  703     if (*endptr == '\0')
  704         return val;
  705     return -1;
  706 }
  707 
  708 static void interpret_xfermode (unsigned int xfermode)
  709 {
  710     printf(" (");
  711     switch(xfermode) {
  712         case 0:     printf("default PIO mode");
  713                 break;
  714         case 1:     printf("default PIO mode, disable IORDY");
  715                 break;
  716         case 8:
  717         case 9:
  718         case 10:
  719         case 11:
  720         case 12:
  721         case 13:
  722         case 14:
  723         case 15:    printf("PIO flow control mode%u", xfermode-8);
  724                 break;
  725         case 16:
  726         case 17:
  727         case 18:
  728         case 19:
  729         case 20:
  730         case 21:
  731         case 22:
  732         case 23:    printf("singleword DMA mode%u", xfermode-16);
  733                 break;
  734         case 32:
  735         case 33:
  736         case 34:
  737         case 35:
  738         case 36:
  739         case 37:
  740         case 38:
  741         case 39:    printf("multiword DMA mode%u", xfermode-32);
  742                 break;
  743         case 64:
  744         case 65:
  745         case 66:
  746         case 67:
  747         case 68:
  748         case 69:
  749         case 70:
  750         case 71:    printf("UltraDMA mode%u", xfermode-64);
  751                 break;
  752         default:
  753                 printf("unknown, probably not valid");
  754                 break;
  755     }
  756     printf(")\n");
  757 }
  758 
  759 static unsigned int get_erase_timeout_secs (int fd, int enhanced)
  760 {
  761     // Grab ID Data
  762     get_identify_data(fd);
  763 
  764     if (id == NULL) {
  765         // ID pointer is invalid, return a default of twelve hours
  766         return 12 * 60 * 60;
  767     }
  768 
  769     // Build an estimate at 1 second per 30MB of capacity (Norman Diamond suggestion)
  770     // Add 30 mins of uncertainty
  771     __u64 const lba_limit = get_lba_capacity(id);
  772     __u64 const estimate  = ((lba_limit / 2048ULL) / 30ULL) + (30 * 60);
  773 
  774     // Grab the timeout field from the ID
  775     // If enhanced is non-zero then look at word 90, otherwise look at word 89
  776     // If bit 15 is set, then the time field is bits [14:0]
  777     // Otherwise the time field is bits [7:0] (ACS-3)
  778     unsigned int const idx      = (enhanced != 0) ? 90: 89;
  779     unsigned int       timeout  = id[idx];
  780     unsigned int const ext_time = (timeout & (1 << 15)) != 0;
  781 
  782     // Mask off reserved bits
  783     timeout = ext_time ? timeout & 0x7FFF: timeout & 0x00FF;
  784     if (timeout == 0) {
  785         // Value is not specified, return the estimate
  786         return estimate;
  787     }
  788 
  789     // Decode timeout (Add some wiggle room)
  790     timeout = ( ext_time && (timeout == 0x7FFF)) ? 65532 + 90:         // Max ext time is > 65532 minutes
  791               (!ext_time && (timeout == 0x00FF)) ? 508 + 90:           // Max non-ext time is > 508 minutes
  792                                                    (timeout * 2) + 60; // Time is id value * 2 mins
  793     timeout *= 60; // Convert timeout to seconds
  794 
  795     // Return the larger value between timeout and estimate
  796     return (timeout < estimate) ? estimate: timeout;
  797 }
  798 static int
  799 get_sanitize_state(__u8 nsect)
  800 {
  801     int state = SANITIZE_IDLE_STATE_SD0;
  802     if (nsect & SANITIZE_FLAG_DEVICE_IN_FROZEN) {
  803         state = SANITIZE_FROZEN_STATE_SD1;
  804     } else if (nsect & SANITIZE_FLAG_OPERATION_IN_PROGRESS) {
  805         state = SANITIZE_OPERATION_IN_PROGRESS_SD2;
  806     }
  807     return state;
  808 }
  809 
  810 static void
  811 sanitize_normal_output(int sanitize_state, struct hdio_taskfile * r)
  812 {
  813     printf("    State:    %s\n", sanitize_states_str[sanitize_state]);
  814     if (sanitize_state == SANITIZE_OPERATION_IN_PROGRESS_SD2) {
  815         int progress = (r->lob.lbam << 8) | r->lob.lbal;
  816         int percent = (progress == 0xFFFF) ? (100) : ((100 * (progress + 1)) / 0xFFFF);
  817         printf("    Progress: 0x%x (%d%%)\n", progress, percent);
  818     }
  819     if (r->hob.nsect & SANITIZE_FLAG_OPERATION_SUCCEEDED) {
  820         printf("    Last Sanitize Operation Completed Without Error\n");
  821     }
  822     if (r->hob.nsect & SANITIZE_FLAG_ANTIFREEZE_BIT)
  823         printf("    Antifreeze bit set\n");
  824 }
  825 
  826 static void
  827 sanitize_error_output(struct hdio_taskfile * r)
  828 {
  829     int err_reason = (r->lob.lbal >= SANITIZE_ERR_NUMBER) ? (SANITIZE_ERR_NO_REASON) : (r->lob.lbal);
  830     fprintf(stderr, "SANITIZE device error reason: %s\n", sanitize_err_reason_str[err_reason]);
  831     if (err_reason == SANITIZE_ERR_CMD_UNSUCCESSFUL)
  832         fprintf(stderr, "Drive in %s state\n", sanitize_states_str[SANITIZE_OPERATION_FAILED_SD3]);
  833 }
  834 
  835 static void
  836 do_sanitize_cmd (int fd)
  837 {
  838     int err = 0;
  839     __u64 lba = 0;
  840     const char *description;
  841     int sanitize_state;
  842     struct hdio_taskfile r;
  843 
  844     get_identify_data(fd);
  845     if (!id)
  846         exit(EIO);
  847     if (id[59] & 0x1000) {
  848 
  849         switch (sanitize_feature) {
  850             case SANITIZE_STATUS_EXT:
  851                 description = "SANITIZE_STATUS";
  852                 break;
  853             case SANITIZE_CRYPTO_SCRAMBLE_EXT:
  854                 lba = SANITIZE_CRYPTO_SCRAMBLE_KEY;
  855                 description = "SANITIZE_CRYPTO_SCRAMBLE";
  856                 break;
  857             case SANITIZE_BLOCK_ERASE_EXT:
  858                 lba = SANITIZE_BLOCK_ERASE_KEY;
  859                 description = "SANITIZE_BLOCK_ERASE";
  860                 break;
  861             case SANITIZE_OVERWRITE_EXT:
  862                 lba = ((__u64)(SANITIZE_OVERWRITE_KEY) << 32) | ow_pattern;
  863                 description = "SANITIZE_OVERWRITE";
  864                 break;
  865             case SANITIZE_FREEZE_LOCK_EXT:
  866                 lba = SANITIZE_FREEZE_LOCK_KEY;
  867                 description = "SANITIZE_FREEZE_LOCK";
  868                 break;
  869             case SANITIZE_ANTIFREEZE_LOCK_EXT:
  870                 lba = SANITIZE_ANTIFREEZE_LOCK_KEY;
  871                 description = "SANITIZE_ANTIFREEZE_LOCK";
  872                 break;
  873             default:
  874                 fprintf(stderr, "BUG in do_sanitize_cmd(), feat=0x%x\n", sanitize_feature);
  875                 exit(EINVAL);
  876         }
  877 
  878         memset(&r, 0, sizeof(r));
  879         r.cmd_req = TASKFILE_CMD_REQ_NODATA;
  880         r.dphase  = TASKFILE_DPHASE_NONE;
  881 
  882         r.oflags.bits.lob.command = 1;
  883         r.oflags.bits.lob.feat    = 1;
  884         r.oflags.bits.lob.lbal    = 1;
  885         r.oflags.bits.lob.lbam    = 1;
  886         r.oflags.bits.lob.lbah    = 1;
  887         r.oflags.bits.hob.lbal    = 1;
  888         r.oflags.bits.hob.lbam    = 1;
  889         r.oflags.bits.hob.lbah    = 1;
  890 
  891         r.lob.command = ATA_OP_SANITIZE;
  892         r.lob.feat    = sanitize_feature;
  893         r.lob.lbal    = lba;
  894         r.lob.lbam    = lba >>  8;
  895         r.lob.lbah    = lba >> 16;
  896         r.hob.lbal    = lba >> 24;
  897         r.hob.lbam    = lba >> 32;
  898         r.hob.lbah    = lba >> 40;
  899 
  900         r.iflags.bits.lob.lbal    = 1;
  901         r.iflags.bits.lob.lbam    = 1;
  902         r.iflags.bits.hob.nsect   = 1;
  903 
  904         if (sanitize_feature == SANITIZE_OVERWRITE_EXT) {
  905             r.oflags.bits.lob.nsect = 1;
  906             r.lob.nsect = sanitize_overwrite_passes;
  907         }
  908 
  909         printf("Issuing %s command\n", description);
  910         if (do_taskfile_cmd(fd, &r, 10)) {
  911             err = errno;
  912             perror("SANITIZE failed");
  913             sanitize_error_output(&r);
  914         }
  915         else {
  916             switch (sanitize_feature) {
  917                 case SANITIZE_STATUS_EXT:
  918                     printf("Sanitize status:\n");
  919                     sanitize_state = get_sanitize_state(r.hob.nsect);
  920                     sanitize_normal_output(sanitize_state, &r);
  921                     break;
  922                 case SANITIZE_BLOCK_ERASE_EXT:
  923                 case SANITIZE_OVERWRITE_EXT:
  924                 case SANITIZE_CRYPTO_SCRAMBLE_EXT:
  925                     printf("Operation started in background\n");
  926                     printf("You may use `--sanitize-status` to check progress\n");
  927                     break;
  928                 default:
  929                     //nothing here
  930                     break;
  931             }
  932         }
  933     } else {
  934         fprintf(stderr, "SANITIZE feature set is not supported\n");
  935         exit(EINVAL);
  936     }
  937     if (err)
  938         exit(err);
  939 }
  940 
  941 static void
  942 do_set_security (int fd)
  943 {
  944     int err = 0;
  945     const char *description;
  946     struct hdio_taskfile *r;
  947     __u8 *data;
  948 
  949     r = malloc(sizeof(struct hdio_taskfile) + 512);
  950     if (!r) {
  951         err = errno;
  952         perror("malloc()");
  953         exit(err);
  954     }
  955 
  956     memset(r, 0, sizeof(struct hdio_taskfile) + 512);
  957     r->cmd_req  = TASKFILE_CMD_REQ_OUT;
  958     r->dphase   = TASKFILE_DPHASE_PIO_OUT;
  959     r->obytes   = 512;
  960     r->lob.command  = security_command;
  961     r->oflags.bits.lob.nsect = 1;
  962     r->lob.nsect    = 1;
  963     data        = (__u8*)r->data;
  964     data[0]     = security_master & 0x01;
  965     memcpy(data+2, security_password, 32);
  966 
  967     r->oflags.bits.lob.command = 1;
  968     r->oflags.bits.lob.feat    = 1;
  969 
  970     switch (security_command) {
  971         case ATA_OP_SECURITY_ERASE_UNIT:
  972             description = "SECURITY_ERASE";
  973             data[0] |= enhanced_erase ? 0x02 : 0;
  974             break;
  975         case ATA_OP_SECURITY_DISABLE:
  976             description = "SECURITY_DISABLE";
  977             break;
  978         case ATA_OP_SECURITY_UNLOCK:
  979             description = "SECURITY_UNLOCK";
  980             break;
  981         case ATA_OP_SECURITY_SET_PASS:
  982             description = "SECURITY_SET_PASS";
  983             data[1] = (security_mode & 0x01);
  984             if (security_master) {
  985                 /* increment master-password revision-code */
  986                 __u16 revcode;
  987                 get_identify_data(fd);
  988                 if (!id)
  989                     exit(EIO);
  990                 revcode = id[92];
  991                 if (revcode == 0xfffe)
  992                     revcode = 0;
  993                 revcode += 1;
  994                 data[34] = revcode;
  995                 data[35] = revcode >> 8;
  996             }
  997             break;
  998         default:
  999             fprintf(stderr, "BUG in do_set_security(), command1=0x%x\n", security_command);
 1000             exit(EINVAL);
 1001     }
 1002     if (!quiet) {
 1003         printf(" Issuing %s command, password=\"%s\", user=%s",
 1004             description, security_password, (data[0] & 1) ? "master" : "user");
 1005         if (security_command == ATA_OP_SECURITY_SET_PASS)
 1006             printf(", mode=%s", data[1] ? "max" : "high");
 1007         printf("\n");
 1008     }
 1009 
 1010     /*
 1011      * The Linux kernel IDE driver (until at least 2.6.12) segfaults on the first
 1012      * command when issued on a locked drive, and the actual erase is never issued.
 1013      * One could patch the code to issue separate commands for erase prepare and
 1014      * erase to erase a locked drive.
 1015      *
 1016      * We would like to issue these commands consecutively, but since the Linux
 1017      * kernel until at least 2.6.12 segfaults on each command issued the second will
 1018      * never be executed.
 1019      *
 1020      * One is at least able to issue the commands consecutively in two hdparm invocations,
 1021      * assuming the segfault isn't followed by an oops.
 1022      */
 1023     if (security_command == ATA_OP_SECURITY_ERASE_UNIT) {
 1024         unsigned int timeout = get_erase_timeout_secs(fd, enhanced_erase);
 1025         __u8 args[4] = {ATA_OP_SECURITY_ERASE_PREPARE,0,0,0};
 1026         if (do_drive_cmd(fd, args, 0)) {   
 1027             err = errno;
 1028             perror("ERASE_PREPARE");
 1029         } else {
 1030             if ((do_taskfile_cmd(fd, r, timeout))) {
 1031                 err = errno;
 1032                 perror("SECURITY_ERASE");
 1033             }
 1034         }
 1035     } else if (security_command == ATA_OP_SECURITY_DISABLE) {
 1036         /* First attempt an unlock  */
 1037         r->lob.command = ATA_OP_SECURITY_UNLOCK;
 1038         if ((do_taskfile_cmd(fd, r, timeout_15secs))) {
 1039             err = errno;
 1040             perror("SECURITY_UNLOCK");
 1041         } else {
 1042             /* Then the security disable */
 1043             r->lob.command = security_command;
 1044             if ((do_taskfile_cmd(fd, r, timeout_15secs))) {
 1045                 err = errno;
 1046                 perror("SECURITY_DISABLE");
 1047             }
 1048         }
 1049     } else if (security_command == ATA_OP_SECURITY_UNLOCK) {
 1050         if ((do_taskfile_cmd(fd, r, timeout_15secs))) {
 1051             err = errno;
 1052             perror("SECURITY_UNLOCK");
 1053         }
 1054     } else if (security_command == ATA_OP_SECURITY_SET_PASS) {
 1055         if ((do_taskfile_cmd(fd, r, timeout_15secs))) {
 1056             err = errno;
 1057             perror("SECURITY_SET_PASS");
 1058         }
 1059     } else {
 1060         fprintf(stderr, "BUG in do_set_security(), command2=0x%x\n", security_command);
 1061         err = EINVAL;
 1062     }
 1063     free(r);
 1064     if (err)
 1065         exit(err);
 1066 }
 1067 
 1068 static __u8 last_identify_op = 0;
 1069 
 1070 static void get_identify_data (int fd)
 1071 {
 1072     static __u8 args[4+512];
 1073     int i;
 1074 
 1075     if (id)
 1076         return;
 1077     memset(args, 0, sizeof(args));
 1078     last_identify_op = ATA_OP_IDENTIFY;
 1079     args[0] = last_identify_op;
 1080     args[3] = 1;    /* sector count */
 1081     if (do_drive_cmd(fd, args, 0)) {
 1082         prefer_ata12 = 0;
 1083         memset(args, 0, sizeof(args));
 1084         last_identify_op = ATA_OP_PIDENTIFY;
 1085         args[0] = last_identify_op;
 1086         args[3] = 1;    /* sector count */
 1087         if (do_drive_cmd(fd, args, 0)) {
 1088             if (verbose)
 1089                 perror(" HDIO_DRIVE_CMD(identify) failed");
 1090             return;
 1091         }
 1092     }
 1093     /* byte-swap the little-endian IDENTIFY data to match byte-order on host CPU */
 1094     id = (void *)(args + 4);
 1095     for (i = 0; i < 0x100; ++i) {
 1096         unsigned char *b = (unsigned char *)&id[i];
 1097         id[i] = b[0] | (b[1] << 8); /* le16_to_cpu() */
 1098     }
 1099 }
 1100 
 1101 static int do_read_log (int fd, __u8 log_address, __u8 pagenr, void *buf)
 1102 {
 1103     struct hdio_taskfile *r;
 1104     int err = 0;
 1105 
 1106     r = malloc(sizeof(struct hdio_taskfile) + 512);
 1107     if (!r) {
 1108         err = errno;
 1109         perror("malloc()");
 1110         return err;
 1111     }
 1112 
 1113     init_hdio_taskfile(r, ATA_OP_READ_LOG_EXT, RW_READ, LBA48_FORCE, log_address + (pagenr << 8), 1, 512);
 1114     if (do_taskfile_cmd(fd, r, timeout_15secs)) {
 1115         err = errno;
 1116     } else {
 1117         memcpy(buf, r->data, 512);
 1118     }
 1119     free(r);
 1120     return err;
 1121 }
 1122 
 1123 
 1124 int get_log_page_data (int fd, __u8 log_address, __u8 pagenr, __u8 *buf)
 1125 {
 1126     static __u16 *page0 = NULL, page0_buf[512] = {0,};
 1127     int err;
 1128 
 1129     get_identify_data(fd);
 1130     if (!id)
 1131         exit(EIO);
 1132     if ((id[84] && (1<<5)) == 0)
 1133         return ENOENT;  /* READ_LOG_EXT not supported */
 1134     if (!page0) {
 1135         err = do_read_log(fd, 0, 0, page0_buf);
 1136         if (err) {
 1137             fprintf(stderr, "READ_LOG_EXT(0,0) failed: %s\n", strerror(err));
 1138             return ENOENT;
 1139         }
 1140         page0 = page0_buf;
 1141     }
 1142     if (page0[log_address] <= pagenr)
 1143         return ENOENT;
 1144     err = do_read_log(fd, log_address, pagenr, buf);
 1145     if (err) {
 1146         fprintf(stderr, "READ_LOG_EXT(0x%02x, %u) failed: %s\n", log_address, pagenr, strerror(err));
 1147         return ENOENT;
 1148     }
 1149     return 0;
 1150 }
 1151 
 1152 static void confirm_i_know_what_i_am_doing (const char *opt, const char *explanation)
 1153 {
 1154     if (!i_know_what_i_am_doing) {
 1155         fprintf(stderr, "Use of %s is VERY DANGEROUS.\n%s\n"
 1156         "Please supply the --yes-i-know-what-i-am-doing flag if you really want this.\n"
 1157         "Program aborted.\n", opt, explanation);
 1158         exit(EPERM);
 1159     }
 1160 }
 1161 
 1162 static void confirm_please_destroy_my_drive (const char *opt, const char *explanation)
 1163 {
 1164     if (!please_destroy_my_drive) {
 1165         fprintf(stderr, "Use of %s is EXTREMELY DANGEROUS.\n%s\n"
 1166         "Please also supply the --please-destroy-my-drive flag if you really want this.\n"
 1167         "Program aborted.\n", opt, explanation);
 1168         exit(EPERM);
 1169     }
 1170 }
 1171 
 1172 static int flush_wcache (int fd)
 1173 {
 1174     __u8 args[4] = {ATA_OP_FLUSHCACHE,0,0,0};
 1175     int err = 0;
 1176 
 1177     get_identify_data(fd);
 1178     if (id && (id[83] & 0xe000) == 0x6000)
 1179         args[0] = ATA_OP_FLUSHCACHE_EXT;
 1180     if (do_drive_cmd(fd, args, timeout_60secs)) {
 1181         err = errno;
 1182         perror (" HDIO_DRIVE_CMD(flushcache) failed");
 1183     }
 1184     return err;
 1185 }
 1186 
 1187 static void dump_sectors (__u16 *w, unsigned int count, int raw, unsigned int sector_bytes)
 1188 {
 1189     unsigned int i;
 1190 
 1191     for (i = 0; i < (count*(sector_bytes/2)/8); ++i) {
 1192         if (raw) {
 1193             printf("%04x %04x %04x %04x %04x %04x %04x %04x\n",
 1194                 w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]);
 1195             w += 8;
 1196         } else {
 1197             int word;
 1198             for (word = 0; word < 8; ++word) {
 1199                 unsigned char *b = (unsigned char *)w++;
 1200                 printf("%02x%02x", b[0], b[1]);
 1201                 putchar(word == 7 ? '\n' : ' ');
 1202             }
 1203         }
 1204     }
 1205 }
 1206 
 1207 static int abort_if_not_full_device (int fd, __u64 lba, const char *devname, const char *msg)
 1208 {
 1209     struct stat st;
 1210     __u64 start_lba;
 1211     int i, err, shortened = 0;
 1212     char *fdevname = strdup(devname);
 1213 
 1214     if (0 == fstat(fd, &st) && S_ISCHR(st.st_mode))
 1215         return 0; /* skip geometry test for character (non-block) devices; eg. /dev/sg* */
 1216     err = get_dev_geometry(fd, NULL, NULL, NULL, &start_lba, NULL);
 1217     if (err)
 1218         exit(err);
 1219     for (i = strlen(fdevname); --i > 2 && (fdevname[i] >= '0' && fdevname[i] <= '9');) {
 1220         fdevname[i] = '\0';
 1221         shortened = 1;
 1222     }
 1223 
 1224     if (!shortened)
 1225         fdevname = strdup("the full disk");
 1226 
 1227     if (start_lba == 0ULL)
 1228         return 0;
 1229     if (start_lba == START_LBA_UNKNOWN || fd_is_raid(fd)) {
 1230         fprintf(stderr, "%s is a RAID device: please specify an absolute LBA of a raw member device instead (raid1 only)\n", devname);
 1231     } else if (msg) {
 1232         fprintf(stderr, "%s\n", msg);
 1233     } else {
 1234         fprintf(stderr, "Device %s has non-zero LBA starting offset of %llu.\n", devname, start_lba);
 1235         fprintf(stderr, "Please use an absolute LBA with the /dev/ entry for the raw device, rather than a partition or raid name.\n");
 1236         fprintf(stderr, "%s is probably a partition of %s (?)\n", devname, fdevname);
 1237         fprintf(stderr, "The absolute LBA of sector %llu from %s should be %llu\n", lba, devname, start_lba + lba);
 1238     }
 1239     fprintf(stderr, "Aborting.\n");
 1240     exit(EINVAL);
 1241 }
 1242 
 1243 static __u16 *get_dco_identify_data (int fd, int quietly)
 1244 {
 1245     static __u8 args[4+512];
 1246     __u16 *dco = (void *)(args + 4);
 1247     int i;
 1248     
 1249     memset(args, 0, sizeof(args));
 1250     args[0] = ATA_OP_DCO;
 1251     args[2] = 0xc2;
 1252     args[3] = 1;
 1253     if (do_drive_cmd(fd, args, 0)) {
 1254         if (!quietly)
 1255             perror(" HDIO_DRIVE_CMD(dco_identify) failed");
 1256         return NULL;
 1257     } else {
 1258         /* byte-swap the little-endian DCO data to match byte-order on host CPU */
 1259         for (i = 0; i < 0x100; ++i) {
 1260             unsigned char *b = (unsigned char *)&dco[i];
 1261             dco[i] = b[0] | (b[1] << 8);    /* le16_to_cpu */
 1262         }
 1263         //dump_sectors(dco, 1, 0, 512);
 1264         return dco;
 1265     }
 1266 }
 1267 
 1268 static void
 1269 do_dco_setmax_cmd (int fd)
 1270 {
 1271     int err = 0;
 1272     struct hdio_taskfile *r;
 1273     __u8 *data;
 1274     __u16 *dco = (__u16 *) NULL;
 1275 
 1276     r = malloc(sizeof(struct hdio_taskfile) + 512);
 1277     if (!r) {
 1278         err = errno;
 1279         perror("malloc()");
 1280         exit(err);
 1281     }
 1282 
 1283     // first, get the dco data
 1284     dco = get_dco_identify_data(fd, 0);
 1285     if (dco != ((__u16 *) NULL)) {
 1286         __u64 *maxlba = (__u64 *) &dco[3];
 1287 
 1288         // first, check DCO checksum
 1289         if (dco_verify_checksum(dco) != (dco[255] >> 8)) {
 1290             printf("DCO Checksum FAILED!\n");
 1291             exit(1);
 1292         }
 1293         if (verbose) {
 1294             printf("Original DCO:\n");
 1295             dump_sectors(dco, 1, 0, 512);
 1296         }
 1297         // set the new MAXLBA to the requested sectors - 1
 1298         *maxlba = set_max_addr - 1;
 1299         // recalculate the checksum
 1300         dco[255] = (dco[255] & 0xFF) | ((__u16) dco_verify_checksum(dco) << 8);
 1301         if (verbose) {
 1302             printf("New DCO:\n");
 1303             dump_sectors(dco, 1, 0, 512);
 1304         }
 1305 
 1306     } else {
 1307         printf("DCO data is NULL!\n");
 1308         exit(1);
 1309     }
 1310     memset(r, 0, sizeof(struct hdio_taskfile) + 512);
 1311     r->cmd_req  = TASKFILE_CMD_REQ_OUT;
 1312     r->dphase   = TASKFILE_DPHASE_PIO_OUT;
 1313     r->obytes   = 512;
 1314     r->lob.command  = ATA_OP_DCO;
 1315     r->oflags.bits.lob.command = 1;
 1316     r->lob.feat        = 0xc3;
 1317     r->oflags.bits.lob.feat = 1;
 1318     data        = (__u8*)r->data;
 1319     // copy data from new dco to output buffer
 1320     memcpy(data, (__u8*) dco, 512);
 1321     if ((do_taskfile_cmd(fd, r, timeout_15secs))) {
 1322         err = errno;
 1323         perror("DEVICE CONFIGURATION SET");
 1324     } 
 1325     free(r);
 1326     if (err)
 1327         exit(err);
 1328 }
 1329 
 1330 
 1331 static __u64 do_get_native_max_sectors (int fd)
 1332 {
 1333     int err = 0;
 1334     __u64 max = 0;
 1335     struct hdio_taskfile r;
 1336 
 1337     get_identify_data(fd);
 1338     if (!id)
 1339         exit(EIO);
 1340     memset(&r, 0, sizeof(r));
 1341     r.cmd_req = TASKFILE_CMD_REQ_NODATA;
 1342     r.dphase  = TASKFILE_DPHASE_NONE;
 1343     r.oflags.bits.lob.command  = 1;
 1344     r.iflags.bits.lob.command  = 1;
 1345     r.iflags.bits.lob.lbal     = 1;
 1346     r.iflags.bits.lob.lbam     = 1;
 1347     r.iflags.bits.lob.lbah     = 1;
 1348 
 1349     if (SUPPORTS_AMAX_ADDR(id)) {
 1350         /* ACS3 supported, no 28-bit variant defined in spec */
 1351         r.iflags.bits.hob.lbal  = 1;
 1352         r.iflags.bits.hob.lbam  = 1;
 1353         r.iflags.bits.hob.lbah  = 1;
 1354         r.oflags.bits.lob.feat  = 1;
 1355         r.lob.command = ATA_OP_GET_NATIVE_MAX_EXT;
 1356         r.lob.feat = 0x00; //GET NATIVE MAX ADDRESS EXT is 78h/0000h
 1357         //bit 6 of DEVICE field is defined as "N/A"
 1358         if (do_taskfile_cmd(fd, &r, 0)) {
 1359             err = errno;
 1360             perror (" GET_NATIVE_MAX_ADDRESS_EXT failed");
 1361         } else {
 1362             if (verbose)
 1363                 printf("GET_NATIVE_MAX_ADDRESS_EXT response: hob={%02x %02x %02x} lob={%02x %02x %02x}\n",
 1364                        r.hob.lbah, r.hob.lbam, r.hob.lbal, r.lob.lbah, r.lob.lbam, r.lob.lbal);
 1365             max = (((__u64)((r.hob.lbah << 16) | ((__u64)(r.hob.lbam << 8) | r.hob.lbal)) << 24)
 1366                    | (__u64)((r.lob.lbah << 16) | (r.lob.lbam << 8) | r.lob.lbal)) + 1;
 1367         }
 1368     } else { // ACS2 or below, or optional AMAX not present
 1369         if (SUPPORTS_48BIT_ADDR(id)) {
 1370             r.iflags.bits.hob.lbal  = 1;
 1371             r.iflags.bits.hob.lbam  = 1;
 1372             r.iflags.bits.hob.lbah  = 1;
 1373             r.oflags.bits.lob.dev   = 1;
 1374             r.lob.command = ATA_OP_READ_NATIVE_MAX_EXT;
 1375             r.lob.dev = 0x40;
 1376             if (do_taskfile_cmd(fd, &r, timeout_15secs)) { //timeout for pre-ACS3 case of do_set_max_sectors
 1377                 err = errno;
 1378                 perror (" READ_NATIVE_MAX_ADDRESS_EXT failed");
 1379             } else {
 1380                 if (verbose)
 1381                     printf("READ_NATIVE_MAX_ADDRESS_EXT response: hob={%02x %02x %02x} lob={%02x %02x %02x}\n",
 1382                         r.hob.lbah, r.hob.lbam, r.hob.lbal, r.lob.lbah, r.lob.lbam, r.lob.lbal);
 1383                 max = (((__u64)((r.hob.lbah << 16) | (r.hob.lbam << 8) | r.hob.lbal) << 24)
 1384                         | ((__u64)(r.lob.lbah << 16) | (r.lob.lbam << 8) | r.lob.lbal)) + 1;
 1385             }
 1386         } else {
 1387             /* DEVICE (3:0) / LBA (27:24) "remap" does NOT apply in ATA Status Return */
 1388             r.iflags.bits.hob.lbal = 1;
 1389             r.lob.command = ATA_OP_READ_NATIVE_MAX;
 1390             //bit 7:5 of DEVICE field is defined as "Obsolete"
 1391             if (do_taskfile_cmd(fd, &r, timeout_15secs)) { //timeout for pre-ACS3 case of do_set_max_sectors
 1392                 err = errno;
 1393                 perror (" READ_NATIVE_MAX_ADDRESS failed");
 1394             } else {
 1395                 max = (((r.hob.lbal & 0x0f) << 24) | (r.lob.lbah << 16) | (r.lob.lbam << 8) | r.lob.lbal) + 1;
 1396             }
 1397         }
 1398     }
 1399 
 1400     errno = err;
 1401     return max;
 1402     
 1403 }
 1404 
 1405 static int do_make_bad_sector (int fd, __u64 lba, const char *devname)
 1406 {
 1407     int err = 0, has_write_unc = 0;
 1408     struct hdio_taskfile *r;
 1409     const char *flagged;
 1410 
 1411     abort_if_not_full_device(fd, lba, devname, NULL);
 1412     r = malloc(sizeof(struct hdio_taskfile) + 520);
 1413     if (!r) {
 1414         err = errno;
 1415         perror("malloc()");
 1416         return err;
 1417     }
 1418 
 1419     get_identify_data(fd);
 1420     if (id)
 1421         has_write_unc = (id[ 83] & 0xc000) == 0x4000 && (id[ 86] & 0x8000) == 0x8000
 1422                  && (id[119] & 0xc004) == 0x4004 && (id[120] & 0xc000) == 0x4000;
 1423 
 1424     if (has_write_unc || make_bad_sector_flagged || lba >= lba28_limit) {
 1425         if (!has_write_unc) {
 1426             printf("Device does not claim to implement the required WRITE_UNC_EXT command\n"
 1427                 "This operation will probably fail (continuing regardless).\n");
 1428         }
 1429         init_hdio_taskfile(r, ATA_OP_WRITE_UNC_EXT, RW_READ, LBA48_FORCE, lba, 1, 0);
 1430         r->oflags.bits.lob.feat = 1;
 1431         r->lob.feat = make_bad_sector_flagged ? 0xaa : 0x55;
 1432         flagged     = make_bad_sector_flagged ? "flagged" : "pseudo";
 1433         printf("Corrupting sector %llu (WRITE_UNC_EXT as %s): ", lba, flagged);
 1434     } else {
 1435         init_hdio_taskfile(r, ATA_OP_WRITE_LONG_ONCE, RW_WRITE, LBA28_OK, lba, 1, 520);
 1436         memset(r->data, 0xa5, 520);
 1437         printf("Corrupting sector %llu (WRITE_LONG): ", lba);
 1438     }
 1439     fflush(stdout);
 1440 
 1441     /* Try and ensure that the system doesn't have our sector in cache */
 1442     flush_buffer_cache(fd);
 1443 
 1444     if (do_taskfile_cmd(fd, r, timeout_60secs)) {
 1445         err = errno;
 1446         perror("FAILED");
 1447     } else {
 1448         printf("succeeded\n");
 1449     }
 1450     free(r);
 1451     return err;
 1452 }
 1453 
 1454 #ifdef FORMAT_AND_ERASE
 1455 static int do_format_track (int fd, __u64 lba, const char *devname)
 1456 {
 1457     int err = 0;
 1458     struct hdio_taskfile *r;
 1459 
 1460     abort_if_not_full_device(fd, lba, devname, NULL);
 1461     r = malloc(sizeof(struct hdio_taskfile) + 512);
 1462     if (!r) {
 1463         err = errno;
 1464         perror("malloc()");
 1465         return err;
 1466     }
 1467     init_hdio_taskfile(r, ATA_OP_FORMAT_TRACK, RW_WRITE, LBA28_OK, lba, 1, 512);
 1468     r->lob.nsect = 0;
 1469 
 1470     printf("re-formatting lba %llu: ", lba);
 1471     fflush(stdout);
 1472 
 1473     if (do_taskfile_cmd(fd, r, timeout_60secs)) {
 1474         err = errno;
 1475         perror("FAILED");
 1476     } else {
 1477         printf("succeeded\n");
 1478     }
 1479 
 1480     // Try and ensure that the system doesn't have our sector in cache:
 1481     flush_buffer_cache(fd);
 1482 
 1483     free(r);
 1484     return err;
 1485 }
 1486 
 1487 static int do_erase_sectors (int fd, __u64 lba, const char *devname)
 1488 {
 1489     int err = 0;
 1490     struct hdio_taskfile *r;
 1491 
 1492     abort_if_not_full_device(fd, lba, devname, NULL);
 1493     r = malloc(sizeof(struct hdio_taskfile) + 0);
 1494     if (!r) {
 1495         err = errno;
 1496         perror("malloc()");
 1497         return err;
 1498     }
 1499     init_hdio_taskfile(r, ATA_OP_ERASE_SECTORS, RW_READ, LBA28_OK, lba, 256, 0);
 1500 
 1501     printf("erasing sectors %llu-%llu: ", lba, lba + 255);
 1502     fflush(stdout);
 1503 
 1504     if (do_taskfile_cmd(fd, r, timeout_60secs)) {
 1505         err = errno;
 1506         perror("FAILED");
 1507     } else {
 1508         printf("succeeded\n");
 1509     }
 1510     free(r);
 1511     return err;
 1512 }
 1513 #endif /* FORMAT_AND_ERASE */
 1514 
 1515 struct sector_range_s {
 1516     __u64   lba;
 1517     __u64   nsectors;
 1518 };
 1519 
 1520 static int trim_sectors (int fd, const char *devname, int nranges, void *data, __u64 nsectors)
 1521 {
 1522     struct ata_tf tf;
 1523     int err = 0;
 1524     unsigned int data_bytes = nranges * sizeof(__u64);
 1525     unsigned int data_sects = (data_bytes + 511) / 512;
 1526 
 1527     data_bytes = data_sects * 512;
 1528 
 1529     abort_if_not_full_device(fd, 0, devname, NULL);
 1530     printf("trimming %llu sectors from %d ranges\n", nsectors, nranges);
 1531     fflush(stdout);
 1532 
 1533     // Try and ensure that the system doesn't have the to-be-trimmed sectors in cache:
 1534     flush_buffer_cache(fd);
 1535 
 1536     tf_init(&tf, ATA_OP_DSM, 0, data_sects);
 1537     tf.lob.feat = 0x01; /* DSM/TRIM */
 1538 
 1539     if (sg16(fd, SG_WRITE, SG_DMA, &tf, data, data_bytes, 300 /* seconds */)) {
 1540         err = errno;
 1541         perror("FAILED");
 1542     } else {
 1543         printf("succeeded\n");
 1544     }
 1545     return err;
 1546 }
 1547 
 1548 static void do_trim_sector_ranges (int fd, const char *devname, int nranges, struct sector_range_s *sr)
 1549 {
 1550     __u64 range, *data, nsectors = 0;
 1551     unsigned int data_sects, data_bytes;
 1552     int i, err = 0;
 1553 
 1554     abort_if_not_full_device(fd, 0, devname, NULL);
 1555 
 1556     data_sects = ((nranges * sizeof(range)) + 511) / 512;
 1557     data_bytes = data_sects * 512;
 1558 
 1559     data = mmap(NULL, data_bytes, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
 1560     if (data == MAP_FAILED) {
 1561         err = errno;
 1562         perror("mmap(MAP_ANONYMOUS)");
 1563         exit(err);
 1564     }
 1565     // FIXME: handle counts > 65535 here!
 1566     for (i = 0; i < nranges; ++i) {
 1567         nsectors += sr->nsectors;
 1568         range = sr->nsectors;
 1569         range = (__u64)(range << 48) | sr->lba;
 1570         data[i] = __cpu_to_le64(range);
 1571         ++sr;
 1572     }
 1573 
 1574     err = trim_sectors(fd, devname, nranges, data, nsectors);
 1575     munmap(data, data_bytes);
 1576     exit(err);
 1577 }
 1578 
 1579 static void
 1580 extract_id_string (__u16 *idw, int words, char *dst)
 1581 {
 1582     char *e;
 1583     int bytes = words * 2;
 1584 
 1585     memcpy(dst, idw, bytes);
 1586     dst[bytes] = '\0';
 1587     for (e = dst + bytes; --e != dst;) {
 1588         if (*e && *e != ' ')
 1589             break;
 1590         *e = '\0';
 1591     }
 1592 }
 1593 
 1594 static int
 1595 get_trim_dev_limit (void)
 1596 {
 1597     char model[41];
 1598 
 1599     if (id[105] && id[105] != 0xffff)
 1600         return id[105];
 1601     extract_id_string(id + 27, 20, model);
 1602     if (0 == strcmp(model, "OCZ VERTEX-LE"))
 1603         return 8;
 1604     if (0 == strcmp(model, "OCZ-VERTEX"))
 1605         return 64;
 1606     return 1;  /* all other drives, including Intel SSDs */
 1607 }
 1608 
 1609 int get_current_sector_size (int fd)
 1610 {
 1611     unsigned int words = 256;
 1612 
 1613     get_identify_data(fd);
 1614     if(id && (id[106] & 0xc000) == 0x4000) {
 1615         if (id[106] & (1<<12))
 1616             words = (id[118] << 16) | id[117];
 1617     }
 1618     return 2 * words;
 1619 }
 1620 
 1621 static int
 1622 get_set_sector_index (int fd, unsigned int wanted_sector_size, int *checkword)
 1623 {
 1624     __u8 d[512] = {0,};
 1625     const int SECTOR_CONFIG = 0x2f;
 1626     int i, rc, found_byte_lss = 0, found_word_lss = 0, lss_is_bytes = 0;
 1627     unsigned int current_lss;
 1628 
 1629     rc = get_log_page_data(fd, SECTOR_CONFIG, 0, d);
 1630     if (rc) {
 1631         fprintf(stderr, "READ_LOG_EXT(SECTOR_CONFIGURATION) failed: %s\n", strerror(rc));
 1632         exit(1);
 1633     }
 1634     /*
 1635      * Some devices incorrectly return logical sector size (lss) as bytes.
 1636      * Scan log entries and if the current lss is in the log, and there isn't an equivalent
 1637      * entry in words, assume the device is returning the logical sector size in bytes.
 1638      * Doing this takes two passes through the log data.
 1639      */
 1640     current_lss = (unsigned int)get_current_sector_size(fd);
 1641     for (i = 0; i < 128; i += 16) {
 1642         unsigned int lss;
 1643         if ((d[i] & 0x80) == 0)  /* Is this descriptor valid? */
 1644             continue;  /* not valid */
 1645         lss = d[i + 4] | (d[i + 5] << 8) | (d[i + 6] << 16) | (d[i + 7] << 24);  /* logical sector size */
 1646         if (lss == current_lss) {
 1647             found_byte_lss = 1;  /* found lss in bytes */
 1648         } else if ((lss * 2) == current_lss) {
 1649             found_word_lss = 1;  /* found lss in words */
 1650             break;
 1651         }
 1652     }
 1653     lss_is_bytes = !found_word_lss && found_byte_lss;
 1654     for (i = 0; i < 128; i += 16) {
 1655         unsigned int lss;
 1656         if ((d[i] & 0x80) == 0)  /* Is this descriptor valid? */
 1657             continue;  /* not valid */
 1658         lss = d[i + 4] | (d[i + 5] << 8) | (d[i + 6] << 16) | (d[i + 7] << 24);  /* logical sector size */
 1659         lss = lss_is_bytes ? lss : lss * 2;
 1660         if (lss == wanted_sector_size) {
 1661             *checkword = d[i + 2] | (d[i + 3] << 8);
 1662             return i / 16;  /* descriptor index */
 1663         }
 1664     }
 1665     fprintf(stderr, "ERROR: unsupported sector size: %d\n", wanted_sector_size);
 1666     exit (-1);
 1667 }
 1668 
 1669 static int do_set_sector_size_cmd (int fd, const char *devname)
 1670 {
 1671     int idx, err = 0;
 1672     __u8 ata_op;
 1673     struct hdio_taskfile *r;
 1674     int checkword = 0;
 1675 
 1676     abort_if_not_full_device(fd, 0, devname, NULL);
 1677     r = malloc(sizeof(struct hdio_taskfile) + 512);
 1678     if (!r) {
 1679         err = errno;
 1680         perror("malloc()");
 1681         return err;
 1682     }
 1683     ata_op = ATA_OP_SET_SECTOR_CONFIGURATION;
 1684     init_hdio_taskfile(r, ata_op, RW_WRITE, LBA48_FORCE, 0, 0, 0);
 1685 
 1686     idx = get_set_sector_index(fd, new_sector_size, &checkword);
 1687     r->hob.feat  = checkword >> 8;
 1688     r->lob.feat  = checkword;
 1689     r->hob.nsect = 0;
 1690     r->lob.nsect = idx;
 1691     r->oflags.bits.hob.feat = 1;
 1692 
 1693     printf("changing sector size configuration to %llu: ", new_sector_size);
 1694     fflush(stdout);
 1695 
 1696     if (do_taskfile_cmd(fd, r, timeout_60secs)) {
 1697         err = errno;
 1698         perror("FAILED");
 1699     } else {
 1700         printf("succeeded\n");
 1701     }
 1702 
 1703     free(r);
 1704     return err;
 1705 }
 1706 
 1707 static int
 1708 do_trim_from_stdin (int fd, const char *devname)
 1709 {
 1710     __u64 *data, range, nsectors = 0, lba_limit;
 1711     unsigned int max_kb, data_sects, data_bytes;
 1712     unsigned int total_ranges = 0, nranges = 0, max_ranges, dev_limit;
 1713     int err = 0;
 1714 
 1715     get_identify_data(fd);
 1716     if (!id)
 1717         exit(EIO);
 1718     lba_limit = get_lba_capacity(id);
 1719     dev_limit = get_trim_dev_limit();
 1720 
 1721     err = sysfs_get_attr(fd, "queue/max_sectors_kb", "%u", &max_kb, NULL, 0);
 1722     if (err || max_kb == 0)
 1723         data_sects = 128;   /* "safe" default for most controllers */
 1724     else
 1725         data_sects = max_kb * 2;
 1726     if (data_sects > dev_limit)
 1727         data_sects = dev_limit;
 1728     data_bytes = data_sects * 512;
 1729 
 1730     data = mmap(NULL, data_bytes, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
 1731     if (data == MAP_FAILED) {
 1732         err = errno;
 1733         perror("mmap(MAP_ANONYMOUS)");
 1734         exit(err);
 1735     }
 1736     memset(data, 0, data_bytes);
 1737     max_ranges = data_bytes / sizeof(range);
 1738 
 1739     do {
 1740         __u64 lba, nsect;
 1741         int args;
 1742 
 1743         if (nranges == 0)
 1744             memset(data, 0, data_bytes);
 1745         errno = EINVAL;
 1746         args = scanf("%llu:%llu", &lba, &nsect);
 1747         if (args == EOF)
 1748             break;
 1749         if (args != 2 || nsect > 0xffff || lba >= lba_limit) {
 1750             if (args == 2)
 1751                 errno = ERANGE;
 1752             err = errno;
 1753             fprintf(stderr, "stdin: error at lba:count pair #%d: %s\n", (total_ranges + 1), strerror(err));
 1754         } else {
 1755             range = (__u64)(nsect << 48) | lba;
 1756             nsectors += nsect;
 1757             data[nranges++] = __cpu_to_le64(range);
 1758             if (nranges == max_ranges) {
 1759                 err = trim_sectors(fd, devname, nranges, data, nsectors);
 1760                 memset(data, 0, data_bytes);
 1761                 nranges = 0;
 1762                 nsectors = 0;
 1763             }
 1764             ++total_ranges;
 1765         }
 1766     } while (!err);
 1767     if (!err && nranges)
 1768         err = trim_sectors(fd, devname, nranges, data, nsectors);
 1769     munmap(data, data_bytes);
 1770     return err;
 1771 }
 1772 
 1773 static int do_write_sector (int fd, __u64 lba, const char *devname)
 1774 {
 1775     int err = 0;
 1776     __u8 ata_op;
 1777     struct hdio_taskfile *r;
 1778     int sector_bytes = get_current_sector_size(fd);
 1779 
 1780     abort_if_not_full_device(fd, lba, devname, NULL);
 1781     r = malloc(sizeof(struct hdio_taskfile) + sector_bytes);
 1782     if (!r) {
 1783         err = errno;
 1784         perror("malloc()");
 1785         return err;
 1786     }
 1787     ata_op = (lba >= lba28_limit) ? ATA_OP_WRITE_PIO_EXT : ATA_OP_WRITE_PIO;
 1788     init_hdio_taskfile(r, ata_op, RW_WRITE, LBA28_OK, lba, 1, sector_bytes);
 1789 
 1790     printf("re-writing sector %llu: ", lba);
 1791     fflush(stdout);
 1792 
 1793     // Try and ensure that the system doesn't have our sector in cache:
 1794     flush_buffer_cache(fd);
 1795 
 1796     if (do_taskfile_cmd(fd, r, timeout_60secs)) {
 1797         err = errno;
 1798         perror("FAILED");
 1799     } else {
 1800         printf("succeeded\n");
 1801     }
 1802 
 1803     free(r);
 1804     return err;
 1805 }
 1806 
 1807 static int do_read_sector (int fd, __u64 lba, const char *devname)
 1808 {
 1809     int err = 0;
 1810     __u8 ata_op;
 1811     struct hdio_taskfile *r;
 1812     int sector_bytes = get_current_sector_size(fd);
 1813 
 1814     abort_if_not_full_device(fd, lba, devname, NULL);
 1815     r = malloc(sizeof(struct hdio_taskfile) + sector_bytes);
 1816     if (!r) {
 1817         err = errno;
 1818         perror("malloc()");
 1819         return err;
 1820     }
 1821     ata_op = (lba >= lba28_limit) ? ATA_OP_READ_PIO_EXT : ATA_OP_READ_PIO;
 1822     init_hdio_taskfile(r, ata_op, RW_READ, LBA28_OK, lba, 1, sector_bytes);
 1823 
 1824     printf("reading sector %llu: ", lba);
 1825     fflush(stdout);
 1826 
 1827     if (do_taskfile_cmd(fd, r, timeout_60secs)) {
 1828         err = errno;
 1829         perror("FAILED");
 1830     } else {
 1831         printf("succeeded\n");
 1832         dump_sectors(r->data, 1, 0, sector_bytes);
 1833     }
 1834     free(r);
 1835     return err;
 1836 }
 1837 
 1838 static int do_idleunload (int fd, const char *devname)
 1839 {
 1840     int err = 0;
 1841     struct hdio_taskfile r;
 1842 
 1843     abort_if_not_full_device(fd, 0, devname, NULL);
 1844     init_hdio_taskfile(&r, ATA_OP_IDLEIMMEDIATE, RW_READ, LBA28_OK, 0x0554e4c, 0, 0);
 1845     r.oflags.bits.lob.feat = 1;
 1846     r.lob.feat = 0x44;
 1847 
 1848     if (do_taskfile_cmd(fd, &r, 0)) {
 1849         err = errno;
 1850         perror("TASKFILE(idle_immediate_unload) failed");
 1851     }
 1852     return err;
 1853 }
 1854 
 1855 static int do_set_max_sectors (int fd, __u64 max_lba, int permanent)
 1856 {
 1857     int err = 0;
 1858     struct hdio_taskfile r;
 1859     __u8 nsect = permanent ? 1 : 0;
 1860     
 1861     get_identify_data(fd);
 1862     if (!id)
 1863         exit(EIO);
 1864     
 1865     if (SUPPORTS_AMAX_ADDR(id)) {
 1866         /* ACS3 supported, no 28-bit variant defined in spec */
 1867         init_hdio_taskfile(&r, ATA_OP_GET_NATIVE_MAX_EXT, RW_READ, LBA48_FORCE, max_lba, nsect, 0);
 1868         r.oflags.bits.lob.feat = 1;
 1869         r.lob.feat = 0x01; //SET ACCESSIBLE MAX ADDRESS EXT is 78h/0001h
 1870         //bit 6 of DEVICE field is defined as "N/A"
 1871 
 1872         /* No more "racey" in ACS3+AMAX case? */
 1873         if (do_taskfile_cmd(fd, &r, timeout_15secs)) {
 1874             err = errno;
 1875             perror(" SET_ACCESSIBLE_MAX_ADDRESS_EXT failed");
 1876         }
 1877     } else {
 1878         if ((max_lba >= lba28_limit) || SUPPORTS_48BIT_ADDR(id)) {
 1879             init_hdio_taskfile(&r, ATA_OP_SET_MAX_EXT, RW_READ, LBA48_FORCE, max_lba, nsect, 0);
 1880             r.oflags.bits.lob.dev = 1;
 1881             r.lob.dev = 0x40;
 1882         } else {
 1883             init_hdio_taskfile(&r, ATA_OP_SET_MAX, RW_READ, LBA28_OK, max_lba, nsect, 0);
 1884             //bit 7:5 of DEVICE field is defined as "Obsolete"
 1885         }
 1886 
 1887         /* spec requires that we do this immediately in front.. racey */
 1888         if (!do_get_native_max_sectors(fd))
 1889             return errno;
 1890 
 1891         /* now set the new value */
 1892         if (do_taskfile_cmd(fd, &r, 0)) {
 1893             err = errno;
 1894             perror(" SET_MAX_ADDRESS(_EXT) failed");
 1895         }
 1896     }
 1897 
 1898     return err;
 1899 }
 1900 
 1901 static void usage_help (int clue, int rc)
 1902 {
 1903     FILE *desc = rc ? stderr : stdout;
 1904 
 1905     fprintf(desc,"\n%s - get/set hard disk parameters - version " HDPARM_VERSION ", by Mark Lord.\n\n", progname);
 1906     if (1) if (rc) fprintf(desc, "clue=%d\n", clue);
 1907     fprintf(desc,"Usage:  %s  [options] [device ...]\n\n", progname);
 1908     fprintf(desc,"Options:\n"
 1909     " -a   Get/set fs readahead\n"
 1910     " -A   Get/set the drive look-ahead flag (0/1)\n"
 1911     " -b   Get/set bus state (0 == off, 1 == on, 2 == tristate)\n"
 1912     " -B   Set Advanced Power Management setting (1-255)\n"
 1913     " -c   Get/set IDE 32-bit IO setting\n"
 1914     " -C   Check drive power mode status\n"
 1915     " -d   Get/set using_dma flag\n"
 1916     " -D   Enable/disable drive defect management\n"
 1917     " -E   Set cd/dvd drive speed\n"
 1918     " -f   Flush buffer cache for device on exit\n"
 1919     " -F   Flush drive write cache\n"
 1920     " -g   Display drive geometry\n"
 1921     " -h   Display terse usage information\n"
 1922     " -H   Read temperature from drive (Hitachi only)\n"
 1923     " -i   Display drive identification\n"
 1924     " -I   Detailed/current information directly from drive\n"
 1925     " -J   Get/set Western DIgital \"Idle3\" timeout for a WDC \"Green\" drive (DANGEROUS)\n"
 1926     " -k   Get/set keep_settings_over_reset flag (0/1)\n"
 1927     " -K   Set drive keep_features_over_reset flag (0/1)\n"
 1928     " -L   Set drive doorlock (0/1) (removable harddisks only)\n"
 1929     " -m   Get/set multiple sector count\n"
 1930     " -M   Get/set acoustic management (0-254, 128: quiet, 254: fast)\n"
 1931     " -n   Get/set ignore-write-errors flag (0/1)\n"
 1932     " -N   Get/set max visible number of sectors (HPA) (VERY DANGEROUS)\n"
 1933     " -p   Set PIO mode on IDE interface chipset (0,1,2,3,4,...)\n"
 1934     " -P   Set drive prefetch count\n"
 1935     " -q   Change next setting quietly\n"
 1936     " -Q   Get/set DMA queue_depth (if supported)\n"
 1937     " -r   Get/set device readonly flag (DANGEROUS to set)\n"
 1938     " -R   Get/set device write-read-verify flag\n"
 1939     " -s   Set power-up in standby flag (0/1) (DANGEROUS)\n"
 1940     " -S   Set standby (spindown) timeout\n"
 1941     " -t   Perform device read timings\n"
 1942     " -T   Perform cache read timings\n"
 1943     " -u   Get/set unmaskirq flag (0/1)\n"
 1944     " -U   Obsolete\n"
 1945     " -v   Use defaults; same as -acdgkmur for IDE drives\n"
 1946     " -V   Display program version and exit immediately\n"
 1947     " -w   Perform device reset (DANGEROUS)\n"
 1948     " -W   Get/set drive write-caching flag (0/1)\n"
 1949     " -x   Obsolete\n"
 1950     " -X   Set IDE xfer mode (DANGEROUS)\n"
 1951     " -y   Put drive in standby mode\n"
 1952     " -Y   Put drive to sleep\n"
 1953     " -z   Re-read partition table\n"
 1954     " -Z   Disable Seagate auto-powersaving mode\n"
 1955     " --dco-freeze      Freeze/lock current device configuration until next power cycle\n"
 1956     " --dco-identify    Read/dump device configuration identify data\n"
 1957     " --dco-restore     Reset device configuration back to factory defaults\n"
 1958     " --dco-setmax      Use DCO to set maximum addressable sectors\n"
 1959     " --direct          Use O_DIRECT to bypass page cache for timings\n"
 1960     " --drq-hsm-error   Crash system with a \"stuck DRQ\" error (VERY DANGEROUS)\n"
 1961     " --fallocate       Create a file without writing data to disk\n"
 1962     " --fibmap          Show device extents (and fragmentation) for a file\n"
 1963     " --fwdownload            Download firmware file to drive (EXTREMELY DANGEROUS)\n"
 1964     " --fwdownload-mode3      Download firmware using min-size segments (EXTREMELY DANGEROUS)\n"
 1965     " --fwdownload-mode3-max  Download firmware using max-size segments (EXTREMELY DANGEROUS)\n"
 1966     " --fwdownload-mode7      Download firmware using a single segment (EXTREMELY DANGEROUS)\n"
 1967     " --fwdownload-modee      Download firmware using mode E (min-size segments) (EXTREMELY DANGEROUS)\n"
 1968     " --fwdownload-modee-max  Download firmware using mode E (max-size segments) (EXTREMELY DANGEROUS)\n"
 1969     " --idle-immediate  Idle drive immediately\n"
 1970     " --idle-unload     Idle immediately and unload heads\n"
 1971     " --Iraw filename   Write raw binary identify data to the specfied file\n"
 1972     " --Istdin          Read identify data from stdin as ASCII hex\n"
 1973     " --Istdout         Write identify data to stdout as ASCII hex\n"
 1974     " --make-bad-sector Deliberately corrupt a sector directly on the media (VERY DANGEROUS)\n"
 1975     " --offset          use with -t, to begin timings at given offset (in GiB) from start of drive\n"
 1976     " --prefer-ata12    Use 12-byte (instead of 16-byte) SAT commands when possible\n"
 1977     " --read-sector     Read and dump (in hex) a sector directly from the media\n"
 1978     " --repair-sector   Alias for the --write-sector option (VERY DANGEROUS)\n"
 1979     " --sanitize-antifreeze-lock  Block sanitize-freeze-lock command until next power cycle\n"
 1980     " --sanitize-block-erase      Start block erase operation\n"
 1981     " --sanitize-crypto-scramble  Change the internal encryption keys that used for used data\n"
 1982     " --sanitize-freeze-lock      Lock drive's sanitize features until next power cycle\n"
 1983     " --sanitize-overwrite  PATTERN  Overwrite the internal media with constant PATTERN\n"
 1984     " --sanitize-overwrite-passes COUNT  Number of overwrite passes from 0 to 7, default 0 means 16 passes\n"
 1985     " --sanitize-status           Show sanitize status information\n"
 1986     " --security-help             Display help for ATA security commands\n"
 1987     " --set-sector-size           Change logical sector size of drive\n"
 1988     " --trim-sector-ranges        Tell SSD firmware to discard unneeded data sectors: lba:count ..\n"
 1989     " --trim-sector-ranges-stdin  Same as above, but reads lba:count pairs from stdin\n"
 1990     " --verbose                   Display extra diagnostics from some commands\n"
 1991     " --write-sector              Repair/overwrite a (possibly bad) sector directly on the media (VERY DANGEROUS)\n"
 1992     "\n");
 1993     exit(rc);
 1994 }
 1995 
 1996 static void security_help (int rc)
 1997 {
 1998     FILE *desc = rc ? stderr : stdout;
 1999 
 2000     fprintf(desc, "\n"
 2001     "ATA Security Commands:\n"
 2002     " Most of these are VERY DANGEROUS and can destroy all of your data!\n"
 2003     " Due to bugs in older Linux kernels, use of these commands may even\n"
 2004     " trigger kernel segfaults or worse.  EXPERIMENT AT YOUR OWN RISK!\n"
 2005     "\n"
 2006     " --security-freeze           Freeze security settings until reset.\n"
 2007     "\n"
 2008     " --security-set-pass PASSWD  Lock drive, using password PASSWD:\n"
 2009     "                                  Use 'NULL' to set empty password.\n"
 2010     "                                  Drive gets locked if user-passwd is selected.\n"
 2011     " --security-prompt-for-password   Prompt user to enter the drive password.\n"
 2012     "\n"
 2013     " --security-unlock   PASSWD  Unlock drive.\n"
 2014     " --security-disable  PASSWD  Disable drive locking.\n"
 2015     " --security-erase    PASSWD  Erase a (locked) drive.\n"
 2016     " --security-erase-enhanced PASSWD   Enhanced-erase a (locked) drive.\n"
 2017     "\n"
 2018     " The above four commands may optionally be preceded by these options:\n"
 2019     " --security-mode  LEVEL      Use LEVEL to select security level:\n"
 2020     "                                  h   high security (default).\n"
 2021     "                                  m   maximum security.\n"
 2022     " --user-master    WHICH      Use WHICH to choose password type:\n"
 2023     "                                  u   user-password (default).\n"
 2024     "                                  m   master-password\n"
 2025     );
 2026     exit(rc);
 2027 }
 2028 
 2029 void process_dev (char *devname)
 2030 {
 2031     int fd;
 2032     int err = 0;
 2033     static long parm, multcount;
 2034 
 2035     id = NULL;
 2036     fd = open(devname, open_flags);
 2037     if (fd < 0) {
 2038         err = errno;
 2039         perror(devname);
 2040         exit(err);
 2041     }
 2042     if (!quiet)
 2043         printf("\n%s:\n", devname);
 2044 
 2045     if (apt_detect(fd, verbose) == -1) {
 2046         err = errno;
 2047         perror(devname);
 2048         close(fd);
 2049         exit(err);
 2050     }
 2051 
 2052     if (do_set_sector_size) {
 2053         if (num_flags_processed > 1 || argc)
 2054             usage_help(16,EINVAL);
 2055         confirm_please_destroy_my_drive("--" SET_SECTOR_SIZE, "This will likely destroy all data on the drive.");
 2056         exit(do_set_sector_size_cmd(fd, devname));
 2057     }
 2058 
 2059     if (trim_from_stdin) {
 2060         if (num_flags_processed > 1 || argc)
 2061             usage_help(12,EINVAL);
 2062         confirm_please_destroy_my_drive("--trim-sector-ranges-stdin", "This might destroy the drive and/or all data on it.");
 2063         exit(do_trim_from_stdin(fd, devname));
 2064     }
 2065 
 2066     if (set_wdidle3) {
 2067         unsigned char timeout = wdidle3_msecs_to_timeout(wdidle3);
 2068         confirm_please_destroy_my_drive("-J", "This implementation is not as thorough as the official WDIDLE3.EXE. Use at your own risk!");
 2069         if (get_wdidle3) {
 2070             printf(" setting wdidle3 to ");
 2071             wdidle3_print_timeout(timeout);
 2072             putchar('\n');
 2073         }
 2074         err = wdidle3_set_timeout(fd, timeout);
 2075     }
 2076     if (set_fsreadahead) {
 2077         if (get_fsreadahead)
 2078             printf(" setting fs readahead to %d\n", fsreadahead);
 2079         if (ioctl(fd, BLKRASET, fsreadahead)) {
 2080             err = errno;
 2081             perror(" BLKRASET failed");
 2082         }
 2083     }
 2084     if (set_piomode) {
 2085         if (get_piomode) {
 2086             if (piomode == 255)
 2087                 printf(" attempting to auto-tune PIO mode\n");
 2088             else if (piomode < 100)
 2089                 printf(" attempting to set PIO mode to %d\n", piomode);
 2090             else if (piomode < 200)
 2091                 printf(" attempting to set MDMA mode to %d\n", (piomode-100));
 2092             else
 2093                 printf(" attempting to set UDMA mode to %d\n", (piomode-200));
 2094         }
 2095         if (ioctl(fd, HDIO_SET_PIO_MODE, piomode)) {
 2096             err = errno;
 2097             perror(" HDIO_SET_PIO_MODE failed");
 2098         }
 2099     }
 2100     if (set_io32bit) {
 2101         if (get_io32bit)
 2102             printf(" setting 32-bit IO_support flag to %d\n", io32bit);
 2103         if (ioctl(fd, HDIO_SET_32BIT, io32bit)) {
 2104             err = errno;
 2105             perror(" HDIO_SET_32BIT failed");
 2106         }
 2107     }
 2108     if (set_mult) {
 2109         if (get_mult)
 2110             printf(" setting multcount to %d\n", mult);
 2111         if (ioctl(fd, HDIO_SET_MULTCOUNT, mult))
 2112 #if 0
 2113             perror(" HDIO_SET_MULTCOUNT failed");
 2114 #else /* for libata */
 2115         {
 2116             if (errno != ENOTTY) {
 2117                 perror(" HDIO_SET_MULTCOUNT failed");
 2118             } else {
 2119                 __u8 args[4] = {ATA_OP_SET_MULTIPLE,mult,0,0};
 2120                 confirm_i_know_what_i_am_doing("-m", "Only the old IDE drivers work correctly with -m with kernels up to at least 2.6.29.\nlibata drives may fail and get hung if you set this flag.");
 2121                 if (do_drive_cmd(fd, args, 0)) {
 2122                     err = errno;
 2123                     perror(" HDIO_DRIVE_CMD(set_multi_count) failed");
 2124                 }
 2125             }
 2126         }
 2127 #endif
 2128     }
 2129     if (set_readonly) {
 2130         if (get_readonly) {
 2131             printf(" setting readonly to %d", readonly);
 2132             on_off(readonly);
 2133         }
 2134         if (ioctl(fd, BLKROSET, &readonly)) {
 2135             err = errno;
 2136             perror(" BLKROSET failed");
 2137         }
 2138     }
 2139     if (set_unmask) {
 2140         if (get_unmask) {
 2141             printf(" setting unmaskirq to %d", unmask);
 2142             on_off(unmask);
 2143         }
 2144         if (ioctl(fd, HDIO_SET_UNMASKINTR, unmask)) {
 2145             err = errno;
 2146             perror(" HDIO_SET_UNMASKINTR failed");
 2147         }
 2148     }
 2149     if (set_dma) {
 2150         if (get_dma) {
 2151             printf(" setting using_dma to %d", dma);
 2152             on_off(dma);
 2153         }
 2154         if (ioctl(fd, HDIO_SET_DMA, dma)) {
 2155             err = errno;
 2156             perror(" HDIO_SET_DMA failed");
 2157         }
 2158     }
 2159     if (set_dma_q) {
 2160         if (get_dma_q)
 2161             printf(" setting queue_depth to %d\n", dma_q);
 2162         err = sysfs_set_attr(fd, "device/queue_depth", "%u", &dma_q, 1);
 2163     }
 2164     if (set_nowerr) {
 2165         if (get_nowerr) {
 2166             printf(" setting nowerr to %d", nowerr);
 2167             on_off(nowerr);
 2168         }
 2169         if (ioctl(fd, HDIO_SET_NOWERR, nowerr)) {
 2170             err = errno;
 2171             perror(" HDIO_SET_NOWERR failed");
 2172         }
 2173     }
 2174     if (set_keep) {
 2175         if (get_keep) {
 2176             printf(" setting keep_settings to %d", keep);
 2177             on_off(keep);
 2178         }
 2179         if (ioctl(fd, HDIO_SET_KEEPSETTINGS, keep)) {
 2180             err = errno;
 2181             perror(" HDIO_SET_KEEPSETTINGS failed");
 2182         }
 2183     }
 2184     if (set_doorlock) {
 2185         __u8 args[4] = {0,0,0,0};
 2186         args[0] = doorlock ? ATA_OP_DOORLOCK : ATA_OP_DOORUNLOCK;
 2187         if (get_doorlock) {
 2188             printf(" setting drive doorlock to %d", doorlock);
 2189             on_off(doorlock);
 2190         }
 2191         if (do_drive_cmd(fd, args, timeout_15secs)) {
 2192             err = errno;
 2193             perror(" HDIO_DRIVE_CMD(doorlock) failed");
 2194         }
 2195     }
 2196     if (set_dkeep) {
 2197         /* lock/unlock the drive's "feature" settings */
 2198         __u8 args[4] = {ATA_OP_SETFEATURES,0,0,0};
 2199         if (get_dkeep) {
 2200             printf(" setting drive keep features to %d", dkeep);
 2201             on_off(dkeep);
 2202         }
 2203         args[2] = dkeep ? 0x66 : 0xcc;
 2204         if (do_drive_cmd(fd, args, 0)) {
 2205             err = errno;
 2206             perror(" HDIO_DRIVE_CMD(keepsettings) failed");
 2207         }
 2208     }
 2209     if (set_defects) {
 2210         __u8 args[4] = {ATA_OP_SETFEATURES,0,0,0};
 2211         args[2] = defects ? 0x04 : 0x84;
 2212         if (get_defects)
 2213             printf(" setting drive defect management to %d\n", defects);
 2214         if (do_drive_cmd(fd, args, 0)) {
 2215             err = errno;
 2216             perror(" HDIO_DRIVE_CMD(defectmgmt) failed");
 2217         }
 2218     }
 2219     if (set_prefetch) {
 2220         __u8 args[4] = {ATA_OP_SETFEATURES,0,0xab,0};
 2221         args[1] = prefetch;
 2222         if (get_prefetch)
 2223             printf(" setting drive prefetch to %d\n", prefetch);
 2224         if (do_drive_cmd(fd, args, 0)) {
 2225             err = errno;
 2226             perror(" HDIO_DRIVE_CMD(setprefetch) failed");
 2227         }
 2228     }
 2229     if (set_xfermode) {
 2230         __u8 args[4] = {ATA_OP_SETFEATURES,0,3,0};
 2231         args[1] = xfermode_requested;
 2232         if (get_xfermode) {
 2233             printf(" setting xfermode to %d", xfermode_requested);
 2234             interpret_xfermode(xfermode_requested);
 2235         }
 2236         if (do_drive_cmd(fd, args, 0)) {
 2237             err = errno;
 2238             perror(" HDIO_DRIVE_CMD(setxfermode) failed");
 2239         }
 2240     }
 2241     if (set_lookahead) {
 2242         __u8 args[4] = {ATA_OP_SETFEATURES,0,0,0};
 2243         args[2] = lookahead ? 0xaa : 0x55;
 2244         if (get_lookahead) {
 2245             printf(" setting drive read-lookahead to %d", lookahead);
 2246             on_off(lookahead);
 2247         }
 2248         if (do_drive_cmd(fd, args, 0)) {
 2249             err = errno;
 2250             perror(" HDIO_DRIVE_CMD(setreadahead) failed");
 2251         }
 2252     }
 2253     if (set_powerup_in_standby) {
 2254         __u8 args[4] = {ATA_OP_SETFEATURES,0,0,0};
 2255         if (powerup_in_standby == 0) {
 2256             __u8 args1[4] = {ATA_OP_SETFEATURES,0,0x07,0}; /* spinup from standby */
 2257             printf(" spin-up:");
 2258             fflush(stdout);
 2259             (void) do_drive_cmd(fd, args1, 0);
 2260         } else {
 2261             confirm_i_know_what_i_am_doing("-s1",
 2262                 "This requires BIOS and kernel support to recognize/boot the drive.");
 2263         }
 2264         if (get_powerup_in_standby) {
 2265             printf(" setting power-up in standby to %d", powerup_in_standby);
 2266             fflush(stdout);
 2267             on_off(powerup_in_standby);
 2268         }
 2269         args[0] = ATA_OP_SETFEATURES;
 2270         args[2] = powerup_in_standby ? 0x06 : 0x86;
 2271         if (do_drive_cmd(fd, args, 0)) {
 2272             err = errno;
 2273             perror(" HDIO_DRIVE_CMD(powerup_in_standby) failed");
 2274         }
 2275     }
 2276     if (set_apmmode) {
 2277         __u8 args[4] = {ATA_OP_SETFEATURES,0,0,0};
 2278         if (get_apmmode)
 2279             printf(" setting Advanced Power Management level to");
 2280         if (apmmode==255) {
 2281             /* disable Advanced Power Management */
 2282             args[2] = 0x85; /* feature register */
 2283             if (get_apmmode) printf(" disabled\n");
 2284         } else {
 2285             /* set Advanced Power Management mode */
 2286             args[2] = 0x05; /* feature register */
 2287             args[1] = apmmode; /* sector count register */
 2288             if (get_apmmode)
 2289                 printf(" 0x%02x (%d)\n",apmmode,apmmode);
 2290         }
 2291         if (do_drive_cmd(fd, args, 0)) {
 2292             err = errno;
 2293             perror(" HDIO_DRIVE_CMD failed");
 2294         }
 2295     }
 2296     if (set_cdromspeed) {
 2297         int err1, err2;
 2298         /* The CDROM_SELECT_SPEED ioctl
 2299          * actually issues GPCMD_SET_SPEED to the drive.
 2300          * But many newer DVD drives want GPCMD_SET_STREAMING instead,
 2301          * which we now do afterwards.
 2302          */
 2303         if (get_cdromspeed)
 2304             printf ("setting cd/dvd speed to %d\n", cdromspeed);
 2305         err1 = set_dvdspeed(fd, cdromspeed);
 2306         err2 = ioctl(fd, CDROM_SELECT_SPEED, cdromspeed);
 2307         if (err1 && err2) {
 2308             err = errno;
 2309             perror(" SET_STREAMING/CDROM_SELECT_SPEED both failed");
 2310         }
 2311     }
 2312     if (set_acoustic) {
 2313         __u8 args[4];
 2314         if (get_acoustic)
 2315             printf(" setting acoustic management to %d\n", acoustic);
 2316         args[0] = ATA_OP_SETFEATURES;
 2317         args[1] = acoustic;
 2318         args[2] = acoustic ? 0x42 : 0xc2;
 2319         args[3] = 0;
 2320         if (do_drive_cmd(fd, args, 0)) {
 2321             err = errno;
 2322             perror(" HDIO_DRIVE_CMD:ACOUSTIC failed");
 2323         }
 2324     }
 2325     if (set_write_read_verify) {
 2326         __u8 args[4];
 2327         if (get_write_read_verify)
 2328             printf(" setting write-read-verify to %d\n", write_read_verify);
 2329         args[0] = ATA_OP_SETFEATURES;
 2330         args[1] = write_read_verify;
 2331         args[2] = write_read_verify ? 0x0b : 0x8b;
 2332         args[3] = 0;
 2333         if (do_drive_cmd(fd, args, 0)) {
 2334             err = errno;
 2335             perror(" HDIO_DRIVE_CMD:WRV failed");
 2336         }
 2337     }
 2338     if (set_wcache) {
 2339         if (get_wcache) {
 2340             printf(" setting drive write-caching to %d", wcache);
 2341             on_off(wcache);
 2342         }
 2343         if (!wcache)
 2344             err = flush_wcache(fd);
 2345         if (ioctl(fd, HDIO_SET_WCACHE, wcache)) {
 2346             __u8 setcache[4] = {ATA_OP_SETFEATURES,0,0,0};
 2347             setcache[2] = wcache ? 0x02 : 0x82;
 2348             if (do_drive_cmd(fd, setcache, 0)) {
 2349                 err = errno;
 2350                 perror(" HDIO_DRIVE_CMD(setcache) failed");
 2351             }
 2352         }
 2353         if (!wcache)
 2354             err = flush_wcache(fd);
 2355     }
 2356     if (set_standby) {
 2357         __u8 args[4] = {ATA_OP_SETIDLE,standby,0,0};
 2358         if (get_standby) {
 2359             printf(" setting standby to %u", standby);
 2360             interpret_standby();
 2361         }
 2362         if (do_drive_cmd(fd, args, 0)) {
 2363             err = errno;
 2364             perror(" HDIO_DRIVE_CMD(setidle) failed");
 2365         }
 2366     }
 2367     if (set_security) {
 2368         do_set_security(fd);
 2369     }
 2370     if (do_sanitize) {
 2371         if (do_sanitize > 1) {
 2372             confirm_i_know_what_i_am_doing("--sanitize", "This sanitize command destroys all user data.");
 2373         }
 2374         do_sanitize_cmd(fd);
 2375     }
 2376     if (do_dco_identify) {
 2377         __u16 *dco = get_dco_identify_data(fd, 0);
 2378         if (dco) {
 2379             if (dco_verify_checksum(dco) == (dco[255] >> 8))
 2380                 printf("DCO Checksum verified.\n");
 2381             else
 2382                 printf("DCO Checksum FAILED!\n");
 2383             dco_identify_print(dco);
 2384         }
 2385     }
 2386     if (do_dco_restore) {
 2387         __u8 args[4] = {ATA_OP_DCO,0,0xc0,0};
 2388         confirm_i_know_what_i_am_doing("--dco-restore", "You are trying to deliberately reset your drive configuration back to the factory defaults.\nThis may change the apparent capacity and feature set of the drive, making all data on it inaccessible.\nYou could lose *everything*.");
 2389         if (!quiet)
 2390             printf(" issuing DCO restore command\n");
 2391         if (do_drive_cmd(fd, args, 0)) {
 2392             err = errno;
 2393             perror(" HDIO_DRIVE_CMD(dco_restore) failed");
 2394         }
 2395     }
 2396     if (do_dco_freeze) {
 2397         __u8 args[4] = {ATA_OP_DCO,0,0xc1,0};
 2398         if (!quiet)
 2399             printf(" issuing DCO freeze command\n");
 2400         if (do_drive_cmd(fd, args, 0)) {
 2401             err = errno;
 2402             perror(" HDIO_DRIVE_CMD(dco_freeze) failed");
 2403         }
 2404     }
 2405     if (do_dco_setmax) {
 2406         get_identify_data(fd);
 2407         if (id) {
 2408             if (set_max_addr < get_lba_capacity(id))
 2409                 confirm_i_know_what_i_am_doing("--dco-setmax", "You have requested reducing the apparent size of the drive.\nThis is a BAD idea, and can easily destroy all of the drive's contents.");
 2410 
 2411             // set max sectors with DCO set command
 2412             if (!quiet)
 2413                 printf("issuing DCO set command (sectors = %llu)\n", set_max_addr);
 2414             do_dco_setmax_cmd(fd);
 2415 
 2416             // invalidate current IDENTIFY data
 2417             id = NULL; 
 2418         }
 2419     }
 2420     if (security_freeze) {
 2421         __u8 args[4] = {ATA_OP_SECURITY_FREEZE_LOCK,0,0,0};
 2422         if (!quiet)
 2423             printf(" issuing security freeze command\n");
 2424         if (do_drive_cmd(fd, args, 0)) {
 2425             err = errno;
 2426             perror(" HDIO_DRIVE_CMD(security_freeze) failed");
 2427         }
 2428     }
 2429     if (set_seagate) {
 2430         __u8 args[4] = {0xfb,0,0,0};
 2431         if (!quiet && get_seagate)
 2432             printf(" disabling Seagate auto powersaving mode\n");
 2433         if (do_drive_cmd(fd, args, 0)) {
 2434             err = errno;
 2435             perror(" HDIO_DRIVE_CMD(seagatepwrsave) failed");
 2436         }
 2437     }
 2438     if (set_busstate) {
 2439         if (!quiet && get_busstate)
 2440             printf(" setting bus state to %d (%s)\n", busstate, busstate_str(busstate));
 2441         if (ioctl(fd, HDIO_SET_BUSSTATE, busstate)) {
 2442             err = errno;
 2443             perror(" HDIO_SET_BUSSTATE failed");
 2444         }
 2445     }
 2446     if (set_max_sectors) {
 2447         if (!quiet && get_native_max_sectors)
 2448             printf(" setting max visible sectors to %llu (%s)\n", set_max_addr, set_max_permanent ? "permanent" : "temporary");
 2449         get_identify_data(fd);
 2450         if (id) {
 2451             if (set_max_addr < get_lba_capacity(id))
 2452                 confirm_i_know_what_i_am_doing("-Nnnnnn", "You have requested reducing the apparent size of the drive.\nThis is a BAD idea, and can easily destroy all of the drive's contents.");
 2453             err = do_set_max_sectors(fd, set_max_addr - 1, set_max_permanent);
 2454             id = NULL; /* invalidate existing identify data */
 2455         }
 2456     }
 2457     if (make_bad_sector) {
 2458         get_identify_data(fd);
 2459         if (id) {
 2460             confirm_i_know_what_i_am_doing("--make-bad-sector", "You are trying to deliberately corrupt a low-level sector on the media.\nThis is a BAD idea, and can easily result in total data loss.");
 2461             err = do_make_bad_sector(fd, make_bad_sector_addr, devname);
 2462         }
 2463     }
 2464 #ifdef FORMAT_AND_ERASE
 2465     if (format_track) {
 2466         confirm_i_know_what_i_am_doing("--format-track", "This flag is still under development and probably does not work correctly yet.\nYou are trying to deliberately destroy your device.\nThis is a BAD idea, and can easily result in total data loss.");
 2467         confirm_please_destroy_my_drive("--format-track", "This might destroy the drive and/or all data on it.");
 2468         err = do_format_track(fd, format_track_addr, devname);
 2469     }
 2470     if (erase_sectors) {
 2471         confirm_i_know_what_i_am_doing("--erase-sectors", "This flag is still under development and probably does not work correctly yet.\nYou are trying to deliberately destroy your device.\nThis is a BAD idea, and can easily result in total data loss.");
 2472         confirm_please_destroy_my_drive("--erase-sectors", "This might destroy the drive and/or all data on it.");
 2473         err = do_erase_sectors(fd, erase_sectors_addr, devname);
 2474     }
 2475 #endif /* FORMAT_AND_ERASE */
 2476     if (trim_sector_ranges_count) {
 2477         if (num_flags_processed > 1 || argc)
 2478             usage_help(13,EINVAL);
 2479         confirm_please_destroy_my_drive("--trim-sector-ranges", "This might destroy the drive and/or all data on it.");
 2480         do_trim_sector_ranges(fd, devname, trim_sector_ranges_count, trim_sector_ranges);
 2481     }
 2482     if (write_sector) {
 2483         if (num_flags_processed > 1 || argc)
 2484             usage_help(14,EINVAL);
 2485         confirm_i_know_what_i_am_doing("--write-sector", "You are trying to deliberately overwrite a low-level sector on the media.\nThis is a BAD idea, and can easily result in total data loss.");
 2486         err = do_write_sector(fd, write_sector_addr, devname);
 2487     }
 2488     if (do_fwdownload) {
 2489         if (num_flags_processed > 1 || argc)
 2490             usage_help(15,EINVAL);
 2491         abort_if_not_full_device (fd, 0, devname, "--fwdownload requires the raw device, not a partition.");
 2492         confirm_i_know_what_i_am_doing("--fwdownload", "This flag has not been tested with many drives to date.\nYou are trying to deliberately overwrite the drive firmware with the contents of the specified file.\nIf this fails, your drive could be toast.");
 2493         confirm_please_destroy_my_drive("--fwdownload", "This might destroy the drive and well as all of the data on it.");
 2494         get_identify_data(fd);
 2495         if (id) {
 2496             err = fwdownload(fd, id, fwpath, xfer_mode);
 2497             if (err)
 2498                 exit(err);
 2499         }
 2500     }
 2501     if (read_sector)
 2502         err = do_read_sector(fd, read_sector_addr, devname);
 2503     if (drq_hsm_error) {
 2504         get_identify_data(fd);
 2505         if (id) {
 2506             __u8 args[4] = {0,0,0,0};
 2507             args[0] = last_identify_op;
 2508             printf(" triggering \"stuck DRQ\" host state machine error\n");
 2509             flush_buffer_cache(fd);
 2510             sleep(1);
 2511             do_drive_cmd(fd, args, timeout_60secs);
 2512             err = errno;
 2513             perror("drq_hsm_error");
 2514             fprintf(stderr, "ata status=0x%02x ata error=0x%02x\n", args[0], args[1]);
 2515         }
 2516     }
 2517     id = NULL; /* force re-IDENTIFY in case something above modified settings */
 2518     if (get_hitachi_temp) {
 2519         __u8 args[4] = {0xf0,0,0x01,0}; /* "Sense Condition", vendor-specific */
 2520         if (do_drive_cmd(fd, args, 0)) {
 2521             err = errno;
 2522             perror(" HDIO_DRIVE_CMD(hitachisensecondition) failed");
 2523         } else {
 2524             printf(" drive temperature (celsius) is:  ");
 2525             if (args[2]==0)
 2526                 printf("under -20");
 2527             else if (args[2]==0xFF)
 2528                 printf("over 107");
 2529             else
 2530                 printf("%d", args[2]/2-20);
 2531             printf("\n drive temperature in range:  %s\n", YN(!(args[1]&0x10)) );
 2532         }
 2533     }
 2534     if (do_defaults || get_mult || do_identity) {
 2535         multcount = -1;
 2536         err = 0;
 2537         if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) {
 2538             err = errno;
 2539             get_identify_data(fd);
 2540             if (id) {
 2541                 err = 0;
 2542                 if ((id[59] & 0xff00) == 0x100)
 2543                     multcount = id[59] & 0xff;
 2544                 else
 2545                     multcount = 0;
 2546             }
 2547             if (err && get_mult) {
 2548                 errno = err;
 2549                 perror(" HDIO_GET_MULTCOUNT failed");
 2550             }
 2551         }
 2552         if (!err && (do_defaults || get_mult)) {
 2553             printf(" multcount     = %2ld", multcount);
 2554             on_off(multcount);
 2555         }
 2556     }
 2557     if (do_defaults || get_io32bit) {
 2558         if (0 == ioctl(fd, HDIO_GET_32BIT, &parm)) {
 2559             printf(" IO_support    =%3ld (", parm);
 2560             switch (parm) {
 2561                 case 0: printf("default) \n");
 2562                     break;
 2563                 case 2: printf("16-bit)\n");
 2564                     break;
 2565                 case 1: printf("32-bit)\n");
 2566                     break;
 2567                 case 3: printf("32-bit w/sync)\n");
 2568                     break;
 2569                 case 8: printf("Request-Queue-Bypass)\n");
 2570                     break;
 2571                 default:printf("\?\?\?)\n");
 2572             }
 2573         } else if (get_io32bit) {
 2574             err = errno;
 2575             perror(" HDIO_GET_32BIT failed");
 2576         }
 2577     }
 2578     if (do_defaults || get_unmask) {
 2579         if (0 == ioctl(fd, HDIO_GET_UNMASKINTR, &parm)) {
 2580             printf(" unmaskirq     = %2ld", parm);
 2581             on_off(parm);
 2582         } else if (get_unmask) {
 2583             err = errno;
 2584             perror(" HDIO_GET_UNMASKINTR failed");
 2585         }
 2586     }
 2587 
 2588     if (do_defaults || get_dma) {
 2589         if (0 == ioctl(fd, HDIO_GET_DMA, &parm)) {
 2590             printf(" using_dma     = %2ld", parm);
 2591             if (parm == 8)
 2592                 printf(" (DMA-Assisted-PIO)\n");
 2593             else
 2594                 on_off(parm);
 2595         } else if (get_dma) {
 2596             err = errno;
 2597             perror(" HDIO_GET_DMA failed");
 2598         }
 2599     }
 2600     if (get_dma_q) {
 2601         err = sysfs_get_attr(fd, "device/queue_depth", "%u", &dma_q, NULL, 1);
 2602         if (!err)
 2603             printf(" queue_depth   = %2u\n", dma_q);
 2604     }
 2605     if (do_defaults || get_keep) {
 2606         if (0 == ioctl(fd, HDIO_GET_KEEPSETTINGS, &parm)) {
 2607             printf(" keepsettings  = %2ld", parm);
 2608             on_off(parm);
 2609         } else if (get_keep) {
 2610             err = errno;
 2611             perror(" HDIO_GET_KEEPSETTINGS failed");
 2612         }
 2613     }
 2614     if (get_nowerr) {
 2615         if (ioctl(fd, HDIO_GET_NOWERR, &parm)) {
 2616             err = errno;
 2617             perror(" HDIO_GET_NOWERR failed");
 2618         } else {
 2619             printf(" nowerr        = %2ld", parm);
 2620             on_off(parm);
 2621         }
 2622     }
 2623     if (do_defaults || get_readonly) {
 2624         if (ioctl(fd, BLKROGET, &parm)) {
 2625             err = errno;
 2626             perror(" BLKROGET failed");
 2627         } else {
 2628             printf(" readonly      = %2ld", parm);
 2629             on_off(parm);
 2630         }
 2631     }
 2632     if (do_defaults || get_fsreadahead) {
 2633         if (ioctl(fd, BLKRAGET, &parm)) {
 2634             err = errno;
 2635             perror(" BLKRAGET failed");
 2636         } else {
 2637             printf(" readahead     = %2ld", parm);
 2638             on_off(parm);
 2639         }
 2640     }
 2641     if (do_defaults || get_geom) {
 2642         __u32 cyls = 0, heads = 0, sects = 0;
 2643         __u64 start_lba = 0, nsectors = 0;
 2644         err = get_dev_geometry (fd, &cyls, &heads, &sects, &start_lba, &nsectors);
 2645         if (!err) {
 2646             printf(" geometry      = %u/%u/%u, sectors = %lld, start = ", cyls, heads, sects, nsectors);
 2647             if (start_lba == START_LBA_UNKNOWN)
 2648                 printf("unknown\n");
 2649             else
 2650                 printf("%lld\n", start_lba);
 2651         }
 2652     }
 2653     if (get_wdidle3) {
 2654         unsigned char timeout = 0;
 2655         err = wdidle3_get_timeout(fd, &timeout);
 2656         if (!err) {
 2657             printf(" wdidle3      = ");
 2658             wdidle3_print_timeout(timeout);
 2659             putchar('\n');
 2660         }
 2661     }
 2662     if (get_powermode) {
 2663         __u8 args[4] = {ATA_OP_CHECKPOWERMODE1,0,0,0};
 2664         const char *state = "unknown";
 2665         if (do_drive_cmd(fd, args, 0)
 2666          && (args[0] = ATA_OP_CHECKPOWERMODE2) /* (single =) try again with 0x98 */
 2667          && do_drive_cmd(fd, args, 0)) {
 2668             err = errno;
 2669         } else {
 2670             switch (args[2]) {
 2671                 case 0x00: state = "standby";       break;
 2672                 case 0x40: state = "NVcache_spindown";  break;
 2673                 case 0x41: state = "NVcache_spinup";    break;
 2674                 case 0x80: state = "idle";      break;
 2675                 case 0xff: state = "active/idle";   break;
 2676             }
 2677         }
 2678         printf(" drive state is:  %s\n", state);
 2679     }
 2680     if (do_identity) {
 2681         __u16 id2[256];
 2682 
 2683         if (!ioctl(fd, HDIO_GET_IDENTITY, id2)) {
 2684             if (multcount != -1) {
 2685                 id2[59] = multcount | 0x100;
 2686             } else {
 2687                 id2[59] &= ~0x100;
 2688             }
 2689             dump_identity(id2);
 2690         } else if (errno == -ENOMSG) {
 2691             printf(" no identification info available\n");
 2692         } else {
 2693             err = errno;
 2694             perror(" HDIO_GET_IDENTITY failed");
 2695         }
 2696     }
 2697     if (do_IDentity) {
 2698         get_identify_data(fd);
 2699         if (id) {
 2700             if (do_IDentity == 2) {
 2701                 dump_sectors(id, 1, 1, 512);
 2702             } else if (do_IDentity == 3) {
 2703                 /* Write raw binary IDENTIFY DEVICE data to the specified file */
 2704                 int rfd = open(raw_identify_path, O_WRONLY|O_TRUNC|O_CREAT, 0644);
 2705                 if (rfd == -1) {
 2706                     err = errno;
 2707                     perror(raw_identify_path);
 2708                     exit(err);
 2709                 }
 2710                 err = write(rfd, id, 0x200);
 2711                 if (err == -1) {
 2712                     err = errno;
 2713                     perror(raw_identify_path);
 2714                     exit(err);
 2715                 } else if (err != 0x200) {
 2716                     fprintf(stderr, "Error writing IDENTIFY DEVICE data to \"%s\"\n", raw_identify_path);
 2717                     exit(EIO);
 2718                 } else {
 2719                     fprintf(stderr, "Wrote IDENTIFY DEVICE data to \"%s\"\n", raw_identify_path);
 2720                     close(rfd);
 2721                 }
 2722             } else {
 2723                 identify(fd, (void *)id);
 2724             }
 2725         }
 2726     }
 2727     if (get_lookahead) {
 2728         get_identify_data(fd);
 2729         if (id) {
 2730             int supported = id[82] & 0x0040;
 2731             if (supported) {
 2732                 lookahead = !!(id[85] & 0x0040);
 2733                 printf(" look-ahead    = %2d", lookahead);
 2734                 on_off(lookahead);
 2735             } else {
 2736                 printf(" look-ahead    = not supported\n");
 2737             }
 2738         }
 2739     }
 2740     if (get_wcache) {
 2741         get_identify_data(fd);
 2742         if (id) {
 2743             int supported = id[82] & 0x0020;
 2744             if (supported) {
 2745                 wcache = !!(id[85] & 0x0020);
 2746                 printf(" write-caching = %2d", wcache);
 2747                 on_off(wcache);
 2748             } else {
 2749                 printf(" write-caching = not supported\n");
 2750             }
 2751         }
 2752     }
 2753     if (get_apmmode) {
 2754         get_identify_data(fd);
 2755         if (id) {
 2756             printf(" APM_level  = ");
 2757             if ((id[83] & 0xc008) == 0x4008) {
 2758                 if (id[86] & 0x0008)
 2759                     printf("%u\n", id[91] & 0xff);
 2760                 else
 2761                     printf("off\n");
 2762             } else
 2763                 printf("not supported\n");
 2764         }
 2765     }
 2766     if (get_acoustic) {
 2767         get_identify_data(fd);
 2768         if (id) {
 2769             int supported = id[83] & 0x200;
 2770             if (supported) 
 2771                 printf(" acoustic      = %2u (128=quiet ... 254=fast)\n", id[94] & 0xff);
 2772             else
 2773                 printf(" acoustic      = not supported\n");
 2774         }
 2775     }
 2776     if (get_write_read_verify) {
 2777         get_identify_data(fd);
 2778         if (id) {
 2779                 int supported = id[119] & 0x2;
 2780                 if (supported)
 2781                     printf(" write-read-verify = %2u\n", id[120] & 0x2);
 2782                 else
 2783                     printf(" write-read-verify = not supported\n");
 2784         }
 2785     }
 2786     if (get_busstate) {
 2787         if (ioctl(fd, HDIO_GET_BUSSTATE, &parm)) {
 2788             err = errno;
 2789             perror(" HDIO_GET_BUSSTATE failed");
 2790         } else {
 2791             printf(" busstate      = %2ld (%s)\n", parm, busstate_str(parm));
 2792         }
 2793     }
 2794     if (get_native_max_sectors) {
 2795         get_identify_data(fd);
 2796         if (id) {
 2797             __u64 visible = get_lba_capacity(id);
 2798             __u64 native  = do_get_native_max_sectors(fd);
 2799             if (!native) {
 2800                 err = errno;
 2801             } else {
 2802                 printf(" max sectors   = %llu/%llu", visible, native);
 2803                 if (visible < native){
 2804                     if (SUPPORTS_AMAX_ADDR(id)) {
 2805                         printf(", ACCESSIBLE MAX ADDRESS enabled\n");
 2806                         printf("Power cycle your device after every ACCESSIBLE MAX ADDRESS\n");
 2807                     }
 2808                     else
 2809                         printf(", HPA is enabled\n");
 2810                 }
 2811                 else if (visible == native){
 2812                     if (SUPPORTS_AMAX_ADDR(id))
 2813                         printf(", ACCESSIBLE MAX ADDRESS disabled\n");
 2814                     else
 2815                         printf(", HPA is disabled\n");
 2816                 }
 2817                 else {
 2818                     __u16 *dco = get_dco_identify_data(fd, 1);
 2819                     if (dco) {
 2820                         __u64 dco_max = dco[5];
 2821                         dco_max = ((((__u64)dco[5]) << 32) | ((__u64)dco[4] << 16) | (__u64)dco[3]) + 1;
 2822                         printf("(%llu?)", dco_max);
 2823                     }
 2824                     printf(", HPA setting seems invalid");
 2825                     if ((native & 0xffffff000000ull) == 0)
 2826                         printf(" (buggy kernel device driver?)");
 2827                     putchar('\n');
 2828                     }
 2829                 }
 2830             }
 2831         
 2832 
 2833     }   
 2834     if (do_ctimings)
 2835         time_cache(fd);
 2836     if (do_flush_wcache)
 2837         err = flush_wcache(fd);
 2838     if (do_timings)
 2839         err = time_device(fd);
 2840     if (do_flush)
 2841         flush_buffer_cache(fd);
 2842     if (set_reread_partn) {
 2843         if (get_reread_partn)
 2844             printf(" re-reading partition table\n");
 2845         if (ioctl(fd, BLKRRPART, NULL)) {
 2846             err = errno;
 2847             perror(" BLKRRPART failed");
 2848         }
 2849     }
 2850     if (set_idleimmediate) {
 2851         __u8 args[4] = {ATA_OP_IDLEIMMEDIATE,0,0,0};
 2852         if (get_idleimmediate)
 2853             printf(" issuing idle_immediate command\n");
 2854         if (do_drive_cmd(fd, args, 0)) {
 2855             err = errno;
 2856             perror(" HDIO_DRIVE_CMD(idle_immediate) failed");
 2857         }
 2858     }
 2859     if (set_standbynow) {
 2860         __u8 args1[4] = {ATA_OP_STANDBYNOW1,0,0,0};
 2861         __u8 args2[4] = {ATA_OP_STANDBYNOW2,0,0,0};
 2862         if (get_standbynow)
 2863             printf(" issuing standby command\n");
 2864         if (do_drive_cmd(fd, args1, 0) && do_drive_cmd(fd, args2, 0)) {
 2865             err = errno;
 2866             perror(" HDIO_DRIVE_CMD(standby) failed");
 2867         }
 2868     }
 2869     if (set_idleunload) {
 2870         if (get_idleunload)
 2871             printf(" issuing idle_immediate_unload command\n");
 2872         err = do_idleunload(fd, devname);
 2873     }
 2874     if (set_sleepnow) {
 2875         __u8 args1[4] = {ATA_OP_SLEEPNOW1,0,0,0};
 2876         __u8 args2[4] = {ATA_OP_SLEEPNOW2,0,0,0};
 2877         if (get_sleepnow)
 2878             printf(" issuing sleep command\n");
 2879         if (do_drive_cmd(fd, args1, 0) && do_drive_cmd(fd, args2, 0)) {
 2880             err = errno;
 2881             perror(" HDIO_DRIVE_CMD(sleep) failed");
 2882         }
 2883     }
 2884     if (set_doreset) {
 2885         if (get_doreset)
 2886             printf(" resetting drive\n");
 2887         if (ioctl(fd, HDIO_DRIVE_RESET, NULL)) {
 2888             err = errno;
 2889             perror(" HDIO_DRIVE_RESET failed");
 2890         }
 2891     }
 2892     close (fd);
 2893     if (err)
 2894         exit (err);
 2895 }
 2896 
 2897 #define GET_XFERMODE(flag, num)                 \
 2898     do {                            \
 2899         char *tmpstr = name;                \
 2900         tmpstr[0] = '\0';               \
 2901         if (!*argp && argc && isalnum(**argv))      \
 2902             argp = *argv++, --argc;         \
 2903         while (isalnum(*argp) && (tmpstr - name) < 31) {\
 2904             tmpstr[0] = *argp++;            \
 2905             tmpstr[1] = '\0';           \
 2906             ++tmpstr;               \
 2907         }                       \
 2908         num = translate_xfermode(name);         \
 2909         if (num == -1)                  \
 2910             flag = 0;               \
 2911         else                        \
 2912             flag = 1;               \
 2913     } while (0)
 2914 
 2915 static int fromhex (__u8 c)
 2916 {
 2917     if (c >= '0' && c <= '9')
 2918         return (c - '0');
 2919     if (c >= 'a' && c <= 'f')
 2920         return 10 + (c - 'a');
 2921     if (c >= 'A' && c <= 'F')
 2922         return 10 + (c - 'A');
 2923     fprintf(stderr, "bad char: '%c' 0x%02x\n", c, c);
 2924     exit(EINVAL);
 2925 }
 2926 
 2927 static int ishex (char c)
 2928 {
 2929     return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
 2930 }
 2931 
 2932 static void
 2933 identify_from_stdin (void)
 2934 {
 2935     __u16 sbuf[512];
 2936     int err, wc = 0;
 2937 
 2938     do {
 2939         int digit;
 2940         int d[4];
 2941 
 2942         if (ishex(d[digit=0] = getchar())
 2943          && ishex(d[++digit] = getchar())
 2944          && ishex(d[++digit] = getchar())
 2945          && ishex(d[++digit] = getchar())) {
 2946             sbuf[wc] = (fromhex(d[0]) << 12) | (fromhex(d[1]) << 8) | (fromhex(d[2]) << 4) | fromhex(d[3]);
 2947             ++wc;
 2948         } else if (d[digit] == EOF) {
 2949             goto eof;
 2950         } else if (wc == 0) {
 2951             /* skip over leading lines of cruft */
 2952             while (d[digit] != '\n') {
 2953                 if (d[digit] == EOF)
 2954                     goto eof;
 2955                 d[digit=0] = getchar();
 2956             };
 2957         }
 2958     } while (wc < 256);
 2959     putchar('\n');
 2960     id = sbuf;  /* necessary for --Istdin:  identify() needs id[] */
 2961     identify(-1, sbuf);
 2962     return;
 2963 eof:
 2964     err = errno;
 2965     fprintf(stderr, "read only %u/256 IDENTIFY words from stdin: %s\n", wc, strerror(err));
 2966     exit(err);
 2967 }
 2968 
 2969 static void
 2970 numeric_parm (char c, const char *name, int *val, int *setparm, int *getparm, int min, int max, int set_only)
 2971 {
 2972     int got_digit = 0;
 2973 
 2974     *val = 0;
 2975     *getparm = noisy;
 2976     noisy = 1;
 2977     if (!*argp && argc && isdigit(**argv))
 2978         argp = *argv++, --argc;
 2979     while (isdigit(*argp)) {
 2980         *setparm = 1;
 2981         *val = (*val * 10) + (*argp++ - '0');
 2982         got_digit = 1;
 2983     }
 2984     if ((set_only && !got_digit) || *val < min || *val > max) {
 2985         fprintf(stderr, "  -%c: bad/missing %s value (%d..%d)\n", c, name, min, max);
 2986         exit(EINVAL);
 2987     }
 2988 }
 2989 
 2990 #define NUMERIC_PARM(CH,NAME,VAR,MIN,MAX,GETSET) numeric_parm(CH,NAME,&VAR,&set_##VAR,&get_##VAR,MIN,MAX,GETSET)
 2991 #define GET_SET_PARM(CH,NAME,VAR,MIN,MAX) CH:NUMERIC_PARM(CH,NAME,VAR,MIN,MAX,0);break
 2992 #define     SET_PARM(CH,NAME,VAR,MIN,MAX) CH:NUMERIC_PARM(CH,NAME,VAR,MIN,MAX,1);break
 2993 #define     SET_FLAG1(VAR)                get_##VAR=noisy;noisy=1;set_##VAR=1
 2994 #define     SET_FLAG(CH,VAR)              CH:SET_FLAG1(VAR);break
 2995 #define      DO_FLAG(CH,VAR)              CH:VAR=1;noisy=1;break
 2996 #define    INCR_FLAG(CH,VAR)              CH:VAR++;noisy=1;break
 2997 
 2998 static void get_security_password (int handle_NULL)
 2999 {
 3000     unsigned int maxlen = sizeof(security_password) - 1;
 3001     unsigned int binary_passwd = 0;
 3002 
 3003     if (security_prompt_for_password) {
 3004         const char *passwd = getpass("Please enter the drive password: ");
 3005         if (passwd == NULL) {
 3006             fprintf(stderr, "failed to read a password, errno=%d\n", errno);
 3007             exit(EINVAL);
 3008         }
 3009         if (strlen(passwd) >= sizeof(security_password)) {
 3010             fprintf(stderr, "password is too long (%u chars max)\n", (int)sizeof(security_password) - 1);
 3011             exit(EINVAL);
 3012         }
 3013         strcpy(security_password, passwd);
 3014         return;
 3015     }
 3016 
 3017     argp = *argv++, --argc;
 3018     if (!argp || argc < 1) {
 3019         fprintf(stderr, "missing PASSWD\n");
 3020         exit(EINVAL);
 3021     }
 3022     memset(security_password, 0, maxlen + 1);
 3023     if (0 == strncmp(argp, "hex:", 4)) {
 3024         argp += 4;
 3025         if (strlen(argp) != (maxlen * 2)) {
 3026             fprintf(stderr, "invalid PASSWD length (hex string must be exactly %d chars)\n", maxlen*2);
 3027             exit(EINVAL);
 3028         }
 3029         char *cur = security_password;
 3030         while (*argp) {
 3031             int d[2];
 3032             d[0] = fromhex(*argp++);
 3033             d[1] = fromhex(*argp++);
 3034             *(cur++) = d[0] << 4 | d[1];
 3035         }
 3036         binary_passwd = 1;
 3037     } else if (strlen(argp) > maxlen) {
 3038         fprintf(stderr, "PASSWD too long (must be %d chars max)\n", maxlen);
 3039         exit(EINVAL);
 3040     } else if (!handle_NULL || strcmp(argp, "NULL")) {
 3041         strcpy(security_password, argp);
 3042     }
 3043     printf("security_password:");
 3044     if (!binary_passwd) {
 3045         printf(" \"%s\"\n", security_password);
 3046     } else {
 3047         unsigned int i;
 3048         for (i = 0; i < maxlen; ++i) {
 3049             unsigned char c = security_password[i];
 3050             printf(" %02x", c);
 3051         }
 3052         putchar('\n');
 3053     }
 3054     while (*argp)
 3055         ++argp;
 3056 }
 3057 
 3058 static void get_ow_pattern (void)
 3059 {
 3060     unsigned int maxlen = sizeof(ow_pattern);
 3061 
 3062     argp = *argv++, --argc;
 3063     if (!argp || argc < 1) {
 3064         fprintf(stderr, "missing PATTERN\n");
 3065         exit(EINVAL);
 3066     }
 3067     if (0 == strncmp(argp, "hex:", 4)) {
 3068         argp += 4;
 3069         if (strlen(argp) != (maxlen * 2)) {
 3070             fprintf(stderr, "invalid PATTERN length (hex string must be exactly %d chars)\n", maxlen*2);
 3071             exit(EINVAL);
 3072         }
 3073         int i = 28;
 3074         ow_pattern = 0;
 3075         while (*argp) {
 3076             ow_pattern |= fromhex(*argp++) << i;
 3077             i -= 4;
 3078         }
 3079 
 3080     } else {
 3081         fprintf(stderr, "invalid PATTERN format (must be hex:XXXXXXXX)\n");
 3082         exit(EINVAL);
 3083     }
 3084 }
 3085 
 3086 static const char *sector_size_emsg = "sector size out of range";
 3087 static const char *lba_emsg = "bad/missing sector value";
 3088 static const char *count_emsg = "bad/missing sector count";
 3089 static const __u64 lba_limit = (1ULL << 48) - 1;
 3090 
 3091 static int
 3092 get_u64_parm (int optional, const char flag_c, int *flag_p, __u64 *value_p,
 3093         unsigned int min_value, __u64 limit, const char *eprefix, const char *emsg)
 3094 {
 3095     int got_value = 0;
 3096     __u64 value = *value_p;
 3097     char *endp = NULL;
 3098 
 3099     if (!*argp && argc && (isdigit(**argv) || (flag_p && flag_c == **argv)))
 3100         argp = *argv++, --argc;
 3101 
 3102     if (flag_p) {
 3103         *flag_p = 0;
 3104         if (*argp == flag_c) {
 3105             *flag_p = 1;
 3106             argp++;
 3107         }
 3108     }
 3109 
 3110     errno = 0;
 3111     value = strtoll(argp, &endp, 0);
 3112     if (errno != 0 || (endp != argp && ((__s64)value < (__s64)min_value || value > limit))) {
 3113         fprintf(stderr, "  %s: %s\n", eprefix, emsg);
 3114         exit(EINVAL);
 3115     }
 3116     if (endp != argp) {
 3117         got_value = 1;
 3118         *value_p = value;
 3119         argp = endp;
 3120     }
 3121     if (!optional && !got_value) {
 3122         fprintf(stderr, "  %s: %s\n", eprefix, emsg);
 3123         exit(EINVAL);
 3124     }
 3125     return got_value;
 3126 }
 3127 
 3128 static void
 3129 get_set_max_sectors_parms (void)
 3130 {
 3131     get_native_max_sectors = noisy;
 3132     noisy = 1;
 3133     set_max_sectors = get_u64_parm(1, 'p', &set_max_permanent, &set_max_addr, 1, lba_limit, "-N", lba_emsg);
 3134 }
 3135 
 3136 static void
 3137 get_set_max_sectors_parms_dco (void)
 3138 {
 3139     do_dco_setmax = get_u64_parm(0, 0, NULL, &set_max_addr, 1, lba_limit, "--dco-setmax", lba_emsg);
 3140 }
 3141 
 3142 static int
 3143 handle_standalone_longarg (char *name)
 3144 {
 3145     if (num_flags_processed) {
 3146         if (verbose)
 3147             fprintf(stderr, "%s: num_flags_processed == %d\n", __func__, num_flags_processed);
 3148         usage_help(1,EINVAL);
 3149     }
 3150     /* --Istdin is special: no filename arg(s) wanted here */
 3151     if (0 == strcasecmp(name, "Istdin")) {
 3152         if (argc > 0) {
 3153             if (verbose)
 3154                 fprintf(stderr, "%s: argc(%d) > 0\n", __func__, argc);
 3155             usage_help(2,EINVAL);
 3156         }
 3157         identify_from_stdin();
 3158         exit(0);
 3159     }
 3160     if (0 == strcasecmp(name, "dco-restore")) {
 3161         do_dco_restore = 1;
 3162     } else if (0 == strcasecmp(name, "dco-setmax")) {
 3163         get_set_max_sectors_parms_dco();
 3164     } else if (0 == strcasecmp(name, "security-help")) {
 3165         security_help(0);
 3166         exit(0);
 3167     } else if (0 == strcasecmp(name, "security-unlock")) {
 3168         set_security = 1;
 3169         security_command = ATA_OP_SECURITY_UNLOCK;
 3170         get_security_password(1);
 3171     } else if (0 == strcasecmp(name, "security-set-pass")) {
 3172         set_security = 1;
 3173         security_command = ATA_OP_SECURITY_SET_PASS;
 3174         get_security_password(1);
 3175     } else if (0 == strcasecmp(name, "security-disable")) {
 3176         set_security = 1;
 3177         security_command = ATA_OP_SECURITY_DISABLE;
 3178         get_security_password(1);
 3179     } else if (0 == strcasecmp(name, "security-erase")) {
 3180         set_security = 1;
 3181         security_command = ATA_OP_SECURITY_ERASE_UNIT;
 3182         get_security_password(1);
 3183     } else if (0 == strcasecmp(name, "security-erase-enhanced")) {
 3184         set_security = 1;
 3185         enhanced_erase = 1;
 3186         security_command = ATA_OP_SECURITY_ERASE_UNIT;
 3187         get_security_password(1);
 3188     } else if (0 == strcasecmp(name, "sanitize-status")) {
 3189         do_sanitize = 1;
 3190         sanitize_feature = SANITIZE_STATUS_EXT;
 3191     } else if (0 == strcasecmp(name, "sanitize-freeze-lock")) {
 3192         do_sanitize = 1;
 3193         sanitize_feature = SANITIZE_FREEZE_LOCK_EXT;
 3194     } else if (0 == strcasecmp(name, "sanitize-antifreeze-lock")) {
 3195         do_sanitize = 1;
 3196         sanitize_feature = SANITIZE_ANTIFREEZE_LOCK_EXT;
 3197     } else if (0 == strcasecmp(name, "sanitize-block-erase")) {
 3198         do_sanitize = 2;
 3199         sanitize_feature = SANITIZE_BLOCK_ERASE_EXT;
 3200     } else if (0 == strcasecmp(name, "sanitize-crypto-scramble")) {
 3201         do_sanitize = 2;
 3202         sanitize_feature = SANITIZE_CRYPTO_SCRAMBLE_EXT;
 3203     } else if (0 == strcasecmp(name, "sanitize-overwrite")) {
 3204         do_sanitize = 2;
 3205         get_ow_pattern();
 3206         sanitize_feature = SANITIZE_OVERWRITE_EXT;
 3207     }
 3208     else {
 3209         fprintf(stderr, "%s: unknown flag\n", name);
 3210         exit(EINVAL);
 3211         //usage_help(3,EINVAL);
 3212     }
 3213     return 1;  // no more flags allowed
 3214 }
 3215 
 3216 static void
 3217 get_filename_parm (char **result, const char *emsg)
 3218 {
 3219     if (!*argp && argc)
 3220         argp = *argv++, --argc;
 3221     if (!argp || !*argp) {
 3222         fprintf(stderr, "  %s: bad/missing filename parameter\n", emsg);
 3223         exit(EINVAL);
 3224     }
 3225     *result = argp;
 3226     argp += strlen(argp);
 3227     // if (argc) argp = *argv++, --argc;
 3228 }
 3229 
 3230 static void
 3231 do_fallocate (const char *name)
 3232 {
 3233     char *path;
 3234     __u64 blkcount;
 3235 
 3236     get_u64_parm(0, 0, NULL, &blkcount, 0, (1ULL << 53), name, "bad/missing block-count");
 3237     get_filename_parm(&path, name);
 3238     if (num_flags_processed || argc)
 3239         usage_help(4,EINVAL);
 3240     exit(do_fallocate_syscall(path, blkcount * 1024));
 3241 }
 3242 
 3243 static void
 3244 do_fibmap_file (const char *name)
 3245 {
 3246     int err;
 3247     char *path;
 3248 
 3249     get_filename_parm(&path, name);
 3250     if (num_flags_processed || argc)
 3251         usage_help(5,EINVAL);
 3252     err = do_filemap(path);
 3253     exit(err);
 3254 }
 3255 
 3256 static int
 3257 get_longarg (void)
 3258 {
 3259     char *name = argp;
 3260 
 3261     while (*argp)
 3262         ++argp;
 3263     if (0 == strcasecmp(name, "verbose")) {
 3264         verbose = 1;
 3265         --num_flags_processed;  /* doesn't count as an action flag */
 3266     } else if (0 == strcasecmp(name, "prefer-ata12")) {
 3267         prefer_ata12 = 1;
 3268         --num_flags_processed;  /* doesn't count as an action flag */
 3269     } else if (0 == strcasecmp(name, "offset")) {
 3270         set_timings_offset = 1;
 3271         get_u64_parm(0, 0, NULL, &timings_offset, 0, ~0, name, "GB offset for -t flag");
 3272         timings_offset *= 0x40000000ULL;
 3273     } else if (0 == strcasecmp(name, "yes-i-know-what-i-am-doing")) {
 3274         i_know_what_i_am_doing = 1;
 3275         --num_flags_processed;  /* doesn't count as an action flag */
 3276     } else if (0 == strcasecmp(name, "please-destroy-my-drive")) {
 3277         please_destroy_my_drive = 1;
 3278         --num_flags_processed;  /* doesn't count as an action flag */
 3279     } else if (0 == strcasecmp(name, "direct")) {
 3280         open_flags |= O_DIRECT;
 3281         --num_flags_processed;  /* doesn't count as an action flag */
 3282     } else if (0 == strcasecmp(name, "sanitize-overwrite-passes")) {
 3283         get_u64_parm(0, 0, NULL, &sanitize_overwrite_passes, 0, 7, name, "Number of passes must be in range 0..7");
 3284         --num_flags_processed;  /* doesn't count as an action flag */
 3285     } else if (0 == strcasecmp(name, "drq-hsm-error")) {
 3286         drq_hsm_error = 1;
 3287     } else if (0 == strcasecmp(name, "dco-freeze")) {
 3288         do_dco_freeze = 1;
 3289     } else if (0 == strcasecmp(name, "dco-identify")) {
 3290         do_dco_identify = 1;
 3291     } else if (0 == strcasecmp(name, "fallocate")) {
 3292         do_fallocate(name);
 3293     } else if (0 == strcasecmp(name, "fibmap")) {
 3294         do_fibmap_file(name);
 3295     } else if (0 == strcasecmp(name, "fwdownload-mode3")) {
 3296         get_filename_parm(&fwpath, name);
 3297         do_fwdownload = 1;
 3298         xfer_mode = 3;
 3299     } else if (0 == strcasecmp(name, "fwdownload-modee")) {
 3300         get_filename_parm(&fwpath, name);
 3301         do_fwdownload = 1;
 3302         xfer_mode = 0xe;
 3303     } else if (0 == strcasecmp(name, "fwdownload-modee-max")) {
 3304         get_filename_parm(&fwpath, name);
 3305         do_fwdownload = 1;
 3306         xfer_mode = 0xe0;
 3307     } else if (0 == strcasecmp(name, "fwdownload-mode3-max")) {
 3308         get_filename_parm(&fwpath, name);
 3309         do_fwdownload = 1;
 3310         xfer_mode = 0x30;
 3311     } else if (0 == strcasecmp(name, "fwdownload-mode7")) {
 3312         get_filename_parm(&fwpath, name);
 3313         do_fwdownload = 1;
 3314         xfer_mode = 7;
 3315     } else if (0 == strcasecmp(name, "fwdownload")) {
 3316         get_filename_parm(&fwpath, name);
 3317         do_fwdownload = 1;
 3318         xfer_mode = 0;
 3319     } else if (0 == strcasecmp(name, "idle-immediate")) {
 3320         SET_FLAG1(idleimmediate);
 3321     } else if (0 == strcasecmp(name, "idle-unload")) {
 3322         SET_FLAG1(idleunload);
 3323     } else if (0 == strcasecmp(name, "make-bad-sector")) {
 3324         make_bad_sector = 1;
 3325         get_u64_parm(0, 'f', &make_bad_sector_flagged, &make_bad_sector_addr, 0, lba_limit, name, lba_emsg);
 3326 #ifdef FORMAT_AND_ERASE
 3327     } else if (0 == strcasecmp(name, "format-track")) {
 3328         format_track = 1;
 3329         get_u64_parm(0, 0, NULL, &format_track_addr, 0, lba_limit, name, lba_emsg);
 3330     } else if (0 == strcasecmp(name, "erase-sectors")) {
 3331         erase_sectors = 1;
 3332         get_u64_parm(0, 0, NULL, &erase_sectors_addr, 0, lba_limit, name, lba_emsg);
 3333 #endif
 3334     } else if (0 == strcasecmp(name, SET_SECTOR_SIZE)) {
 3335         if (get_u64_parm(0, 0, NULL, &new_sector_size, 0x200, 0x1080, "--" SET_SECTOR_SIZE, sector_size_emsg))
 3336             do_set_sector_size = 1;
 3337     } else if (0 == strcasecmp(name, "trim-sector-ranges-stdin")) {
 3338         trim_from_stdin = 1;
 3339     } else if (0 == strcasecmp(name, "trim-sector-ranges")) {
 3340         int i, optional = 0, max_ranges = argc;
 3341         trim_sector_ranges = malloc(sizeof(struct sector_range_s) * max_ranges);
 3342         if (!trim_sector_ranges) {
 3343             int err = errno;
 3344             perror("malloc()");
 3345             exit(err);
 3346         }
 3347         open_flags |= O_RDWR;
 3348         for (i = 0; i < max_ranges; ++i) {
 3349             char err_prefix[64];
 3350             struct sector_range_s *p = &trim_sector_ranges[i];
 3351             sprintf(err_prefix, "%s[%u]", name, i);
 3352             if (!get_u64_parm(optional, 0, NULL, &(p->lba), 0, lba_limit, err_prefix, lba_emsg))
 3353                 break;
 3354             if (*argp++ != ':' || !isdigit(*argp)) {
 3355                 fprintf(stderr, "%s: %s\n", err_prefix, count_emsg);
 3356                 exit(EINVAL);
 3357             }
 3358             get_u64_parm(0, 0, NULL, &(p->nsectors), 1, 0xffff, err_prefix, count_emsg);
 3359             optional = 1;
 3360             trim_sector_ranges_count = i + 1;
 3361         }
 3362     } else if (0 == strcasecmp(name, "write-sector") || 0 == strcasecmp(name, "repair-sector")) {
 3363         write_sector = 1;
 3364         get_u64_parm(0, 0, NULL, &write_sector_addr, 0, lba_limit, name, lba_emsg);
 3365     } else if (0 == strcasecmp(name, "read-sector")) {
 3366         read_sector = 1;
 3367         get_u64_parm(0, 0, NULL, &read_sector_addr, 0, lba_limit, name, lba_emsg);
 3368     } else if (0 == strcasecmp(name, "Istdout")) {
 3369         do_IDentity = 2;
 3370     } else if (0 == strcasecmp(name, "Iraw")) {
 3371         do_IDentity = 3;
 3372         get_filename_parm(&raw_identify_path, name);
 3373     } else if (0 == strcasecmp(name, "security-mode")) {
 3374         if (argc && isalpha(**argv)) {
 3375             argp = *argv++, --argc;
 3376             if (*argp == 'm')   /* max */
 3377                 security_mode = 1;
 3378             else if (*argp == 'h')  /* high */
 3379                 security_mode = 0;
 3380             else
 3381                 security_help(EINVAL);
 3382             while (*argp) ++argp;
 3383         }
 3384         --num_flags_processed;  /* doesn't count as an action flag */
 3385     } else if (0 == strcasecmp(name, "security-prompt-for-password")) {
 3386         security_prompt_for_password = 1;
 3387         --num_flags_processed;  /* doesn't count as an action flag */
 3388     } else if (0 == strcasecmp(name, "user-master")) {
 3389         if (argc && isalpha(**argv)) {
 3390             argp = *argv++, --argc;
 3391             if (*argp == 'u')   /* user */
 3392                 security_master = 0;
 3393             else if (*argp == 'm')  /* master */
 3394                 security_master = 1;
 3395             else
 3396                 security_help(EINVAL);
 3397             while (*argp) ++argp;
 3398         }
 3399         --num_flags_processed;  /* doesn't count as an action flag */
 3400     } else if (0 == strcasecmp(name, "security-freeze")) {
 3401         security_freeze = 1;
 3402     } else {
 3403         return handle_standalone_longarg(name);
 3404     }
 3405     return 0; /* additional flags allowed */
 3406 }
 3407 
 3408 int main (int _argc, char **_argv)
 3409 {
 3410     int no_more_flags = 0, disallow_flags = 0;
 3411     char c;
 3412     char name[32];
 3413 
 3414     argc = _argc;
 3415     argv = _argv;
 3416     argp = NULL;
 3417 
 3418     if  ((progname = (char *) strrchr(*argv, '/')) == NULL)
 3419         progname = *argv;
 3420     else
 3421         progname++;
 3422     ++argv;
 3423 
 3424     if (!--argc)
 3425         usage_help(6,EINVAL);
 3426     while (argc--) {
 3427         argp = *argv++;
 3428         if (no_more_flags || argp[0] != '-') {
 3429             if (!num_flags_processed)
 3430                 do_defaults = 1;
 3431             process_dev(argp);
 3432             continue;
 3433         }
 3434         if (0 == strcmp(argp, "--")) {
 3435             no_more_flags = 1;
 3436             continue;
 3437         }
 3438         if (disallow_flags) {
 3439             fprintf(stderr, "Excess flags given.\n");
 3440             usage_help(7,EINVAL);
 3441         }
 3442         if (!*++argp)
 3443             usage_help(8,EINVAL);
 3444         while (argp && (c = *argp++)) {
 3445             switch (c) {
 3446                 case GET_SET_PARM('a',"filesystem-read-ahead",fsreadahead,0,2048);
 3447                 case GET_SET_PARM('A',"look-ahead",lookahead,0,1);
 3448                 case GET_SET_PARM('b',"bus-state",busstate,0,2);
 3449                 case GET_SET_PARM('B',"power-management-mode",apmmode,0,255);
 3450                 case GET_SET_PARM('c',"32-bit-IO",io32bit,0,3);
 3451                 case     SET_FLAG('C',powermode);
 3452                 case GET_SET_PARM('d',"dma-enable",dma,0,1);
 3453                 case     SET_PARM('D',"defects-management",defects,0,1);
 3454                 case     SET_PARM('E',"CDROM/DVD-speed",cdromspeed,0,255);
 3455                 case      DO_FLAG('f',do_flush);
 3456                 case      DO_FLAG('F',do_flush_wcache);
 3457                 case      DO_FLAG('g',get_geom);
 3458                 case              'h': usage_help(9,0); break;
 3459                 case     SET_FLAG('H',hitachi_temp);
 3460                 case      DO_FLAG('i',do_identity);
 3461                 case      DO_FLAG('I',do_IDentity);
 3462                 case GET_SET_PARM('J',"WDC-idle3-timeout",wdidle3,0,300);
 3463                 case GET_SET_PARM('k',"kernel-keep-settings",keep,0,1);
 3464                 case     SET_PARM('K',"drive-keep-settings",dkeep,0,1);
 3465                 case     SET_PARM('L',"door-lock",doorlock,0,1);
 3466                 case GET_SET_PARM('m',"multmode-count",mult,0,64);
 3467                 case GET_SET_PARM('M',"acoustic-management",acoustic,0,255);
 3468                 case GET_SET_PARM('n',"ignore-write-errors",nowerr,0,1);
 3469                 case              'N': get_set_max_sectors_parms(); break;
 3470                 case     SET_PARM('P',"prefetch",prefetch,0,255);
 3471                 case              'q': quiet = 1; noisy = 0; break;
 3472                 case GET_SET_PARM('Q',"queue-depth",dma_q,0,1024);
 3473                 case     SET_PARM('s',"powerup-in-standby",powerup_in_standby,0,1);
 3474                 case     SET_PARM('S',"standby-interval",standby,0,255);
 3475                 case GET_SET_PARM('r',"read-only",readonly,0,1);
 3476                 case GET_SET_PARM('R',"write-read-verify",write_read_verify,0,3);
 3477                 case      DO_FLAG('t',do_timings);
 3478                 case      DO_FLAG('T',do_ctimings);
 3479                 case GET_SET_PARM('u',"unmask-irq",unmask,0,1);
 3480                 case      DO_FLAG('v',do_defaults);
 3481                 case              'V': fprintf(stdout, "%s %s\n", progname, HDPARM_VERSION); exit(0);
 3482                 case     SET_FLAG('w',doreset);
 3483                 case GET_SET_PARM('W',"write-cache",wcache,0,1);
 3484                 case     SET_FLAG('y',standbynow);
 3485                 case     SET_FLAG('Y',sleepnow);
 3486 
 3487                 case     SET_FLAG('z',reread_partn);
 3488                 case     SET_FLAG('Z',seagate);
 3489 
 3490                 case '-':
 3491                     if (get_longarg())
 3492                         disallow_flags = 1;
 3493                     break;
 3494 
 3495                 case 'p':
 3496                     get_piomode = noisy;
 3497                     noisy = 1;
 3498                     GET_XFERMODE(set_piomode,piomode);
 3499                     break;
 3500 
 3501                 case 'X':
 3502                     get_xfermode = noisy;
 3503                     noisy = 1;
 3504                     GET_XFERMODE(set_xfermode,xfermode_requested);
 3505                     if (!set_xfermode)
 3506                         fprintf(stderr, "-X: missing value\n");
 3507                     break;
 3508 
 3509 
 3510                 default:
 3511                     usage_help(10,EINVAL);
 3512             }
 3513             num_flags_processed++;
 3514         }
 3515         if (!argc)
 3516             usage_help(11,EINVAL);
 3517     }
 3518     return 0;
 3519 }