"Fossies" - the Fresh Open Source Software Archive

Member "hdparm-9.60/hdparm.c" (21 Nov 2020, 101692 Bytes) of package /linux/misc/hdparm-9.60.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.58_vs_9.60.

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