busybox/miscutils/hdparm.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * hdparm implementation for busybox
   4 *
   5 * Copyright (C) [2003] by [Matteo Croce] <3297627799@wind.it>
   6 * Hacked by Tito <farmatito@tiscali.it> for size optimization.
   7 *
   8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   9 *
  10 * This program is based on the source code of hdparm: see below...
  11 * hdparm.c - Command line interface to get/set hard disk parameters
  12 *          - by Mark Lord (C) 1994-2002 -- freely distributable
  13 */
  14#include "libbb.h"
  15/* must be _after_ libbb.h: */
  16#include <linux/hdreg.h>
  17#include <sys/mount.h>
  18#if !defined(BLKGETSIZE64)
  19# define BLKGETSIZE64 _IOR(0x12,114,size_t)
  20#endif
  21
  22/* device types */
  23/* ------------ */
  24#define NO_DEV                  0xffff
  25#define ATA_DEV                 0x0000
  26#define ATAPI_DEV               0x0001
  27
  28/* word definitions */
  29/* ---------------- */
  30#define GEN_CONFIG              0   /* general configuration */
  31#define LCYLS                   1   /* number of logical cylinders */
  32#define CONFIG                  2   /* specific configuration */
  33#define LHEADS                  3   /* number of logical heads */
  34#define TRACK_BYTES             4   /* number of bytes/track (ATA-1) */
  35#define SECT_BYTES              5   /* number of bytes/sector (ATA-1) */
  36#define LSECTS                  6   /* number of logical sectors/track */
  37#define START_SERIAL            10  /* ASCII serial number */
  38#define LENGTH_SERIAL           10  /* 10 words (20 bytes or characters) */
  39#define BUF_TYPE                20  /* buffer type (ATA-1) */
  40#define BUFFER__SIZE            21  /* buffer size (ATA-1) */
  41#define RW_LONG                 22  /* extra bytes in R/W LONG cmd ( < ATA-4)*/
  42#define START_FW_REV            23  /* ASCII firmware revision */
  43#define LENGTH_FW_REV            4  /*  4 words (8 bytes or characters) */
  44#define START_MODEL             27  /* ASCII model number */
  45#define LENGTH_MODEL            20  /* 20 words (40 bytes or characters) */
  46#define SECTOR_XFER_MAX         47  /* r/w multiple: max sectors xfered */
  47#define DWORD_IO                48  /* can do double-word IO (ATA-1 only) */
  48#define CAPAB_0                 49  /* capabilities */
  49#define CAPAB_1                 50
  50#define PIO_MODE                51  /* max PIO mode supported (obsolete)*/
  51#define DMA_MODE                52  /* max Singleword DMA mode supported (obs)*/
  52#define WHATS_VALID             53  /* what fields are valid */
  53#define LCYLS_CUR               54  /* current logical cylinders */
  54#define LHEADS_CUR              55  /* current logical heads */
  55#define LSECTS_CUR              56  /* current logical sectors/track */
  56#define CAPACITY_LSB            57  /* current capacity in sectors */
  57#define CAPACITY_MSB            58
  58#define SECTOR_XFER_CUR         59  /* r/w multiple: current sectors xfered */
  59#define LBA_SECTS_LSB           60  /* LBA: total number of user */
  60#define LBA_SECTS_MSB           61  /*      addressable sectors */
  61#define SINGLE_DMA              62  /* singleword DMA modes */
  62#define MULTI_DMA               63  /* multiword DMA modes */
  63#define ADV_PIO_MODES           64  /* advanced PIO modes supported */
  64                                    /* multiword DMA xfer cycle time: */
  65#define DMA_TIME_MIN            65  /*   - minimum */
  66#define DMA_TIME_NORM           66  /*   - manufacturer's recommended */
  67                                    /* minimum PIO xfer cycle time: */
  68#define PIO_NO_FLOW             67  /*   - without flow control */
  69#define PIO_FLOW                68  /*   - with IORDY flow control */
  70#define PKT_REL                 71  /* typical #ns from PKT cmd to bus rel */
  71#define SVC_NBSY                72  /* typical #ns from SERVICE cmd to !BSY */
  72#define CDR_MAJOR               73  /* CD ROM: major version number */
  73#define CDR_MINOR               74  /* CD ROM: minor version number */
  74#define QUEUE_DEPTH             75  /* queue depth */
  75#define MAJOR                   80  /* major version number */
  76#define MINOR                   81  /* minor version number */
  77#define CMDS_SUPP_0             82  /* command/feature set(s) supported */
  78#define CMDS_SUPP_1             83
  79#define CMDS_SUPP_2             84
  80#define CMDS_EN_0               85  /* command/feature set(s) enabled */
  81#define CMDS_EN_1               86
  82#define CMDS_EN_2               87
  83#define ULTRA_DMA               88  /* ultra DMA modes */
  84                                    /* time to complete security erase */
  85#define ERASE_TIME              89  /*   - ordinary */
  86#define ENH_ERASE_TIME          90  /*   - enhanced */
  87#define ADV_PWR                 91  /* current advanced power management level
  88                                       in low byte, 0x40 in high byte. */
  89#define PSWD_CODE               92  /* master password revision code */
  90#define HWRST_RSLT              93  /* hardware reset result */
  91#define ACOUSTIC                94  /* acoustic mgmt values ( >= ATA-6) */
  92#define LBA_LSB                 100 /* LBA: maximum.  Currently only 48 */
  93#define LBA_MID                 101 /*      bits are used, but addr 103 */
  94#define LBA_48_MSB              102 /*      has been reserved for LBA in */
  95#define LBA_64_MSB              103 /*      the future. */
  96#define RM_STAT                 127 /* removable media status notification feature set support */
  97#define SECU_STATUS             128 /* security status */
  98#define CFA_PWR_MODE            160 /* CFA power mode 1 */
  99#define START_MEDIA             176 /* media serial number */
 100#define LENGTH_MEDIA            20  /* 20 words (40 bytes or characters)*/
 101#define START_MANUF             196 /* media manufacturer I.D. */
 102#define LENGTH_MANUF            10  /* 10 words (20 bytes or characters) */
 103#define INTEGRITY               255 /* integrity word */
 104
 105/* bit definitions within the words */
 106/* -------------------------------- */
 107
 108/* many words are considered valid if bit 15 is 0 and bit 14 is 1 */
 109#define VALID                   0xc000
 110#define VALID_VAL               0x4000
 111/* many words are considered invalid if they are either all-0 or all-1 */
 112#define NOVAL_0                 0x0000
 113#define NOVAL_1                 0xffff
 114
 115/* word 0: gen_config */
 116#define NOT_ATA                 0x8000
 117#define NOT_ATAPI               0x4000  /* (check only if bit 15 == 1) */
 118#define MEDIA_REMOVABLE         0x0080
 119#define DRIVE_NOT_REMOVABLE     0x0040  /* bit obsoleted in ATA 6 */
 120#define INCOMPLETE              0x0004
 121#define CFA_SUPPORT_VAL         0x848a  /* 848a=CFA feature set support */
 122#define DRQ_RESPONSE_TIME       0x0060
 123#define DRQ_3MS_VAL             0x0000
 124#define DRQ_INTR_VAL            0x0020
 125#define DRQ_50US_VAL            0x0040
 126#define PKT_SIZE_SUPPORTED      0x0003
 127#define PKT_SIZE_12_VAL         0x0000
 128#define PKT_SIZE_16_VAL         0x0001
 129#define EQPT_TYPE               0x1f00
 130#define SHIFT_EQPT              8
 131
 132#define CDROM 0x0005
 133
 134/* word 1: number of logical cylinders */
 135#define LCYLS_MAX               0x3fff /* maximum allowable value */
 136
 137/* word 2: specific configuration
 138 * (a) require SET FEATURES to spin-up
 139 * (b) require spin-up to fully reply to IDENTIFY DEVICE
 140 */
 141#define STBY_NID_VAL            0x37c8  /*     (a) and     (b) */
 142#define STBY_ID_VAL             0x738c  /*     (a) and not (b) */
 143#define PWRD_NID_VAL            0x8c73  /* not (a) and     (b) */
 144#define PWRD_ID_VAL             0xc837  /* not (a) and not (b) */
 145
 146/* words 47 & 59: sector_xfer_max & sector_xfer_cur */
 147#define SECTOR_XFER             0x00ff  /* sectors xfered on r/w multiple cmds*/
 148#define MULTIPLE_SETTING_VALID  0x0100  /* 1=multiple sector setting is valid */
 149
 150/* word 49: capabilities 0 */
 151#define STD_STBY                0x2000  /* 1=standard values supported (ATA); 0=vendor specific values */
 152#define IORDY_SUP               0x0800  /* 1=support; 0=may be supported */
 153#define IORDY_OFF               0x0400  /* 1=may be disabled */
 154#define LBA_SUP                 0x0200  /* 1=Logical Block Address support */
 155#define DMA_SUP                 0x0100  /* 1=Direct Memory Access support */
 156#define DMA_IL_SUP              0x8000  /* 1=interleaved DMA support (ATAPI) */
 157#define CMD_Q_SUP               0x4000  /* 1=command queuing support (ATAPI) */
 158#define OVLP_SUP                0x2000  /* 1=overlap operation support (ATAPI) */
 159#define SWRST_REQ               0x1000  /* 1=ATA SW reset required (ATAPI, obsolete */
 160
 161/* word 50: capabilities 1 */
 162#define MIN_STANDBY_TIMER       0x0001  /* 1=device specific standby timer value minimum */
 163
 164/* words 51 & 52: PIO & DMA cycle times */
 165#define MODE                    0xff00  /* the mode is in the MSBs */
 166
 167/* word 53: whats_valid */
 168#define OK_W88                  0x0004  /* the ultra_dma info is valid */
 169#define OK_W64_70               0x0002  /* see above for word descriptions */
 170#define OK_W54_58               0x0001  /* current cyl, head, sector, cap. info valid */
 171
 172/*word 63,88: dma_mode, ultra_dma_mode*/
 173#define MODE_MAX                7       /* bit definitions force udma <=7 (when
 174                                         * udma >=8 comes out it'll have to be
 175                                         * defined in a new dma_mode word!) */
 176
 177/* word 64: PIO transfer modes */
 178#define PIO_SUP                 0x00ff  /* only bits 0 & 1 are used so far,  */
 179#define PIO_MODE_MAX            8       /* but all 8 bits are defined        */
 180
 181/* word 75: queue_depth */
 182#define DEPTH_BITS              0x001f  /* bits used for queue depth */
 183
 184/* words 80-81: version numbers */
 185/* NOVAL_0 or  NOVAL_1 means device does not report version */
 186
 187/* word 81: minor version number */
 188#define MINOR_MAX               0x22
 189/* words 82-84: cmds/feats supported */
 190#define CMDS_W82                0x77ff  /* word 82: defined command locations*/
 191#define CMDS_W83                0x3fff  /* word 83: defined command locations*/
 192#define CMDS_W84                0x002f  /* word 83: defined command locations*/
 193#define SUPPORT_48_BIT          0x0400
 194#define NUM_CMD_FEAT_STR        48
 195
 196/* words 85-87: cmds/feats enabled */
 197/* use cmd_feat_str[] to display what commands and features have
 198 * been enabled with words 85-87
 199 */
 200
 201/* words 89, 90, SECU ERASE TIME */
 202#define ERASE_BITS      0x00ff
 203
 204/* word 92: master password revision */
 205/* NOVAL_0 or  NOVAL_1 means no support for master password revision */
 206
 207/* word 93: hw reset result */
 208#define CBLID           0x2000  /* CBLID status */
 209#define RST0            0x0001  /* 1=reset to device #0 */
 210#define DEV_DET         0x0006  /* how device num determined */
 211#define JUMPER_VAL      0x0002  /* device num determined by jumper */
 212#define CSEL_VAL        0x0004  /* device num determined by CSEL_VAL */
 213
 214/* word 127: removable media status notification feature set support */
 215#define RM_STAT_BITS    0x0003
 216#define RM_STAT_SUP     0x0001
 217
 218/* word 128: security */
 219#define SECU_ENABLED    0x0002
 220#define SECU_LEVEL      0x0010
 221#define NUM_SECU_STR    6
 222
 223/* word 160: CFA power mode */
 224#define VALID_W160              0x8000  /* 1=word valid */
 225#define PWR_MODE_REQ            0x2000  /* 1=CFA power mode req'd by some cmds*/
 226#define PWR_MODE_OFF            0x1000  /* 1=CFA power moded disabled */
 227#define MAX_AMPS                0x0fff  /* value = max current in ma */
 228
 229/* word 255: integrity */
 230#define SIG                     0x00ff  /* signature location */
 231#define SIG_VAL                 0x00a5  /* signature value */
 232
 233#define TIMING_BUF_MB           1
 234#define TIMING_BUF_BYTES        (TIMING_BUF_MB * 1024 * 1024)
 235
 236#undef DO_FLUSHCACHE            /* under construction: force cache flush on -W0 */
 237
 238
 239#define IS_GET 1
 240#define IS_SET 2
 241
 242
 243enum { fd = 3 };
 244
 245
 246struct globals {
 247        smallint get_identity, get_geom;
 248        smallint do_flush;
 249        smallint do_ctimings, do_timings;
 250        smallint reread_partn;
 251        smallint set_piomode, noisy_piomode;
 252        smallint getset_readahead;
 253        smallint getset_readonly;
 254        smallint getset_unmask;
 255        smallint getset_mult;
 256#ifdef HDIO_GET_QDMA
 257        smallint getset_dma_q;
 258#endif
 259        smallint getset_nowerr;
 260        smallint getset_keep;
 261        smallint getset_io32bit;
 262        int piomode;
 263        unsigned long Xreadahead;
 264        unsigned long readonly;
 265        unsigned long unmask;
 266        unsigned long mult;
 267#ifdef HDIO_SET_QDMA
 268        unsigned long dma_q;
 269#endif
 270        unsigned long nowerr;
 271        unsigned long keep;
 272        unsigned long io32bit;
 273#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
 274        unsigned long dma;
 275        smallint getset_dma;
 276#endif
 277#ifdef HDIO_DRIVE_CMD
 278        smallint set_xfermode, get_xfermode;
 279        smallint getset_dkeep;
 280        smallint getset_standby;
 281        smallint getset_lookahead;
 282        smallint getset_prefetch;
 283        smallint getset_defects;
 284        smallint getset_wcache;
 285        smallint getset_doorlock;
 286        smallint set_seagate;
 287        smallint set_standbynow;
 288        smallint set_sleepnow;
 289        smallint get_powermode;
 290        smallint getset_apmmode;
 291        int xfermode_requested;
 292        unsigned long dkeep;
 293        unsigned long standby_requested; /* 0..255 */
 294        unsigned long lookahead;
 295        unsigned long prefetch;
 296        unsigned long defects;
 297        unsigned long wcache;
 298        unsigned long doorlock;
 299        unsigned long apmmode;
 300#endif
 301        IF_FEATURE_HDPARM_GET_IDENTITY(        smallint get_IDentity;)
 302        IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  smallint getset_busstate;)
 303        IF_FEATURE_HDPARM_HDIO_DRIVE_RESET(    smallint perform_reset;)
 304        IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  smallint perform_tristate;)
 305        IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(smallint unregister_hwif;)
 306        IF_FEATURE_HDPARM_HDIO_SCAN_HWIF(      smallint scan_hwif;)
 307        IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  unsigned long busstate;)
 308        IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  unsigned long tristate;)
 309        IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(unsigned long hwif;)
 310#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
 311        unsigned long hwif_data;
 312        unsigned long hwif_ctrl;
 313        unsigned long hwif_irq;
 314#endif
 315#ifdef DO_FLUSHCACHE
 316        unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };
 317#endif
 318} FIX_ALIASING;
 319#define G (*(struct globals*)&bb_common_bufsiz1)
 320struct BUG_G_too_big {
 321        char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
 322};
 323#define get_identity       (G.get_identity           )
 324#define get_geom           (G.get_geom               )
 325#define do_flush           (G.do_flush               )
 326#define do_ctimings        (G.do_ctimings            )
 327#define do_timings         (G.do_timings             )
 328#define reread_partn       (G.reread_partn           )
 329#define set_piomode        (G.set_piomode            )
 330#define noisy_piomode      (G.noisy_piomode          )
 331#define getset_readahead   (G.getset_readahead       )
 332#define getset_readonly    (G.getset_readonly        )
 333#define getset_unmask      (G.getset_unmask          )
 334#define getset_mult        (G.getset_mult            )
 335#define getset_dma_q       (G.getset_dma_q           )
 336#define getset_nowerr      (G.getset_nowerr          )
 337#define getset_keep        (G.getset_keep            )
 338#define getset_io32bit     (G.getset_io32bit         )
 339#define piomode            (G.piomode                )
 340#define Xreadahead         (G.Xreadahead             )
 341#define readonly           (G.readonly               )
 342#define unmask             (G.unmask                 )
 343#define mult               (G.mult                   )
 344#define dma_q              (G.dma_q                  )
 345#define nowerr             (G.nowerr                 )
 346#define keep               (G.keep                   )
 347#define io32bit            (G.io32bit                )
 348#define dma                (G.dma                    )
 349#define getset_dma         (G.getset_dma             )
 350#define set_xfermode       (G.set_xfermode           )
 351#define get_xfermode       (G.get_xfermode           )
 352#define getset_dkeep       (G.getset_dkeep           )
 353#define getset_standby     (G.getset_standby         )
 354#define getset_lookahead   (G.getset_lookahead       )
 355#define getset_prefetch    (G.getset_prefetch        )
 356#define getset_defects     (G.getset_defects         )
 357#define getset_wcache      (G.getset_wcache          )
 358#define getset_doorlock    (G.getset_doorlock        )
 359#define set_seagate        (G.set_seagate            )
 360#define set_standbynow     (G.set_standbynow         )
 361#define set_sleepnow       (G.set_sleepnow           )
 362#define get_powermode      (G.get_powermode          )
 363#define getset_apmmode     (G.getset_apmmode         )
 364#define xfermode_requested (G.xfermode_requested     )
 365#define dkeep              (G.dkeep                  )
 366#define standby_requested  (G.standby_requested      )
 367#define lookahead          (G.lookahead              )
 368#define prefetch           (G.prefetch               )
 369#define defects            (G.defects                )
 370#define wcache             (G.wcache                 )
 371#define doorlock           (G.doorlock               )
 372#define apmmode            (G.apmmode                )
 373#define get_IDentity       (G.get_IDentity           )
 374#define getset_busstate    (G.getset_busstate        )
 375#define perform_reset      (G.perform_reset          )
 376#define perform_tristate   (G.perform_tristate       )
 377#define unregister_hwif    (G.unregister_hwif        )
 378#define scan_hwif          (G.scan_hwif              )
 379#define busstate           (G.busstate               )
 380#define tristate           (G.tristate               )
 381#define hwif               (G.hwif                   )
 382#define hwif_data          (G.hwif_data              )
 383#define hwif_ctrl          (G.hwif_ctrl              )
 384#define hwif_irq           (G.hwif_irq               )
 385
 386
 387/* Busybox messages and functions */
 388#if ENABLE_IOCTL_HEX2STR_ERROR
 389static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt, const char *string)
 390{
 391        if (!ioctl(fd, cmd, args))
 392                return 0;
 393        args[0] = alt;
 394        return bb_ioctl_or_warn(fd, cmd, args, string);
 395}
 396#define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt,#cmd)
 397#else
 398static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt)
 399{
 400        if (!ioctl(fd, cmd, args))
 401                return 0;
 402        args[0] = alt;
 403        return bb_ioctl_or_warn(fd, cmd, args);
 404}
 405#define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt)
 406#endif
 407
 408static void on_off(int value)
 409{
 410        puts(value ? " (on)" : " (off)");
 411}
 412
 413static void print_flag_on_off(int get_arg, const char *s, unsigned long arg)
 414{
 415        if (get_arg) {
 416                printf(" setting %s to %ld", s, arg);
 417                on_off(arg);
 418        }
 419}
 420
 421static void print_value_on_off(const char *str, unsigned long argp)
 422{
 423        printf(" %s\t= %2ld", str, argp);
 424        on_off(argp != 0);
 425}
 426
 427#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
 428static void print_ascii(const char *p, int length)
 429{
 430#if BB_BIG_ENDIAN
 431#define LE_ONLY(x)
 432        enum { ofs = 0 };
 433#else
 434#define LE_ONLY(x) x
 435        /* every 16bit word is big-endian (i.e. inverted) */
 436        /* accessing bytes in 1,0, 3,2, 5,4... sequence */
 437        int ofs = 1;
 438#endif
 439
 440        length *= 2;
 441        /* find first non-space & print it */
 442        while (length && p[ofs] != ' ') {
 443                p++;
 444                LE_ONLY(ofs = -ofs;)
 445                length--;
 446        }
 447        while (length && p[ofs]) {
 448                bb_putchar(p[ofs]);
 449                p++;
 450                LE_ONLY(ofs = -ofs;)
 451                length--;
 452        }
 453        bb_putchar('\n');
 454#undef LE_ONLY
 455}
 456
 457static void xprint_ascii(uint16_t *val, int i, const char *string, int n)
 458{
 459        if (val[i]) {
 460                printf("\t%-20s", string);
 461                print_ascii((void*)&val[i], n);
 462        }
 463}
 464
 465static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode)
 466{
 467        uint16_t ii;
 468        uint8_t err_dma = 0;
 469
 470        for (ii = 0; ii <= MODE_MAX; ii++) {
 471                if (mode_sel & 0x0001) {
 472                        printf("*%cdma%u ", cc, ii);
 473                        if (*have_mode)
 474                                err_dma = 1;
 475                        *have_mode = 1;
 476                } else if (mode_sup & 0x0001)
 477                        printf("%cdma%u ", cc, ii);
 478
 479                mode_sup >>= 1;
 480                mode_sel >>= 1;
 481        }
 482        return err_dma;
 483}
 484
 485static const char pkt_str[] ALIGN1 =
 486        "Direct-access device" "\0"             /* word 0, bits 12-8 = 00 */
 487        "Sequential-access device" "\0"         /* word 0, bits 12-8 = 01 */
 488        "Printer" "\0"                          /* word 0, bits 12-8 = 02 */
 489        "Processor" "\0"                        /* word 0, bits 12-8 = 03 */
 490        "Write-once device" "\0"                /* word 0, bits 12-8 = 04 */
 491        "CD-ROM" "\0"                           /* word 0, bits 12-8 = 05 */
 492        "Scanner" "\0"                          /* word 0, bits 12-8 = 06 */
 493        "Optical memory" "\0"                   /* word 0, bits 12-8 = 07 */
 494        "Medium changer" "\0"                   /* word 0, bits 12-8 = 08 */
 495        "Communications device" "\0"            /* word 0, bits 12-8 = 09 */
 496        "ACS-IT8 device" "\0"                   /* word 0, bits 12-8 = 0a */
 497        "ACS-IT8 device" "\0"                   /* word 0, bits 12-8 = 0b */
 498        "Array controller" "\0"                 /* word 0, bits 12-8 = 0c */
 499        "Enclosure services" "\0"               /* word 0, bits 12-8 = 0d */
 500        "Reduced block command device" "\0"     /* word 0, bits 12-8 = 0e */
 501        "Optical card reader/writer" "\0"       /* word 0, bits 12-8 = 0f */
 502;
 503
 504static const char ata1_cfg_str[] ALIGN1 =       /* word 0 in ATA-1 mode */
 505        "reserved" "\0"                         /* bit 0 */
 506        "hard sectored" "\0"                    /* bit 1 */
 507        "soft sectored" "\0"                    /* bit 2 */
 508        "not MFM encoded " "\0"                 /* bit 3 */
 509        "head switch time > 15us" "\0"          /* bit 4 */
 510        "spindle motor control option" "\0"     /* bit 5 */
 511        "fixed drive" "\0"                      /* bit 6 */
 512        "removable drive" "\0"                  /* bit 7 */
 513        "disk xfer rate <= 5Mbs" "\0"           /* bit 8 */
 514        "disk xfer rate > 5Mbs, <= 10Mbs" "\0"  /* bit 9 */
 515        "disk xfer rate > 5Mbs" "\0"            /* bit 10 */
 516        "rotational speed tol." "\0"            /* bit 11 */
 517        "data strobe offset option" "\0"        /* bit 12 */
 518        "track offset option" "\0"              /* bit 13 */
 519        "format speed tolerance gap reqd" "\0"  /* bit 14 */
 520        "ATAPI"                                 /* bit 14 */
 521;
 522
 523static const char minor_str[] ALIGN1 =
 524        /* word 81 value: */
 525        "Unspecified" "\0"                                  /* 0x0000 */
 526        "ATA-1 X3T9.2 781D prior to rev.4" "\0"             /* 0x0001 */
 527        "ATA-1 published, ANSI X3.221-1994" "\0"            /* 0x0002 */
 528        "ATA-1 X3T9.2 781D rev.4" "\0"                      /* 0x0003 */
 529        "ATA-2 published, ANSI X3.279-1996" "\0"            /* 0x0004 */
 530        "ATA-2 X3T10 948D prior to rev.2k" "\0"             /* 0x0005 */
 531        "ATA-3 X3T10 2008D rev.1" "\0"                      /* 0x0006 */
 532        "ATA-2 X3T10 948D rev.2k" "\0"                      /* 0x0007 */
 533        "ATA-3 X3T10 2008D rev.0" "\0"                      /* 0x0008 */
 534        "ATA-2 X3T10 948D rev.3" "\0"                       /* 0x0009 */
 535        "ATA-3 published, ANSI X3.298-199x" "\0"            /* 0x000a */
 536        "ATA-3 X3T10 2008D rev.6" "\0"                      /* 0x000b */
 537        "ATA-3 X3T13 2008D rev.7 and 7a" "\0"               /* 0x000c */
 538        "ATA/ATAPI-4 X3T13 1153D rev.6" "\0"                /* 0x000d */
 539        "ATA/ATAPI-4 T13 1153D rev.13" "\0"                 /* 0x000e */
 540        "ATA/ATAPI-4 X3T13 1153D rev.7" "\0"                /* 0x000f */
 541        "ATA/ATAPI-4 T13 1153D rev.18" "\0"                 /* 0x0010 */
 542        "ATA/ATAPI-4 T13 1153D rev.15" "\0"                 /* 0x0011 */
 543        "ATA/ATAPI-4 published, ANSI INCITS 317-1998" "\0"  /* 0x0012 */
 544        "ATA/ATAPI-5 T13 1321D rev.3" "\0"                  /* 0x0013 */
 545        "ATA/ATAPI-4 T13 1153D rev.14" "\0"                 /* 0x0014 */
 546        "ATA/ATAPI-5 T13 1321D rev.1" "\0"                  /* 0x0015 */
 547        "ATA/ATAPI-5 published, ANSI INCITS 340-2000" "\0"  /* 0x0016 */
 548        "ATA/ATAPI-4 T13 1153D rev.17" "\0"                 /* 0x0017 */
 549        "ATA/ATAPI-6 T13 1410D rev.0" "\0"                  /* 0x0018 */
 550        "ATA/ATAPI-6 T13 1410D rev.3a" "\0"                 /* 0x0019 */
 551        "ATA/ATAPI-7 T13 1532D rev.1" "\0"                  /* 0x001a */
 552        "ATA/ATAPI-6 T13 1410D rev.2" "\0"                  /* 0x001b */
 553        "ATA/ATAPI-6 T13 1410D rev.1" "\0"                  /* 0x001c */
 554        "ATA/ATAPI-7 published, ANSI INCITS 397-2005" "\0"  /* 0x001d */
 555        "ATA/ATAPI-7 T13 1532D rev.0" "\0"                  /* 0x001e */
 556        "reserved" "\0"                                     /* 0x001f */
 557        "reserved" "\0"                                     /* 0x0020 */
 558        "ATA/ATAPI-7 T13 1532D rev.4a" "\0"                 /* 0x0021 */
 559        "ATA/ATAPI-6 published, ANSI INCITS 361-2002" "\0"  /* 0x0022 */
 560        "reserved"                                          /* 0x0023-0xfffe */
 561;
 562static const char actual_ver[MINOR_MAX + 2] ALIGN1 = {
 563           /* word 81 value: */
 564        0, /* 0x0000 WARNING: actual_ver[] array */
 565        1, /* 0x0001 WARNING: corresponds        */
 566        1, /* 0x0002 WARNING: *exactly*          */
 567        1, /* 0x0003 WARNING: to the ATA/        */
 568        2, /* 0x0004 WARNING: ATAPI version      */
 569        2, /* 0x0005 WARNING: listed in          */
 570        3, /* 0x0006 WARNING: the                */
 571        2, /* 0x0007 WARNING: minor_str          */
 572        3, /* 0x0008 WARNING: array              */
 573        2, /* 0x0009 WARNING: above.             */
 574        3, /* 0x000a WARNING:                    */
 575        3, /* 0x000b WARNING: If you change      */
 576        3, /* 0x000c WARNING: that one,          */
 577        4, /* 0x000d WARNING: change this one    */
 578        4, /* 0x000e WARNING: too!!!             */
 579        4, /* 0x000f */
 580        4, /* 0x0010 */
 581        4, /* 0x0011 */
 582        4, /* 0x0012 */
 583        5, /* 0x0013 */
 584        4, /* 0x0014 */
 585        5, /* 0x0015 */
 586        5, /* 0x0016 */
 587        4, /* 0x0017 */
 588        6, /* 0x0018 */
 589        6, /* 0x0019 */
 590        7, /* 0x001a */
 591        6, /* 0x001b */
 592        6, /* 0x001c */
 593        7, /* 0x001d */
 594        7, /* 0x001e */
 595        0, /* 0x001f */
 596        0, /* 0x0020 */
 597        7, /* 0x0021 */
 598        6, /* 0x0022 */
 599        0  /* 0x0023-0xfffe */
 600};
 601
 602static const char cmd_feat_str[] ALIGN1 =
 603        "" "\0"                                     /* word 82 bit 15: obsolete  */
 604        "NOP cmd" "\0"                              /* word 82 bit 14 */
 605        "READ BUFFER cmd" "\0"                      /* word 82 bit 13 */
 606        "WRITE BUFFER cmd" "\0"                     /* word 82 bit 12 */
 607        "" "\0"                                     /* word 82 bit 11: obsolete  */
 608        "Host Protected Area feature set" "\0"      /* word 82 bit 10 */
 609        "DEVICE RESET cmd" "\0"                     /* word 82 bit  9 */
 610        "SERVICE interrupt" "\0"                    /* word 82 bit  8 */
 611        "Release interrupt" "\0"                    /* word 82 bit  7 */
 612        "Look-ahead" "\0"                           /* word 82 bit  6 */
 613        "Write cache" "\0"                          /* word 82 bit  5 */
 614        "PACKET command feature set" "\0"           /* word 82 bit  4 */
 615        "Power Management feature set" "\0"         /* word 82 bit  3 */
 616        "Removable Media feature set" "\0"          /* word 82 bit  2 */
 617        "Security Mode feature set" "\0"            /* word 82 bit  1 */
 618        "SMART feature set" "\0"                    /* word 82 bit  0 */
 619                                                    /* -------------- */
 620        "" "\0"                                     /* word 83 bit 15: !valid bit */
 621        "" "\0"                                     /* word 83 bit 14:  valid bit */
 622        "FLUSH CACHE EXT cmd" "\0"                  /* word 83 bit 13 */
 623        "Mandatory FLUSH CACHE cmd " "\0"           /* word 83 bit 12 */
 624        "Device Configuration Overlay feature set " "\0"
 625        "48-bit Address feature set " "\0"          /* word 83 bit 10 */
 626        "" "\0"
 627        "SET MAX security extension" "\0"           /* word 83 bit  8 */
 628        "Address Offset Reserved Area Boot" "\0"    /* word 83 bit  7 */
 629        "SET FEATURES subcommand required to spinup after power up" "\0"
 630        "Power-Up In Standby feature set" "\0"      /* word 83 bit  5 */
 631        "Removable Media Status Notification feature set" "\0"
 632        "Adv. Power Management feature set" "\0"    /* word 83 bit  3 */
 633        "CFA feature set" "\0"                      /* word 83 bit  2 */
 634        "READ/WRITE DMA QUEUED" "\0"                /* word 83 bit  1 */
 635        "DOWNLOAD MICROCODE cmd" "\0"               /* word 83 bit  0 */
 636                                                    /* -------------- */
 637        "" "\0"                                     /* word 84 bit 15: !valid bit */
 638        "" "\0"                                     /* word 84 bit 14:  valid bit */
 639        "" "\0"                                     /* word 84 bit 13:  reserved */
 640        "" "\0"                                     /* word 84 bit 12:  reserved */
 641        "" "\0"                                     /* word 84 bit 11:  reserved */
 642        "" "\0"                                     /* word 84 bit 10:  reserved */
 643        "" "\0"                                     /* word 84 bit  9:  reserved */
 644        "" "\0"                                     /* word 84 bit  8:  reserved */
 645        "" "\0"                                     /* word 84 bit  7:  reserved */
 646        "" "\0"                                     /* word 84 bit  6:  reserved */
 647        "General Purpose Logging feature set" "\0"  /* word 84 bit  5 */
 648        "" "\0"                                     /* word 84 bit  4:  reserved */
 649        "Media Card Pass Through Command feature set " "\0"
 650        "Media serial number " "\0"                 /* word 84 bit  2 */
 651        "SMART self-test " "\0"                     /* word 84 bit  1 */
 652        "SMART error logging "                      /* word 84 bit  0 */
 653;
 654
 655static const char secu_str[] ALIGN1 =
 656        "supported" "\0"                /* word 128, bit 0 */
 657        "enabled" "\0"                  /* word 128, bit 1 */
 658        "locked" "\0"                   /* word 128, bit 2 */
 659        "frozen" "\0"                   /* word 128, bit 3 */
 660        "expired: security count" "\0"  /* word 128, bit 4 */
 661        "supported: enhanced erase"     /* word 128, bit 5 */
 662;
 663
 664// Parse 512 byte disk identification block and print much crap.
 665static void identify(uint16_t *val) NORETURN;
 666static void identify(uint16_t *val)
 667{
 668        uint16_t ii, jj, kk;
 669        uint16_t like_std = 1, std = 0, min_std = 0xffff;
 670        uint16_t dev = NO_DEV, eqpt = NO_DEV;
 671        uint8_t  have_mode = 0, err_dma = 0;
 672        uint8_t  chksum = 0;
 673        uint32_t ll, mm, nn, oo;
 674        uint64_t bbbig; /* (:) */
 675        const char *strng;
 676#if BB_BIG_ENDIAN
 677        uint16_t buf[256];
 678
 679        // Adjust for endianness
 680        swab(val, buf, sizeof(buf));
 681        val = buf;
 682#endif
 683        /* check if we recognize the device type */
 684        bb_putchar('\n');
 685        if (!(val[GEN_CONFIG] & NOT_ATA)) {
 686                dev = ATA_DEV;
 687                printf("ATA device, with ");
 688        } else if (val[GEN_CONFIG]==CFA_SUPPORT_VAL) {
 689                dev = ATA_DEV;
 690                like_std = 4;
 691                printf("CompactFlash ATA device, with ");
 692        } else if (!(val[GEN_CONFIG] & NOT_ATAPI)) {
 693                dev = ATAPI_DEV;
 694                eqpt = (val[GEN_CONFIG] & EQPT_TYPE) >> SHIFT_EQPT;
 695                printf("ATAPI %s, with ", eqpt <= 0xf ? nth_string(pkt_str, eqpt) : "unknown");
 696                like_std = 3;
 697        } else
 698                /* "Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n" */
 699                bb_error_msg_and_die("unknown device type");
 700
 701        printf("%sremovable media\n", !(val[GEN_CONFIG] & MEDIA_REMOVABLE) ? "non-" : "");
 702        /* Info from the specific configuration word says whether or not the
 703         * ID command completed correctly.  It is only defined, however in
 704         * ATA/ATAPI-5 & 6; it is reserved (value theoretically 0) in prior
 705         * standards.  Since the values allowed for this word are extremely
 706         * specific, it should be safe to check it now, even though we don't
 707         * know yet what standard this device is using.
 708         */
 709        if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL)
 710         || (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL)
 711        ) {
 712                like_std = 5;
 713                if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL))
 714                        printf("powers-up in standby; SET FEATURES subcmd spins-up.\n");
 715                if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE))
 716                        printf("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n\n");
 717        }
 718
 719        /* output the model and serial numbers and the fw revision */
 720        xprint_ascii(val, START_MODEL,  "Model Number:",        LENGTH_MODEL);
 721        xprint_ascii(val, START_SERIAL, "Serial Number:",       LENGTH_SERIAL);
 722        xprint_ascii(val, START_FW_REV, "Firmware Revision:",   LENGTH_FW_REV);
 723        xprint_ascii(val, START_MEDIA,  "Media Serial Num:",    LENGTH_MEDIA);
 724        xprint_ascii(val, START_MANUF,  "Media Manufacturer:",  LENGTH_MANUF);
 725
 726        /* major & minor standards version number (Note: these words were not
 727         * defined until ATA-3 & the CDROM std uses different words.) */
 728        printf("Standards:");
 729        if (eqpt != CDROM) {
 730                if (val[MINOR] && (val[MINOR] <= MINOR_MAX)) {
 731                        if (like_std < 3) like_std = 3;
 732                        std = actual_ver[val[MINOR]];
 733                        if (std)
 734                                printf("\n\tUsed: %s ", nth_string(minor_str, val[MINOR]));
 735                }
 736                /* looks like when they up-issue the std, they obsolete one;
 737                 * thus, only the newest 4 issues need be supported. (That's
 738                 * what "kk" and "min_std" are all about.) */
 739                if (val[MAJOR] && (val[MAJOR] != NOVAL_1)) {
 740                        printf("\n\tSupported: ");
 741                        jj = val[MAJOR] << 1;
 742                        kk = like_std >4 ? like_std-4: 0;
 743                        for (ii = 14; (ii >0)&&(ii>kk); ii--) {
 744                                if (jj & 0x8000) {
 745                                        printf("%u ", ii);
 746                                        if (like_std < ii) {
 747                                                like_std = ii;
 748                                                kk = like_std >4 ? like_std-4: 0;
 749                                        }
 750                                        if (min_std > ii) min_std = ii;
 751                                }
 752                                jj <<= 1;
 753                        }
 754                        if (like_std < 3) like_std = 3;
 755                }
 756                /* Figure out what standard the device is using if it hasn't told
 757                 * us.  If we know the std, check if the device is using any of
 758                 * the words from the next level up.  It happens.
 759                 */
 760                if (like_std < std) like_std = std;
 761
 762                if (((std == 5) || (!std && (like_std < 6))) &&
 763                        ((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
 764                        ((      val[CMDS_SUPP_1] & CMDS_W83) > 0x00ff)) ||
 765                        (((     val[CMDS_SUPP_2] & VALID) == VALID_VAL) &&
 766                        (       val[CMDS_SUPP_2] & CMDS_W84) ) )
 767                ) {
 768                        like_std = 6;
 769                } else if (((std == 4) || (!std && (like_std < 5))) &&
 770                        ((((val[INTEGRITY]      & SIG) == SIG_VAL) && !chksum) ||
 771                        ((      val[HWRST_RSLT] & VALID) == VALID_VAL) ||
 772                        (((     val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
 773                        ((      val[CMDS_SUPP_1] & CMDS_W83) > 0x001f)) ) )
 774                {
 775                        like_std = 5;
 776                } else if (((std == 3) || (!std && (like_std < 4))) &&
 777                                ((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
 778                                (((     val[CMDS_SUPP_1] & CMDS_W83) > 0x0000) ||
 779                                ((      val[CMDS_SUPP_0] & CMDS_W82) > 0x000f))) ||
 780                                ((      val[CAPAB_1] & VALID) == VALID_VAL) ||
 781                                ((      val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) ||
 782                                ((      val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) )
 783                ) {
 784                        like_std = 4;
 785                } else if (((std == 2) || (!std && (like_std < 3)))
 786                 && ((val[CMDS_SUPP_1] & VALID) == VALID_VAL)
 787                ) {
 788                        like_std = 3;
 789                } else if (((std == 1) || (!std && (like_std < 2))) &&
 790                                ((val[CAPAB_0] & (IORDY_SUP | IORDY_OFF)) ||
 791                                (val[WHATS_VALID] & OK_W64_70)) )
 792                {
 793                        like_std = 2;
 794                }
 795
 796                if (!std)
 797                        printf("\n\tLikely used: %u\n", like_std);
 798                else if (like_std > std)
 799                        printf("& some of %u\n", like_std);
 800                else
 801                        bb_putchar('\n');
 802        } else {
 803                /* TBD: do CDROM stuff more thoroughly.  For now... */
 804                kk = 0;
 805                if (val[CDR_MINOR] == 9) {
 806                        kk = 1;
 807                        printf("\n\tUsed: ATAPI for CD-ROMs, SFF-8020i, r2.5");
 808                }
 809                if (val[CDR_MAJOR] && (val[CDR_MAJOR] !=NOVAL_1)) {
 810                        kk = 1;
 811                        printf("\n\tSupported: CD-ROM ATAPI");
 812                        jj = val[CDR_MAJOR] >> 1;
 813                        for (ii = 1; ii < 15; ii++) {
 814                                if (jj & 0x0001) printf("-%u ", ii);
 815                                jj >>= 1;
 816                        }
 817                }
 818                puts(kk ? "" : "\n\tLikely used CD-ROM ATAPI-1");
 819                /* the cdrom stuff is more like ATA-2 than anything else, so: */
 820                like_std = 2;
 821        }
 822
 823        if (min_std == 0xffff)
 824                min_std = like_std > 4 ? like_std - 3 : 1;
 825
 826        printf("Configuration:\n");
 827        /* more info from the general configuration word */
 828        if ((eqpt != CDROM) && (like_std == 1)) {
 829                jj = val[GEN_CONFIG] >> 1;
 830                for (ii = 1; ii < 15; ii++) {
 831                        if (jj & 0x0001)
 832                                printf("\t%s\n", nth_string(ata1_cfg_str, ii));
 833                        jj >>=1;
 834                }
 835        }
 836        if (dev == ATAPI_DEV) {
 837                if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) ==  DRQ_3MS_VAL)
 838                        strng = "3ms";
 839                else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) ==  DRQ_INTR_VAL)
 840                        strng = "<=10ms with INTRQ";
 841                else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) ==  DRQ_50US_VAL)
 842                        strng ="50us";
 843                else
 844                        strng = "unknown";
 845                printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */
 846
 847                if ((val[GEN_CONFIG] & PKT_SIZE_SUPPORTED) == PKT_SIZE_12_VAL)
 848                        strng = "12 bytes";
 849                else if ((val[GEN_CONFIG] & PKT_SIZE_SUPPORTED) == PKT_SIZE_16_VAL)
 850                        strng = "16 bytes";
 851                else
 852                        strng = "unknown";
 853                puts(strng);
 854        } else {
 855                /* addressing...CHS? See section 6.2 of ATA specs 4 or 5 */
 856                ll = (uint32_t)val[LBA_SECTS_MSB] << 16 | val[LBA_SECTS_LSB];
 857                mm = 0;
 858                bbbig = 0;
 859                if ((ll > 0x00FBFC10) && (!val[LCYLS]))
 860                        printf("\tCHS addressing not supported\n");
 861                else {
 862                        jj = val[WHATS_VALID] & OK_W54_58;
 863                        printf("\tLogical\t\tmax\tcurrent\n"
 864                                "\tcylinders\t%u\t%u\n"
 865                                "\theads\t\t%u\t%u\n"
 866                                "\tsectors/track\t%u\t%u\n"
 867                                "\t--\n",
 868                                val[LCYLS],
 869                                jj ? val[LCYLS_CUR] : 0,
 870                                val[LHEADS],
 871                                jj ? val[LHEADS_CUR] : 0,
 872                                val[LSECTS],
 873                                jj ? val[LSECTS_CUR] : 0);
 874
 875                        if ((min_std == 1) && (val[TRACK_BYTES] || val[SECT_BYTES]))
 876                                printf("\tbytes/track: %u\tbytes/sector: %u\n",
 877                                        val[TRACK_BYTES], val[SECT_BYTES]);
 878
 879                        if (jj) {
 880                                mm = (uint32_t)val[CAPACITY_MSB] << 16 | val[CAPACITY_LSB];
 881                                if (like_std < 3) {
 882                                        /* check Endian of capacity bytes */
 883                                        nn = val[LCYLS_CUR] * val[LHEADS_CUR] * val[LSECTS_CUR];
 884                                        oo = (uint32_t)val[CAPACITY_LSB] << 16 | val[CAPACITY_MSB];
 885                                        if (abs(mm - nn) > abs(oo - nn))
 886                                                mm = oo;
 887                                }
 888                                printf("\tCHS current addressable sectors:%11u\n", mm);
 889                        }
 890                }
 891                /* LBA addressing */
 892                printf("\tLBA    user addressable sectors:%11u\n", ll);
 893                if (((val[CMDS_SUPP_1] & VALID) == VALID_VAL)
 894                 && (val[CMDS_SUPP_1] & SUPPORT_48_BIT)
 895                ) {
 896                        bbbig = (uint64_t)val[LBA_64_MSB] << 48 |
 897                                (uint64_t)val[LBA_48_MSB] << 32 |
 898                                (uint64_t)val[LBA_MID] << 16 |
 899                                        val[LBA_LSB];
 900                        printf("\tLBA48  user addressable sectors:%11"PRIu64"\n", bbbig);
 901                }
 902
 903                if (!bbbig)
 904                        bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */
 905                printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11);
 906                bbbig = (bbbig << 9) / 1000000;
 907                printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig);
 908
 909                if (bbbig > 1000)
 910                        printf("(%"PRIu64" GB)\n", bbbig/1000);
 911                else
 912                        bb_putchar('\n');
 913        }
 914
 915        /* hw support of commands (capabilities) */
 916        printf("Capabilities:\n\t");
 917
 918        if (dev == ATAPI_DEV) {
 919                if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP))
 920                        printf("Cmd queuing, ");
 921                if (val[CAPAB_0] & OVLP_SUP)
 922                        printf("Cmd overlap, ");
 923        }
 924        if (val[CAPAB_0] & LBA_SUP) printf("LBA, ");
 925
 926        if (like_std != 1) {
 927                printf("IORDY%s(can%s be disabled)\n",
 928                        !(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "",
 929                        (val[CAPAB_0] & IORDY_OFF) ? "" :"not");
 930        } else
 931                printf("no IORDY\n");
 932
 933        if ((like_std == 1) && val[BUF_TYPE]) {
 934                printf("\tBuffer type: %04x: %s%s\n", val[BUF_TYPE],
 935                        (val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector",
 936                        (val[BUF_TYPE] > 2) ? " with read caching ability" : "");
 937        }
 938
 939        if ((min_std == 1) && (val[BUFFER__SIZE] && (val[BUFFER__SIZE] != NOVAL_1))) {
 940                printf("\tBuffer size: %.1fkB\n", (float)val[BUFFER__SIZE]/2);
 941        }
 942        if ((min_std < 4) && (val[RW_LONG])) {
 943                printf("\tbytes avail on r/w long: %u\n", val[RW_LONG]);
 944        }
 945        if ((eqpt != CDROM) && (like_std > 3)) {
 946                printf("\tQueue depth: %u\n", (val[QUEUE_DEPTH] & DEPTH_BITS) + 1);
 947        }
 948
 949        if (dev == ATA_DEV) {
 950                if (like_std == 1)
 951                        printf("\tCan%s perform double-word IO\n", (!val[DWORD_IO]) ? "not" : "");
 952                else {
 953                        printf("\tStandby timer values: spec'd by %s",
 954                                (val[CAPAB_0] & STD_STBY) ? "standard" : "vendor");
 955                        if ((like_std > 3) && ((val[CAPAB_1] & VALID) == VALID_VAL))
 956                                printf(", %s device specific minimum\n",
 957                                        (val[CAPAB_1] & MIN_STANDBY_TIMER) ? "with" : "no");
 958                        else
 959                                bb_putchar('\n');
 960                }
 961                printf("\tR/W multiple sector transfer: ");
 962                if ((like_std < 3) && !(val[SECTOR_XFER_MAX] & SECTOR_XFER))
 963                        printf("not supported\n");
 964                else {
 965                        printf("Max = %u\tCurrent = ", val[SECTOR_XFER_MAX] & SECTOR_XFER);
 966                        if (val[SECTOR_XFER_CUR] & MULTIPLE_SETTING_VALID)
 967                                printf("%u\n", val[SECTOR_XFER_CUR] & SECTOR_XFER);
 968                        else
 969                                printf("?\n");
 970                }
 971                if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008)) {
 972                        /* We print out elsewhere whether the APM feature is enabled or
 973                           not.  If it's not enabled, let's not repeat the info; just print
 974                           nothing here. */
 975                        printf("\tAdvancedPM level: ");
 976                        if ((val[ADV_PWR] & 0xFF00) == 0x4000) {
 977                                uint8_t apm_level = val[ADV_PWR] & 0x00FF;
 978                                printf("%u (0x%x)\n", apm_level, apm_level);
 979                        }
 980                        else
 981                                printf("unknown setting (0x%04x)\n", val[ADV_PWR]);
 982                }
 983                if (like_std > 5 && val[ACOUSTIC]) {
 984                        printf("\tRecommended acoustic management value: %u, current value: %u\n",
 985                                (val[ACOUSTIC] >> 8) & 0x00ff,
 986                                val[ACOUSTIC] & 0x00ff);
 987                }
 988        } else {
 989                 /* ATAPI */
 990                if (eqpt != CDROM && (val[CAPAB_0] & SWRST_REQ))
 991                        printf("\tATA sw reset required\n");
 992
 993                if (val[PKT_REL] || val[SVC_NBSY]) {
 994                        printf("\tOverlap support:");
 995                        if (val[PKT_REL])
 996                                printf(" %uus to release bus.", val[PKT_REL]);
 997                        if (val[SVC_NBSY])
 998                                printf(" %uus to clear BSY after SERVICE cmd.",
 999                                        val[SVC_NBSY]);
1000                        bb_putchar('\n');
1001                }
1002        }
1003
1004        /* DMA stuff. Check that only one DMA mode is selected. */
1005        printf("\tDMA: ");
1006        if (!(val[CAPAB_0] & DMA_SUP))
1007                printf("not supported\n");
1008        else {
1009                if (val[DMA_MODE] && !val[SINGLE_DMA] && !val[MULTI_DMA])
1010                        printf(" sdma%u\n", (val[DMA_MODE] & MODE) >> 8);
1011                if (val[SINGLE_DMA]) {
1012                        jj = val[SINGLE_DMA];
1013                        kk = val[SINGLE_DMA] >> 8;
1014                        err_dma += mode_loop(jj, kk, 's', &have_mode);
1015                }
1016                if (val[MULTI_DMA]) {
1017                        jj = val[MULTI_DMA];
1018                        kk = val[MULTI_DMA] >> 8;
1019                        err_dma += mode_loop(jj, kk, 'm', &have_mode);
1020                }
1021                if ((val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) {
1022                        jj = val[ULTRA_DMA];
1023                        kk = val[ULTRA_DMA] >> 8;
1024                        err_dma += mode_loop(jj, kk, 'u', &have_mode);
1025                }
1026                if (err_dma || !have_mode) printf("(?)");
1027                bb_putchar('\n');
1028
1029                if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP))
1030                        printf("\t\tInterleaved DMA support\n");
1031
1032                if ((val[WHATS_VALID] & OK_W64_70)
1033                 && (val[DMA_TIME_MIN] || val[DMA_TIME_NORM])
1034                ) {
1035                        printf("\t\tCycle time:");
1036                        if (val[DMA_TIME_MIN]) printf(" min=%uns", val[DMA_TIME_MIN]);
1037                        if (val[DMA_TIME_NORM]) printf(" recommended=%uns", val[DMA_TIME_NORM]);
1038                        bb_putchar('\n');
1039                }
1040        }
1041
1042        /* Programmed IO stuff */
1043        printf("\tPIO: ");
1044        /* If a drive supports mode n (e.g. 3), it also supports all modes less
1045         * than n (e.g. 3, 2, 1 and 0).  Print all the modes. */
1046        if ((val[WHATS_VALID] & OK_W64_70) && (val[ADV_PIO_MODES] & PIO_SUP)) {
1047                jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007;
1048                for (ii = 0; ii <= PIO_MODE_MAX; ii++) {
1049                        if (jj & 0x0001) printf("pio%d ", ii);
1050                        jj >>=1;
1051                }
1052                bb_putchar('\n');
1053        } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) {
1054                for (ii = 0; ii <= val[PIO_MODE]>>8; ii++)
1055                        printf("pio%d ", ii);
1056                bb_putchar('\n');
1057        } else
1058                puts("unknown");
1059
1060        if (val[WHATS_VALID] & OK_W64_70) {
1061                if (val[PIO_NO_FLOW] || val[PIO_FLOW]) {
1062                        printf("\t\tCycle time:");
1063                        if (val[PIO_NO_FLOW])
1064                                printf(" no flow control=%uns", val[PIO_NO_FLOW]);
1065                        if (val[PIO_FLOW])
1066                                printf("  IORDY flow control=%uns", val[PIO_FLOW]);
1067                        bb_putchar('\n');
1068                }
1069        }
1070
1071        if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) {
1072                printf("Commands/features:\n"
1073                        "\tEnabled\tSupported:\n");
1074                jj = val[CMDS_SUPP_0];
1075                kk = val[CMDS_EN_0];
1076                for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++) {
1077                        const char *feat_str = nth_string(cmd_feat_str, ii);
1078                        if ((jj & 0x8000) && (*feat_str != '\0')) {
1079                                printf("\t%s\t%s\n", (kk & 0x8000) ? "   *" : "", feat_str);
1080                        }
1081                        jj <<= 1;
1082                        kk <<= 1;
1083                        if (ii % 16 == 15) {
1084                                jj = val[CMDS_SUPP_0+1+(ii/16)];
1085                                kk = val[CMDS_EN_0+1+(ii/16)];
1086                        }
1087                        if (ii == 31) {
1088                                if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL)
1089                                        ii +=16;
1090                        }
1091                }
1092        }
1093        /* Removable Media Status Notification feature set */
1094        if ((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP)
1095                printf("\t%s supported\n", nth_string(cmd_feat_str, 27));
1096
1097        /* security */
1098        if ((eqpt != CDROM) && (like_std > 3)
1099         && (val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME])
1100        ) {
1101                printf("Security:\n");
1102                if (val[PSWD_CODE] && (val[PSWD_CODE] != NOVAL_1))
1103                        printf("\tMaster password revision code = %u\n", val[PSWD_CODE]);
1104                jj = val[SECU_STATUS];
1105                if (jj) {
1106                        for (ii = 0; ii < NUM_SECU_STR; ii++) {
1107                                printf("\t%s\t%s\n",
1108                                        (!(jj & 0x0001)) ? "not" : "",
1109                                        nth_string(secu_str, ii));
1110                                jj >>=1;
1111                        }
1112                        if (val[SECU_STATUS] & SECU_ENABLED) {
1113                                printf("\tSecurity level %s\n",
1114                                        (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high");
1115                        }
1116                }
1117                jj =  val[ERASE_TIME]     & ERASE_BITS;
1118                kk =  val[ENH_ERASE_TIME] & ERASE_BITS;
1119                if (jj || kk) {
1120                        bb_putchar('\t');
1121                        if (jj) printf("%umin for %sSECURITY ERASE UNIT. ", jj==ERASE_BITS ? 508 : jj<<1, "");
1122                        if (kk) printf("%umin for %sSECURITY ERASE UNIT. ", kk==ERASE_BITS ? 508 : kk<<1, "ENHANCED ");
1123                        bb_putchar('\n');
1124                }
1125        }
1126
1127        /* reset result */
1128        jj = val[HWRST_RSLT];
1129        if ((jj & VALID) == VALID_VAL) {
1130                oo = (jj & RST0);
1131                if (!oo)
1132                        jj >>= 8;
1133                if ((jj & DEV_DET) == JUMPER_VAL)
1134                        strng = " determined by the jumper";
1135                else if ((jj & DEV_DET) == CSEL_VAL)
1136                        strng = " determined by CSEL";
1137                else
1138                        strng = "";
1139                printf("HW reset results:\n"
1140                        "\tCBLID- %s Vih\n"
1141                        "\tDevice num = %i%s\n",
1142                        (val[HWRST_RSLT] & CBLID) ? "above" : "below",
1143                        !(oo), strng);
1144        }
1145
1146        /* more stuff from std 5 */
1147        if ((like_std > 4) && (eqpt != CDROM)) {
1148                if (val[CFA_PWR_MODE] & VALID_W160) {
1149                        printf("CFA power mode 1:\n"
1150                                "\t%s%s\n",
1151                                (val[CFA_PWR_MODE] & PWR_MODE_OFF) ? "disabled" : "enabled",
1152                                (val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : "");
1153                        if (val[CFA_PWR_MODE] & MAX_AMPS)
1154                                printf("\tMaximum current = %uma\n", val[CFA_PWR_MODE] & MAX_AMPS);
1155                }
1156                if ((val[INTEGRITY] & SIG) == SIG_VAL) {
1157                        printf("Checksum: %scorrect\n", chksum ? "in" : "");
1158                }
1159        }
1160
1161        exit(EXIT_SUCCESS);
1162}
1163#endif
1164
1165// Historically, if there was no HDIO_OBSOLETE_IDENTITY, then
1166// then the HDIO_GET_IDENTITY only returned 142 bytes.
1167// Otherwise, HDIO_OBSOLETE_IDENTITY returns 142 bytes,
1168// and HDIO_GET_IDENTITY returns 512 bytes.  But the latest
1169// 2.5.xx kernels no longer define HDIO_OBSOLETE_IDENTITY
1170// (which they should, but they should just return -EINVAL).
1171//
1172// So.. we must now assume that HDIO_GET_IDENTITY returns 512 bytes.
1173// On a really old system, it will not, and we will be confused.
1174// Too bad, really.
1175
1176#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
1177static const char cfg_str[] ALIGN1 =
1178        """\0"            "HardSect""\0"   "SoftSect""\0"  "NotMFM""\0"
1179        "HdSw>15uSec""\0" "SpinMotCtl""\0" "Fixed""\0"     "Removeable""\0"
1180        "DTR<=5Mbs""\0"   "DTR>5Mbs""\0"   "DTR>10Mbs""\0" "RotSpdTol>.5%""\0"
1181        "dStbOff""\0"     "TrkOff""\0"     "FmtGapReq""\0" "nonMagnetic"
1182;
1183
1184static const char BuffType[] ALIGN1 =
1185        "unknown""\0"     "1Sect""\0"      "DualPort""\0"  "DualPortCache"
1186;
1187
1188static NOINLINE void dump_identity(const struct hd_driveid *id)
1189{
1190        int i;
1191        const unsigned short *id_regs = (const void*) id;
1192
1193        printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n Config={",
1194                                id->model, id->fw_rev, id->serial_no);
1195        for (i = 0; i <= 15; i++) {
1196                if (id->config & (1<<i))
1197                        printf(" %s", nth_string(cfg_str, i));
1198        }
1199        printf(" }\n RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n"
1200                " BuffType=(%u) %s, BuffSize=%ukB, MaxMultSect=%u",
1201                id->cyls, id->heads, id->sectors, id->track_bytes,
1202                id->sector_bytes, id->ecc_bytes,
1203                id->buf_type,
1204                nth_string(BuffType, (id->buf_type > 3) ? 0 : id->buf_type),
1205                id->buf_size/2, id->max_multsect);
1206        if (id->max_multsect) {
1207                printf(", MultSect=");
1208                if (!(id->multsect_valid & 1))
1209                        printf("?%u?", id->multsect);
1210                else if (id->multsect)
1211                        printf("%u", id->multsect);
1212                else
1213                        printf("off");
1214        }
1215        bb_putchar('\n');
1216
1217        if (!(id->field_valid & 1))
1218                printf(" (maybe):");
1219
1220        printf(" CurCHS=%u/%u/%u, CurSects=%lu, LBA=%s", id->cur_cyls, id->cur_heads,
1221                id->cur_sectors,
1222                (BB_BIG_ENDIAN) ?
1223                        (unsigned long)(id->cur_capacity0 << 16) | id->cur_capacity1 :
1224                        (unsigned long)(id->cur_capacity1 << 16) | id->cur_capacity0,
1225                        ((id->capability&2) == 0) ? "no" : "yes");
1226
1227        if (id->capability & 2)
1228                printf(", LBAsects=%u", id->lba_capacity);
1229
1230        printf("\n IORDY=%s",
1231                (id->capability & 8)
1232                        ? ((id->capability & 4) ? "on/off" : "yes")
1233                        : "no");
1234
1235        if (((id->capability & 8) || (id->field_valid & 2)) && (id->field_valid & 2))
1236                printf(", tPIO={min:%u,w/IORDY:%u}", id->eide_pio, id->eide_pio_iordy);
1237
1238        if ((id->capability & 1) && (id->field_valid & 2))
1239                printf(", tDMA={min:%u,rec:%u}", id->eide_dma_min, id->eide_dma_time);
1240
1241        printf("\n PIO modes:  ");
1242        if (id->tPIO <= 5) {
1243                printf("pio0 ");
1244                if (id->tPIO >= 1) printf("pio1 ");
1245                if (id->tPIO >= 2) printf("pio2 ");
1246        }
1247        if (id->field_valid & 2) {
1248                static const masks_labels_t pio_modes = {
1249                        .masks = { 1, 2, ~3 },
1250                        .labels = "pio3 \0""pio4 \0""pio? \0",
1251                };
1252                print_flags(&pio_modes, id->eide_pio_modes);
1253        }
1254        if (id->capability & 1) {
1255                if (id->dma_1word | id->dma_mword) {
1256                        static const int dma_wmode_masks[] = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 };
1257                        printf("\n DMA modes:  ");
1258                        print_flags_separated(dma_wmode_masks,
1259                                "*\0""sdma0 \0""*\0""sdma1 \0""*\0""sdma2 \0""*\0""sdma? \0",
1260                                id->dma_1word, NULL);
1261                        print_flags_separated(dma_wmode_masks,
1262                                "*\0""mdma0 \0""*\0""mdma1 \0""*\0""mdma2 \0""*\0""mdma? \0",
1263                                id->dma_mword, NULL);
1264                }
1265        }
1266        if (((id->capability & 8) || (id->field_valid & 2)) && id->field_valid & 4) {
1267                static const masks_labels_t ultra_modes1 = {
1268                        .masks = { 0x100, 0x001, 0x200, 0x002, 0x400, 0x004 },
1269                        .labels = "*\0""udma0 \0""*\0""udma1 \0""*\0""udma2 \0",
1270                };
1271
1272                printf("\n UDMA modes: ");
1273                print_flags(&ultra_modes1, id->dma_ultra);
1274#ifdef __NEW_HD_DRIVE_ID
1275                if (id->hw_config & 0x2000) {
1276#else /* !__NEW_HD_DRIVE_ID */
1277                if (id->word93 & 0x2000) {
1278#endif /* __NEW_HD_DRIVE_ID */
1279                        static const masks_labels_t ultra_modes2 = {
1280                                .masks = { 0x0800, 0x0008, 0x1000, 0x0010,
1281                                        0x2000, 0x0020, 0x4000, 0x0040,
1282                                        0x8000, 0x0080 },
1283                                .labels = "*\0""udma3 \0""*\0""udma4 \0"
1284                                        "*\0""udma5 \0""*\0""udma6 \0"
1285                                        "*\0""udma7 \0"
1286                        };
1287                        print_flags(&ultra_modes2, id->dma_ultra);
1288                }
1289        }
1290        printf("\n AdvancedPM=%s", (!(id_regs[83] & 8)) ? "no" : "yes");
1291        if (id_regs[83] & 8) {
1292                if (!(id_regs[86] & 8))
1293                        printf(": disabled (255)");
1294                else if ((id_regs[91] & 0xFF00) != 0x4000)
1295                        printf(": unknown setting");
1296                else
1297                        printf(": mode=0x%02X (%u)", id_regs[91] & 0xFF, id_regs[91] & 0xFF);
1298        }
1299        if (id_regs[82] & 0x20)
1300                printf(" WriteCache=%s", (id_regs[85] & 0x20) ? "enabled" : "disabled");
1301#ifdef __NEW_HD_DRIVE_ID
1302        if ((id->minor_rev_num && id->minor_rev_num <= 31)
1303         || (id->major_rev_num && id->minor_rev_num <= 31)
1304        ) {
1305                printf("\n Drive conforms to: %s: ",
1306                        (id->minor_rev_num <= 31) ? nth_string(minor_str, id->minor_rev_num) : "unknown");
1307                if (id->major_rev_num != 0x0000 /* NOVAL_0 */
1308                 && id->major_rev_num != 0xFFFF /* NOVAL_1 */
1309                ) {
1310                        for (i = 0; i <= 15; i++) {
1311                                if (id->major_rev_num & (1<<i))
1312                                        printf(" ATA/ATAPI-%u", i);
1313                        }
1314                }
1315        }
1316#endif /* __NEW_HD_DRIVE_ID */
1317        printf("\n\n * current active mode\n\n");
1318}
1319#endif
1320
1321static void flush_buffer_cache(/*int fd*/ void)
1322{
1323        fsync(fd);                              /* flush buffers */
1324        ioctl_or_warn(fd, BLKFLSBUF, NULL); /* do it again, big time */
1325#ifdef HDIO_DRIVE_CMD
1326        sleep(1);
1327        if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) {       /* await completion */
1328                if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */
1329                        bb_perror_msg("HDIO_DRIVE_CMD");
1330                else
1331                        bb_perror_msg("ioctl %#x failed", HDIO_DRIVE_CMD);
1332        }
1333#endif
1334}
1335
1336static void seek_to_zero(/*int fd*/ void)
1337{
1338        xlseek(fd, (off_t) 0, SEEK_SET);
1339}
1340
1341static void read_big_block(/*int fd,*/ char *buf)
1342{
1343        int i;
1344
1345        xread(fd, buf, TIMING_BUF_BYTES);
1346        /* access all sectors of buf to ensure the read fully completed */
1347        for (i = 0; i < TIMING_BUF_BYTES; i += 512)
1348                buf[i] &= 1;
1349}
1350
1351static unsigned dev_size_mb(/*int fd*/ void)
1352{
1353        union {
1354                unsigned long long blksize64;
1355                unsigned blksize32;
1356        } u;
1357
1358        if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // bytes
1359                u.blksize64 /= (1024 * 1024);
1360        } else {
1361                xioctl(fd, BLKGETSIZE, &u.blksize32); // sectors
1362                u.blksize64 = u.blksize32 / (2 * 1024);
1363        }
1364        if (u.blksize64 > UINT_MAX)
1365                return UINT_MAX;
1366        return u.blksize64;
1367}
1368
1369static void print_timing(unsigned m, unsigned elapsed_us)
1370{
1371        unsigned sec = elapsed_us / 1000000;
1372        unsigned hs = (elapsed_us % 1000000) / 10000;
1373
1374        printf("%5u MB in %u.%02u seconds = %u kB/s\n",
1375                m, sec, hs,
1376                /* "| 1" prevents div-by-0 */
1377                (unsigned) ((unsigned long long)m * (1024 * 1000000) / (elapsed_us | 1))
1378                // ~= (m * 1024) / (elapsed_us / 1000000)
1379                // = kb / elapsed_sec
1380        );
1381}
1382
1383static void do_time(int cache /*,int fd*/)
1384/* cache=1: time cache: repeatedly read N MB at offset 0
1385 * cache=0: time device: linear read, starting at offset 0
1386 */
1387{
1388        unsigned max_iterations, iterations;
1389        unsigned start; /* doesn't need to be long long */
1390        unsigned elapsed, elapsed2;
1391        unsigned total_MB;
1392        char *buf = xmalloc(TIMING_BUF_BYTES);
1393
1394        if (mlock(buf, TIMING_BUF_BYTES))
1395                bb_perror_msg_and_die("mlock");
1396
1397        /* Clear out the device request queues & give them time to complete.
1398         * NB: *small* delay. User is expected to have a clue and to not run
1399         * heavy io in parallel with measurements. */
1400        sync();
1401        sleep(1);
1402        if (cache) { /* Time cache */
1403                seek_to_zero();
1404                read_big_block(buf);
1405                printf("Timing buffer-cache reads: ");
1406        } else { /* Time device */
1407                printf("Timing buffered disk reads:");
1408        }
1409        fflush_all();
1410
1411        /* Now do the timing */
1412        iterations = 0;
1413        /* Max time to run (small for cache, avoids getting
1414         * huge total_MB which can overlow unsigned type) */
1415        elapsed2 = 510000; /* cache */
1416        max_iterations = UINT_MAX;
1417        if (!cache) {
1418                elapsed2 = 3000000; /* not cache */
1419                /* Don't want to read past the end! */
1420                max_iterations = dev_size_mb() / TIMING_BUF_MB;
1421        }
1422        start = monotonic_us();
1423        do {
1424                if (cache)
1425                        seek_to_zero();
1426                read_big_block(buf);
1427                elapsed = (unsigned)monotonic_us() - start;
1428                ++iterations;
1429        } while (elapsed < elapsed2 && iterations < max_iterations);
1430        total_MB = iterations * TIMING_BUF_MB;
1431        //printf(" elapsed:%u iterations:%u ", elapsed, iterations);
1432        if (cache) {
1433                /* Cache: remove lseek() and monotonic_us() overheads
1434                 * from elapsed */
1435                start = monotonic_us();
1436                do {
1437                        seek_to_zero();
1438                        elapsed2 = (unsigned)monotonic_us() - start;
1439                } while (--iterations);
1440                //printf(" elapsed2:%u ", elapsed2);
1441                elapsed -= elapsed2;
1442                total_MB *= 2; // BUFCACHE_FACTOR (why?)
1443                flush_buffer_cache();
1444        }
1445        print_timing(total_MB, elapsed);
1446        munlock(buf, TIMING_BUF_BYTES);
1447        free(buf);
1448}
1449
1450#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
1451static void bus_state_value(unsigned value)
1452{
1453        if (value == BUSSTATE_ON)
1454                on_off(1);
1455        else if (value == BUSSTATE_OFF)
1456                on_off(0);
1457        else if (value == BUSSTATE_TRISTATE)
1458                printf(" (tristate)\n");
1459        else
1460                printf(" (unknown: %d)\n", value);
1461}
1462#endif
1463
1464#ifdef HDIO_DRIVE_CMD
1465static void interpret_standby(uint8_t standby)
1466{
1467        printf(" (");
1468        if (standby == 0) {
1469                printf("off");
1470        } else if (standby <= 240 || standby == 252 || standby == 255) {
1471                /* standby is in 5 sec units */
1472                unsigned t = standby * 5;
1473                printf("%u minutes %u seconds", t / 60, t % 60);
1474        } else if (standby <= 251) {
1475                unsigned t = (standby - 240); /* t is in 30 min units */;
1476                printf("%u.%c hours", t / 2, (t & 1) ? '5' : '0');
1477        }
1478        if (standby == 253)
1479                printf("vendor-specific");
1480        if (standby == 254)
1481                printf("reserved");
1482        printf(")\n");
1483}
1484
1485static const uint8_t xfermode_val[] ALIGN1 = {
1486         8,      9,     10,     11,     12,     13,     14,     15,
1487        16,     17,     18,     19,     20,     21,     22,     23,
1488        32,     33,     34,     35,     36,     37,     38,     39,
1489        64,     65,     66,     67,     68,     69,     70,     71
1490};
1491/* NB: we save size by _not_ storing terninating NUL! */
1492static const char xfermode_name[][5] ALIGN1 = {
1493        "pio0", "pio1", "pio2", "pio3", "pio4", "pio5", "pio6", "pio7",
1494        "sdma0","sdma1","sdma2","sdma3","sdma4","sdma5","sdma6","sdma7",
1495        "mdma0","mdma1","mdma2","mdma3","mdma4","mdma5","mdma6","mdma7",
1496        "udma0","udma1","udma2","udma3","udma4","udma5","udma6","udma7"
1497};
1498
1499static int translate_xfermode(const char *name)
1500{
1501        int val;
1502        unsigned i;
1503
1504        for (i = 0; i < ARRAY_SIZE(xfermode_val); i++) {
1505                if (!strncmp(name, xfermode_name[i], 5))
1506                        if (strlen(name) <= 5)
1507                                return xfermode_val[i];
1508        }
1509        /* Negative numbers are invalid and are caught later */
1510        val = bb_strtoi(name, NULL, 10);
1511        if (!errno)
1512                return val;
1513        return -1;
1514}
1515
1516static void interpret_xfermode(unsigned xfermode)
1517{
1518        printf(" (");
1519        if (xfermode == 0)
1520                printf("default PIO mode");
1521        else if (xfermode == 1)
1522                printf("default PIO mode, disable IORDY");
1523        else if (xfermode >= 8 && xfermode <= 15)
1524                printf("PIO flow control mode%u", xfermode - 8);
1525        else if (xfermode >= 16 && xfermode <= 23)
1526                printf("singleword DMA mode%u", xfermode - 16);
1527        else if (xfermode >= 32 && xfermode <= 39)
1528                printf("multiword DMA mode%u", xfermode - 32);
1529        else if (xfermode >= 64 && xfermode <= 71)
1530                printf("UltraDMA mode%u", xfermode - 64);
1531        else
1532                printf("unknown");
1533        printf(")\n");
1534}
1535#endif /* HDIO_DRIVE_CMD */
1536
1537static void print_flag(int flag, const char *s, unsigned long value)
1538{
1539        if (flag)
1540                printf(" setting %s to %ld\n", s, value);
1541}
1542
1543static void process_dev(char *devname)
1544{
1545        /*int fd;*/
1546        long parm, multcount;
1547#ifndef HDIO_DRIVE_CMD
1548        int force_operation = 0;
1549#endif
1550        /* Please restore args[n] to these values after each ioctl
1551           except for args[2] */
1552        unsigned char args[4] = { WIN_SETFEATURES, 0, 0, 0 };
1553        const char *fmt = " %s\t= %2ld";
1554
1555        /*fd = xopen_nonblocking(devname);*/
1556        xmove_fd(xopen_nonblocking(devname), fd);
1557        printf("\n%s:\n", devname);
1558
1559        if (getset_readahead == IS_SET) {
1560                print_flag(getset_readahead, "fs readahead", Xreadahead);
1561                ioctl_or_warn(fd, BLKRASET, (int *)Xreadahead);
1562        }
1563#if ENABLE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
1564        if (unregister_hwif) {
1565                printf(" attempting to unregister hwif#%lu\n", hwif);
1566                ioctl_or_warn(fd, HDIO_UNREGISTER_HWIF, (int *)(unsigned long)hwif);
1567        }
1568#endif
1569#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
1570        if (scan_hwif == IS_SET) {
1571                printf(" attempting to scan hwif (0x%lx, 0x%lx, %lu)\n", hwif_data, hwif_ctrl, hwif_irq);
1572                args[0] = hwif_data;
1573                args[1] = hwif_ctrl;
1574                args[2] = hwif_irq;
1575                ioctl_or_warn(fd, HDIO_SCAN_HWIF, args);
1576                args[0] = WIN_SETFEATURES;
1577                args[1] = 0;
1578        }
1579#endif
1580        if (set_piomode) {
1581                if (noisy_piomode) {
1582                        printf(" attempting to ");
1583                        if (piomode == 255)
1584                                printf("auto-tune PIO mode\n");
1585                        else if (piomode < 100)
1586                                printf("set PIO mode to %d\n", piomode);
1587                        else if (piomode < 200)
1588                                printf("set MDMA mode to %d\n", (piomode-100));
1589                        else
1590                                printf("set UDMA mode to %d\n", (piomode-200));
1591                }
1592                ioctl_or_warn(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode);
1593        }
1594        if (getset_io32bit == IS_SET) {
1595                print_flag(getset_io32bit, "32-bit IO_support flag", io32bit);
1596                ioctl_or_warn(fd, HDIO_SET_32BIT, (int *)io32bit);
1597        }
1598        if (getset_mult == IS_SET) {
1599                print_flag(getset_mult, "multcount", mult);
1600#ifdef HDIO_DRIVE_CMD
1601                ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult);
1602#else
1603                force_operation |= (!ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult));
1604#endif
1605        }
1606        if (getset_readonly == IS_SET) {
1607                print_flag_on_off(getset_readonly, "readonly", readonly);
1608                ioctl_or_warn(fd, BLKROSET, &readonly);
1609        }
1610        if (getset_unmask == IS_SET) {
1611                print_flag_on_off(getset_unmask, "unmaskirq", unmask);
1612                ioctl_or_warn(fd, HDIO_SET_UNMASKINTR, (int *)unmask);
1613        }
1614#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
1615        if (getset_dma == IS_SET) {
1616                print_flag_on_off(getset_dma, "using_dma", dma);
1617                ioctl_or_warn(fd, HDIO_SET_DMA, (int *)dma);
1618        }
1619#endif /* FEATURE_HDPARM_HDIO_GETSET_DMA */
1620#ifdef HDIO_SET_QDMA
1621        if (getset_dma_q == IS_SET) {
1622                print_flag_on_off(getset_dma_q, "DMA queue_depth", dma_q);
1623                ioctl_or_warn(fd, HDIO_SET_QDMA, (int *)dma_q);
1624        }
1625#endif
1626        if (getset_nowerr == IS_SET) {
1627                print_flag_on_off(getset_nowerr, "nowerr", nowerr);
1628                ioctl_or_warn(fd, HDIO_SET_NOWERR, (int *)nowerr);
1629        }
1630        if (getset_keep == IS_SET) {
1631                print_flag_on_off(getset_keep, "keep_settings", keep);
1632                ioctl_or_warn(fd, HDIO_SET_KEEPSETTINGS, (int *)keep);
1633        }
1634#ifdef HDIO_DRIVE_CMD
1635        if (getset_doorlock == IS_SET) {
1636                args[0] = doorlock ? WIN_DOORLOCK : WIN_DOORUNLOCK;
1637                args[2] = 0;
1638                print_flag_on_off(getset_doorlock, "drive doorlock", doorlock);
1639                ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1640                args[0] = WIN_SETFEATURES;
1641        }
1642        if (getset_dkeep == IS_SET) {
1643                /* lock/unlock the drive's "feature" settings */
1644                print_flag_on_off(getset_dkeep, "drive keep features", dkeep);
1645                args[2] = dkeep ? 0x66 : 0xcc;
1646                ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1647        }
1648        if (getset_defects == IS_SET) {
1649                args[2] = defects ? 0x04 : 0x84;
1650                print_flag(getset_defects, "drive defect-mgmt", defects);
1651                ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1652        }
1653        if (getset_prefetch == IS_SET) {
1654                args[1] = prefetch;
1655                args[2] = 0xab;
1656                print_flag(getset_prefetch, "drive prefetch", prefetch);
1657                ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1658                args[1] = 0;
1659        }
1660        if (set_xfermode) {
1661                args[1] = xfermode_requested;
1662                args[2] = 3;
1663                print_flag(1, "xfermode", xfermode_requested);
1664                interpret_xfermode(xfermode_requested);
1665                ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1666                args[1] = 0;
1667        }
1668        if (getset_lookahead == IS_SET) {
1669                args[2] = lookahead ? 0xaa : 0x55;
1670                print_flag_on_off(getset_lookahead, "drive read-lookahead", lookahead);
1671                ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1672        }
1673        if (getset_apmmode == IS_SET) {
1674                /* feature register */
1675                args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */;
1676                args[1] = apmmode; /* sector count register 1-255 */
1677                printf(" setting APM level to %s 0x%02lX (%ld)\n",
1678                        (apmmode == 255) ? "disabled" : "",
1679                        apmmode, apmmode);
1680                ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1681                args[1] = 0;
1682        }
1683        if (getset_wcache == IS_SET) {
1684#ifdef DO_FLUSHCACHE
1685#ifndef WIN_FLUSHCACHE
1686#define WIN_FLUSHCACHE 0xe7
1687#endif
1688#endif /* DO_FLUSHCACHE */
1689                args[2] = wcache ? 0x02 : 0x82;
1690                print_flag_on_off(getset_wcache, "drive write-caching", wcache);
1691#ifdef DO_FLUSHCACHE
1692                if (!wcache)
1693                        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache);
1694#endif /* DO_FLUSHCACHE */
1695                ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1696#ifdef DO_FLUSHCACHE
1697                if (!wcache)
1698                        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache);
1699#endif /* DO_FLUSHCACHE */
1700        }
1701
1702        /* In code below, we do not preserve args[0], but the rest
1703           is preserved, including args[2] */
1704        args[2] = 0;
1705
1706        if (set_standbynow) {
1707#ifndef WIN_STANDBYNOW1
1708#define WIN_STANDBYNOW1 0xE0
1709#endif
1710#ifndef WIN_STANDBYNOW2
1711#define WIN_STANDBYNOW2 0x94
1712#endif
1713                printf(" issuing standby command\n");
1714                args[0] = WIN_STANDBYNOW1;
1715                ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2);
1716        }
1717        if (set_sleepnow) {
1718#ifndef WIN_SLEEPNOW1
1719#define WIN_SLEEPNOW1 0xE6
1720#endif
1721#ifndef WIN_SLEEPNOW2
1722#define WIN_SLEEPNOW2 0x99
1723#endif
1724                printf(" issuing sleep command\n");
1725                args[0] = WIN_SLEEPNOW1;
1726                ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2);
1727        }
1728        if (set_seagate) {
1729                args[0] = 0xfb;
1730                printf(" disabling Seagate auto powersaving mode\n");
1731                ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1732        }
1733        if (getset_standby == IS_SET) {
1734                args[0] = WIN_SETIDLE1;
1735                args[1] = standby_requested;
1736                print_flag(1, "standby", standby_requested);
1737                interpret_standby(standby_requested);
1738                ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1739                args[1] = 0;
1740        }
1741#else   /* HDIO_DRIVE_CMD */
1742        if (force_operation) {
1743                char buf[512];
1744                flush_buffer_cache();
1745                if (-1 == read(fd, buf, sizeof(buf)))
1746                        bb_perror_msg("read of 512 bytes failed");
1747        }
1748#endif  /* HDIO_DRIVE_CMD */
1749        if (getset_mult || get_identity) {
1750                multcount = -1;
1751                if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) {
1752                        /* To be coherent with ioctl_or_warn. */
1753                        if (getset_mult && ENABLE_IOCTL_HEX2STR_ERROR)
1754                                bb_perror_msg("HDIO_GET_MULTCOUNT");
1755                        else
1756                                bb_perror_msg("ioctl %#x failed", HDIO_GET_MULTCOUNT);
1757                } else if (getset_mult) {
1758                        printf(fmt, "multcount", multcount);
1759                        on_off(multcount != 0);
1760                }
1761        }
1762        if (getset_io32bit) {
1763                if (!ioctl_or_warn(fd, HDIO_GET_32BIT, &parm)) {
1764                        printf(" IO_support\t=%3ld (", parm);
1765                        if (parm == 0)
1766                                printf("default 16-bit)\n");
1767                        else if (parm == 2)
1768                                printf("16-bit)\n");
1769                        else if (parm == 1)
1770                                printf("32-bit)\n");
1771                        else if (parm == 3)
1772                                printf("32-bit w/sync)\n");
1773                        else if (parm == 8)
1774                                printf("Request-Queue-Bypass)\n");
1775                        else
1776                                printf("\?\?\?)\n");
1777                }
1778        }
1779        if (getset_unmask) {
1780                if (!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, &parm))
1781                        print_value_on_off("unmaskirq", parm);
1782        }
1783#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
1784        if (getset_dma) {
1785                if (!ioctl_or_warn(fd, HDIO_GET_DMA, &parm)) {
1786                        printf(fmt, "using_dma", parm);
1787                        if (parm == 8)
1788                                printf(" (DMA-Assisted-PIO)\n");
1789                        else
1790                                on_off(parm != 0);
1791                }
1792        }
1793#endif
1794#ifdef HDIO_GET_QDMA
1795        if (getset_dma_q) {
1796                if (!ioctl_or_warn(fd, HDIO_GET_QDMA, &parm))
1797                        print_value_on_off("queue_depth", parm);
1798        }
1799#endif
1800        if (getset_keep) {
1801                if (!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, &parm))
1802                        print_value_on_off("keepsettings", parm);
1803        }
1804        if (getset_nowerr) {
1805                if (!ioctl_or_warn(fd, HDIO_GET_NOWERR, &parm))
1806                        print_value_on_off("nowerr", parm);
1807        }
1808        if (getset_readonly) {
1809                if (!ioctl_or_warn(fd, BLKROGET, &parm))
1810                        print_value_on_off("readonly", parm);
1811        }
1812        if (getset_readahead) {
1813                if (!ioctl_or_warn(fd, BLKRAGET, &parm))
1814                        print_value_on_off("readahead", parm);
1815        }
1816        if (get_geom) {
1817                if (!ioctl_or_warn(fd, BLKGETSIZE, &parm)) {
1818                        struct hd_geometry g;
1819
1820                        if (!ioctl_or_warn(fd, HDIO_GETGEO, &g))
1821                                printf(" geometry\t= %u/%u/%u, sectors = %ld, start = %ld\n",
1822                                        g.cylinders, g.heads, g.sectors, parm, g.start);
1823                }
1824        }
1825#ifdef HDIO_DRIVE_CMD
1826        if (get_powermode) {
1827#ifndef WIN_CHECKPOWERMODE1
1828#define WIN_CHECKPOWERMODE1 0xE5
1829#endif
1830#ifndef WIN_CHECKPOWERMODE2
1831#define WIN_CHECKPOWERMODE2 0x98
1832#endif
1833                const char *state;
1834
1835                args[0] = WIN_CHECKPOWERMODE1;
1836                if (ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2)) {
1837                        if (errno != EIO || args[0] != 0 || args[1] != 0)
1838                                state = "unknown";
1839                        else
1840                                state = "sleeping";
1841                } else
1842                        state = (args[2] == 255) ? "active/idle" : "standby";
1843                args[1] = args[2] = 0;
1844
1845                printf(" drive state is:  %s\n", state);
1846        }
1847#endif
1848#if ENABLE_FEATURE_HDPARM_HDIO_DRIVE_RESET
1849        if (perform_reset) {
1850                ioctl_or_warn(fd, HDIO_DRIVE_RESET, NULL);
1851        }
1852#endif /* FEATURE_HDPARM_HDIO_DRIVE_RESET */
1853#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
1854        if (perform_tristate) {
1855                args[0] = 0;
1856                args[1] = tristate;
1857                ioctl_or_warn(fd, HDIO_TRISTATE_HWIF, &args);
1858        }
1859#endif /* FEATURE_HDPARM_HDIO_TRISTATE_HWIF */
1860#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
1861        if (get_identity) {
1862                struct hd_driveid id;
1863
1864                if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) {
1865                        if (multcount != -1) {
1866                                id.multsect = multcount;
1867                                id.multsect_valid |= 1;
1868                        } else
1869                                id.multsect_valid &= ~1;
1870                        dump_identity(&id);
1871                } else if (errno == -ENOMSG)
1872                        printf(" no identification info available\n");
1873                else if (ENABLE_IOCTL_HEX2STR_ERROR)  /* To be coherent with ioctl_or_warn */
1874                        bb_perror_msg("HDIO_GET_IDENTITY");
1875                else
1876                        bb_perror_msg("ioctl %#x failed", HDIO_GET_IDENTITY);
1877        }
1878
1879        if (get_IDentity) {
1880                unsigned char args1[4+512]; /* = { ... } will eat 0.5k of rodata! */
1881
1882                memset(args1, 0, sizeof(args1));
1883                args1[0] = WIN_IDENTIFY;
1884                args1[3] = 1;
1885                if (!ioctl_alt_or_warn(HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY))
1886                        identify((void *)(args1 + 4));
1887        }
1888#endif
1889#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
1890        if (getset_busstate == IS_SET) {
1891                print_flag(1, "bus state", busstate);
1892                bus_state_value(busstate);
1893                ioctl_or_warn(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate);
1894        }
1895        if (getset_busstate) {
1896                if (!ioctl_or_warn(fd, HDIO_GET_BUSSTATE, &parm)) {
1897                        printf(fmt, "bus state", parm);
1898                        bus_state_value(parm);
1899                }
1900        }
1901#endif
1902        if (reread_partn)
1903                ioctl_or_warn(fd, BLKRRPART, NULL);
1904
1905        if (do_ctimings)
1906                do_time(1 /*,fd*/); /* time cache */
1907        if (do_timings)
1908                do_time(0 /*,fd*/); /* time device */
1909        if (do_flush)
1910                flush_buffer_cache();
1911        close(fd);
1912}
1913
1914#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
1915static int fromhex(unsigned char c)
1916{
1917        if (isdigit(c))
1918                return (c - '0');
1919        if (c >= 'a' && c <= 'f')
1920                return (c - ('a' - 10));
1921        bb_error_msg_and_die("bad char: '%c' 0x%02x", c, c);
1922}
1923
1924static void identify_from_stdin(void) NORETURN;
1925static void identify_from_stdin(void)
1926{
1927        uint16_t sbuf[256];
1928        unsigned char buf[1280];
1929        unsigned char *b = (unsigned char *)buf;
1930        int i;
1931
1932        xread(STDIN_FILENO, buf, 1280);
1933
1934        // Convert the newline-separated hex data into an identify block.
1935
1936        for (i = 0; i < 256; i++) {
1937                int j;
1938                for (j = 0; j < 4; j++)
1939                        sbuf[i] = (sbuf[i] << 4) + fromhex(*(b++));
1940        }
1941
1942        // Parse the data.
1943
1944        identify(sbuf);
1945}
1946#else
1947void identify_from_stdin(void);
1948#endif
1949
1950/* busybox specific stuff */
1951static int parse_opts(unsigned long *value, int min, int max)
1952{
1953        if (optarg) {
1954                *value = xatol_range(optarg, min, max);
1955                return IS_SET;
1956        }
1957        return IS_GET;
1958}
1959static int parse_opts_0_max(unsigned long *value, int max)
1960{
1961        return parse_opts(value, 0, max);
1962}
1963static int parse_opts_0_1(unsigned long *value)
1964{
1965        return parse_opts(value, 0, 1);
1966}
1967static int parse_opts_0_INTMAX(unsigned long *value)
1968{
1969        return parse_opts(value, 0, INT_MAX);
1970}
1971
1972static void parse_xfermode(int flag, smallint *get, smallint *set, int *value)
1973{
1974        if (flag) {
1975                *get = IS_GET;
1976                if (optarg) {
1977                        *value = translate_xfermode(optarg);
1978                        *set = (*value > -1);
1979                }
1980        }
1981}
1982
1983/*------- getopt short options --------*/
1984static const char hdparm_options[] ALIGN1 =
1985        "gfu::n::p:r::m::c::k::a::B:tT"
1986        IF_FEATURE_HDPARM_GET_IDENTITY("iI")
1987        IF_FEATURE_HDPARM_HDIO_GETSET_DMA("d::")
1988#ifdef HDIO_DRIVE_CMD
1989        "S:D:P:X:K:A:L:W:CyYzZ"
1990#endif
1991        IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("U:")
1992#ifdef HDIO_GET_QDMA
1993#ifdef HDIO_SET_QDMA
1994        "Q:"
1995#else
1996        "Q"
1997#endif
1998#endif
1999        IF_FEATURE_HDPARM_HDIO_DRIVE_RESET("w")
2000        IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF("x::b:")
2001        IF_FEATURE_HDPARM_HDIO_SCAN_HWIF("R:");
2002/*-------------------------------------*/
2003
2004/* our main() routine: */
2005int hdparm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
2006int hdparm_main(int argc, char **argv)
2007{
2008        int c;
2009        int flagcount = 0;
2010
2011        while ((c = getopt(argc, argv, hdparm_options)) >= 0) {
2012                flagcount++;
2013                IF_FEATURE_HDPARM_GET_IDENTITY(get_IDentity |= (c == 'I'));
2014                IF_FEATURE_HDPARM_GET_IDENTITY(get_identity |= (c == 'i'));
2015                get_geom |= (c == 'g');
2016                do_flush |= (c == 'f');
2017                if (c == 'u') getset_unmask    = parse_opts_0_1(&unmask);
2018        IF_FEATURE_HDPARM_HDIO_GETSET_DMA(
2019                if (c == 'd') getset_dma       = parse_opts_0_max(&dma, 9);
2020        )
2021                if (c == 'n') getset_nowerr    = parse_opts_0_1(&nowerr);
2022                parse_xfermode((c == 'p'), &noisy_piomode, &set_piomode, &piomode);
2023                if (c == 'r') getset_readonly  = parse_opts_0_1(&readonly);
2024                if (c == 'm') getset_mult      = parse_opts_0_INTMAX(&mult /*32*/);
2025                if (c == 'c') getset_io32bit   = parse_opts_0_INTMAX(&io32bit /*8*/);
2026                if (c == 'k') getset_keep      = parse_opts_0_1(&keep);
2027                if (c == 'a') getset_readahead = parse_opts_0_INTMAX(&Xreadahead);
2028                if (c == 'B') getset_apmmode   = parse_opts(&apmmode, 1, 255);
2029                do_flush |= do_timings |= (c == 't');
2030                do_flush |= do_ctimings |= (c == 'T');
2031#ifdef HDIO_DRIVE_CMD
2032                if (c == 'S') getset_standby  = parse_opts_0_max(&standby_requested, 255);
2033                if (c == 'D') getset_defects  = parse_opts_0_INTMAX(&defects);
2034                if (c == 'P') getset_prefetch = parse_opts_0_INTMAX(&prefetch);
2035                parse_xfermode((c == 'X'), &get_xfermode, &set_xfermode, &xfermode_requested);
2036                if (c == 'K') getset_dkeep     = parse_opts_0_1(&prefetch);
2037                if (c == 'A') getset_lookahead = parse_opts_0_1(&lookahead);
2038                if (c == 'L') getset_doorlock  = parse_opts_0_1(&doorlock);
2039                if (c == 'W') getset_wcache    = parse_opts_0_1(&wcache);
2040                get_powermode |= (c == 'C');
2041                set_standbynow |= (c == 'y');
2042                set_sleepnow |= (c == 'Y');
2043                reread_partn |= (c == 'z');
2044                set_seagate |= (c == 'Z');
2045#endif
2046                IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') unregister_hwif = parse_opts_0_INTMAX(&hwif));
2047#ifdef HDIO_GET_QDMA
2048                if (c == 'Q') {
2049                        getset_dma_q = parse_opts_0_INTMAX(&dma_q);
2050                }
2051#endif
2052                IF_FEATURE_HDPARM_HDIO_DRIVE_RESET(perform_reset = (c == 'r'));
2053                IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'x') perform_tristate = parse_opts_0_1(&tristate));
2054                IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'b') getset_busstate = parse_opts_0_max(&busstate, 2));
2055#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
2056                if (c == 'R') {
2057                        scan_hwif = parse_opts_0_INTMAX(&hwif_data);
2058                        hwif_ctrl = xatoi_positive((argv[optind]) ? argv[optind] : "");
2059                        hwif_irq  = xatoi_positive((argv[optind+1]) ? argv[optind+1] : "");
2060                        /* Move past the 2 additional arguments */
2061                        argv += 2;
2062                        argc -= 2;
2063                }
2064#endif
2065        }
2066        /* When no flags are given (flagcount = 0), -acdgkmnru is assumed. */
2067        if (!flagcount) {
2068                getset_mult = getset_io32bit = getset_unmask = getset_keep = getset_readonly = getset_readahead = get_geom = IS_GET;
2069                IF_FEATURE_HDPARM_HDIO_GETSET_DMA(getset_dma = IS_GET);
2070        }
2071        argv += optind;
2072
2073        if (!*argv) {
2074                if (ENABLE_FEATURE_HDPARM_GET_IDENTITY && !isatty(STDIN_FILENO))
2075                        identify_from_stdin(); /* EXIT */
2076                bb_show_usage();
2077        }
2078
2079        do {
2080                process_dev(*argv++);
2081        } while (*argv);
2082
2083        return EXIT_SUCCESS;
2084}
2085