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