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