Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/miscutils/hdparm.c

    r1765 r2725  
    66 * Hacked by Tito <farmatito@tiscali.it> for size optimization.
    77 *
    8  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 *
    1010 * This program is based on the source code of hdparm: see below...
     
    1212 *          - by Mark Lord (C) 1994-2002 -- freely distributable
    1313 */
    14 
    1514#include "libbb.h"
     15/* must be _after_ libbb.h: */
    1616#include <linux/hdreg.h>
     17#include <sys/mount.h>
     18#if !defined(BLKGETSIZE64)
     19# define BLKGETSIZE64 _IOR(0x12,114,size_t)
     20#endif
    1721
    1822/* device types */
     
    6064                    /* multiword DMA xfer cycle time: */
    6165#define DMA_TIME_MIN        65  /*   - minimum */
    62 #define DMA_TIME_NORM       66  /*   - manufacturer's recommended   */
     66#define DMA_TIME_NORM       66  /*   - manufacturer's recommended */
    6367                    /* minimum PIO xfer cycle time: */
    6468#define PIO_NO_FLOW     67  /*   - without flow control */
     
    8387#define ADV_PWR         91  /* current advanced power management level
    8488                       in low byte, 0x40 in high byte. */
    85 #define PSWD_CODE       92  /* master password revision code    */
     89#define PSWD_CODE       92  /* master password revision code */
    8690#define HWRST_RSLT      93  /* hardware reset result */
    8791#define ACOUSTIC        94  /* acoustic mgmt values ( >= ATA-6) */
     
    128132#define CDROM 0x0005
    129133
    130 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY
    131 static const char *const pkt_str[] = {
    132     "Direct-access device",         /* word 0, bits 12-8 = 00 */
    133     "Sequential-access device",     /* word 0, bits 12-8 = 01 */
    134     "Printer",              /* word 0, bits 12-8 = 02 */
    135     "Processor",                /* word 0, bits 12-8 = 03 */
    136     "Write-once device",            /* word 0, bits 12-8 = 04 */
    137     "CD-ROM",               /* word 0, bits 12-8 = 05 */
    138     "Scanner",              /* word 0, bits 12-8 = 06 */
    139     "Optical memory",           /* word 0, bits 12-8 = 07 */
    140     "Medium changer",           /* word 0, bits 12-8 = 08 */
    141     "Communications device",        /* word 0, bits 12-8 = 09 */
    142     "ACS-IT8 device",           /* word 0, bits 12-8 = 0a */
    143     "ACS-IT8 device",           /* word 0, bits 12-8 = 0b */
    144     "Array controller",         /* word 0, bits 12-8 = 0c */
    145     "Enclosure services",           /* word 0, bits 12-8 = 0d */
    146     "Reduced block command device",     /* word 0, bits 12-8 = 0e */
    147     "Optical card reader/writer",       /* word 0, bits 12-8 = 0f */
    148     "",                 /* word 0, bits 12-8 = 10 */
    149     "",                 /* word 0, bits 12-8 = 11 */
    150     "",                 /* word 0, bits 12-8 = 12 */
    151     "",                 /* word 0, bits 12-8 = 13 */
    152     "",                 /* word 0, bits 12-8 = 14 */
    153     "",                 /* word 0, bits 12-8 = 15 */
    154     "",                 /* word 0, bits 12-8 = 16 */
    155     "",                 /* word 0, bits 12-8 = 17 */
    156     "",                 /* word 0, bits 12-8 = 18 */
    157     "",                 /* word 0, bits 12-8 = 19 */
    158     "",                 /* word 0, bits 12-8 = 1a */
    159     "",                 /* word 0, bits 12-8 = 1b */
    160     "",                 /* word 0, bits 12-8 = 1c */
    161     "",                 /* word 0, bits 12-8 = 1d */
    162     "",                 /* word 0, bits 12-8 = 1e */
    163     "Unknown",          /* word 0, bits 12-8 = 1f */
    164 };
    165 
    166 static const char *const ata1_cfg_str[] = {         /* word 0 in ATA-1 mode */
    167     "Reserved",             /* bit 0 */
    168     "hard sectored",            /* bit 1 */
    169     "soft sectored",            /* bit 2 */
    170     "not MFM encoded ",         /* bit 3 */
    171     "head switch time > 15us",      /* bit 4 */
    172     "spindle motor control option",     /* bit 5 */
    173     "fixed drive",              /* bit 6 */
    174     "removable drive",          /* bit 7 */
    175     "disk xfer rate <= 5Mbs",       /* bit 8 */
    176     "disk xfer rate > 5Mbs, <= 10Mbs",  /* bit 9 */
    177     "disk xfer rate > 5Mbs",        /* bit 10 */
    178     "rotational speed tol.",        /* bit 11 */
    179     "data strobe offset option",        /* bit 12 */
    180     "track offset option",          /* bit 13 */
    181     "format speed tolerance gap reqd",  /* bit 14 */
    182     "ATAPI"                 /* bit 14 */
    183 };
    184 #endif
    185 
    186134/* word 1: number of logical cylinders */
    187135#define LCYLS_MAX       0x3fff /* maximum allowable value */
     
    239187/* word 81: minor version number */
    240188#define MINOR_MAX       0x22
     189/* words 82-84: cmds/feats supported */
     190#define CMDS_W82        0x77ff  /* word 82: defined command locations*/
     191#define CMDS_W83        0x3fff  /* word 83: defined command locations*/
     192#define CMDS_W84        0x002f  /* word 83: defined command locations*/
     193#define SUPPORT_48_BIT      0x0400
     194#define NUM_CMD_FEAT_STR    48
     195
     196/* words 85-87: cmds/feats enabled */
     197/* use cmd_feat_str[] to display what commands and features have
     198 * been enabled with words 85-87
     199 */
     200
     201/* words 89, 90, SECU ERASE TIME */
     202#define ERASE_BITS      0x00ff
     203
     204/* word 92: master password revision */
     205/* NOVAL_0 or  NOVAL_1 means no support for master password revision */
     206
     207/* word 93: hw reset result */
     208#define CBLID           0x2000  /* CBLID status */
     209#define RST0            0x0001  /* 1=reset to device #0 */
     210#define DEV_DET         0x0006  /* how device num determined */
     211#define JUMPER_VAL      0x0002  /* device num determined by jumper */
     212#define CSEL_VAL        0x0004  /* device num determined by CSEL_VAL */
     213
     214/* word 127: removable media status notification feature set support */
     215#define RM_STAT_BITS    0x0003
     216#define RM_STAT_SUP     0x0001
     217
     218/* word 128: security */
     219#define SECU_ENABLED    0x0002
     220#define SECU_LEVEL      0x0010
     221#define NUM_SECU_STR    6
     222
     223/* word 160: CFA power mode */
     224#define VALID_W160              0x8000  /* 1=word valid */
     225#define PWR_MODE_REQ            0x2000  /* 1=CFA power mode req'd by some cmds*/
     226#define PWR_MODE_OFF            0x1000  /* 1=CFA power moded disabled */
     227#define MAX_AMPS                0x0fff  /* value = max current in ma */
     228
     229/* word 255: integrity */
     230#define SIG                     0x00ff  /* signature location */
     231#define SIG_VAL                 0x00a5  /* signature value */
     232
     233#define TIMING_BUF_MB           1
     234#define TIMING_BUF_BYTES        (TIMING_BUF_MB * 1024 * 1024)
     235
     236#undef DO_FLUSHCACHE            /* under construction: force cache flush on -W0 */
     237
     238
     239#define IS_GET 1
     240#define IS_SET 2
     241
     242
     243enum { fd = 3 };
     244
     245
     246struct globals {
     247    smallint get_identity, get_geom;
     248    smallint do_flush;
     249    smallint do_ctimings, do_timings;
     250    smallint reread_partn;
     251    smallint set_piomode, noisy_piomode;
     252    smallint getset_readahead;
     253    smallint getset_readonly;
     254    smallint getset_unmask;
     255    smallint getset_mult;
     256#ifdef HDIO_GET_QDMA
     257    smallint getset_dma_q;
     258#endif
     259    smallint getset_nowerr;
     260    smallint getset_keep;
     261    smallint getset_io32bit;
     262    int piomode;
     263    unsigned long Xreadahead;
     264    unsigned long readonly;
     265    unsigned long unmask;
     266    unsigned long mult;
     267#ifdef HDIO_SET_QDMA
     268    unsigned long dma_q;
     269#endif
     270    unsigned long nowerr;
     271    unsigned long keep;
     272    unsigned long io32bit;
     273#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
     274    unsigned long dma;
     275    smallint getset_dma;
     276#endif
     277#ifdef HDIO_DRIVE_CMD
     278    smallint set_xfermode, get_xfermode;
     279    smallint getset_dkeep;
     280    smallint getset_standby;
     281    smallint getset_lookahead;
     282    smallint getset_prefetch;
     283    smallint getset_defects;
     284    smallint getset_wcache;
     285    smallint getset_doorlock;
     286    smallint set_seagate;
     287    smallint set_standbynow;
     288    smallint set_sleepnow;
     289    smallint get_powermode;
     290    smallint getset_apmmode;
     291    int xfermode_requested;
     292    unsigned long dkeep;
     293    unsigned long standby_requested; /* 0..255 */
     294    unsigned long lookahead;
     295    unsigned long prefetch;
     296    unsigned long defects;
     297    unsigned long wcache;
     298    unsigned long doorlock;
     299    unsigned long apmmode;
     300#endif
     301    IF_FEATURE_HDPARM_GET_IDENTITY(        smallint get_IDentity;)
     302    IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  smallint getset_busstate;)
     303    IF_FEATURE_HDPARM_HDIO_DRIVE_RESET(    smallint perform_reset;)
     304    IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  smallint perform_tristate;)
     305    IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(smallint unregister_hwif;)
     306    IF_FEATURE_HDPARM_HDIO_SCAN_HWIF(      smallint scan_hwif;)
     307    IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  unsigned long busstate;)
     308    IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  unsigned long tristate;)
     309    IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(unsigned long hwif;)
     310#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
     311    unsigned long hwif_data;
     312    unsigned long hwif_ctrl;
     313    unsigned long hwif_irq;
     314#endif
     315#ifdef DO_FLUSHCACHE
     316    unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };
     317#endif
     318} FIX_ALIASING;
     319#define G (*(struct globals*)&bb_common_bufsiz1)
     320struct BUG_G_too_big {
     321    char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
     322};
     323#define get_identity       (G.get_identity           )
     324#define get_geom           (G.get_geom               )
     325#define do_flush           (G.do_flush               )
     326#define do_ctimings        (G.do_ctimings            )
     327#define do_timings         (G.do_timings             )
     328#define reread_partn       (G.reread_partn           )
     329#define set_piomode        (G.set_piomode            )
     330#define noisy_piomode      (G.noisy_piomode          )
     331#define getset_readahead   (G.getset_readahead       )
     332#define getset_readonly    (G.getset_readonly        )
     333#define getset_unmask      (G.getset_unmask          )
     334#define getset_mult        (G.getset_mult            )
     335#define getset_dma_q       (G.getset_dma_q           )
     336#define getset_nowerr      (G.getset_nowerr          )
     337#define getset_keep        (G.getset_keep            )
     338#define getset_io32bit     (G.getset_io32bit         )
     339#define piomode            (G.piomode                )
     340#define Xreadahead         (G.Xreadahead             )
     341#define readonly           (G.readonly               )
     342#define unmask             (G.unmask                 )
     343#define mult               (G.mult                   )
     344#define dma_q              (G.dma_q                  )
     345#define nowerr             (G.nowerr                 )
     346#define keep               (G.keep                   )
     347#define io32bit            (G.io32bit                )
     348#define dma                (G.dma                    )
     349#define getset_dma         (G.getset_dma             )
     350#define set_xfermode       (G.set_xfermode           )
     351#define get_xfermode       (G.get_xfermode           )
     352#define getset_dkeep       (G.getset_dkeep           )
     353#define getset_standby     (G.getset_standby         )
     354#define getset_lookahead   (G.getset_lookahead       )
     355#define getset_prefetch    (G.getset_prefetch        )
     356#define getset_defects     (G.getset_defects         )
     357#define getset_wcache      (G.getset_wcache          )
     358#define getset_doorlock    (G.getset_doorlock        )
     359#define set_seagate        (G.set_seagate            )
     360#define set_standbynow     (G.set_standbynow         )
     361#define set_sleepnow       (G.set_sleepnow           )
     362#define get_powermode      (G.get_powermode          )
     363#define getset_apmmode     (G.getset_apmmode         )
     364#define xfermode_requested (G.xfermode_requested     )
     365#define dkeep              (G.dkeep                  )
     366#define standby_requested  (G.standby_requested      )
     367#define lookahead          (G.lookahead              )
     368#define prefetch           (G.prefetch               )
     369#define defects            (G.defects                )
     370#define wcache             (G.wcache                 )
     371#define doorlock           (G.doorlock               )
     372#define apmmode            (G.apmmode                )
     373#define get_IDentity       (G.get_IDentity           )
     374#define getset_busstate    (G.getset_busstate        )
     375#define perform_reset      (G.perform_reset          )
     376#define perform_tristate   (G.perform_tristate       )
     377#define unregister_hwif    (G.unregister_hwif        )
     378#define scan_hwif          (G.scan_hwif              )
     379#define busstate           (G.busstate               )
     380#define tristate           (G.tristate               )
     381#define hwif               (G.hwif                   )
     382#define hwif_data          (G.hwif_data              )
     383#define hwif_ctrl          (G.hwif_ctrl              )
     384#define hwif_irq           (G.hwif_irq               )
     385
     386
     387/* Busybox messages and functions */
     388#if ENABLE_IOCTL_HEX2STR_ERROR
     389static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt, const char *string)
     390{
     391    if (!ioctl(fd, cmd, args))
     392        return 0;
     393    args[0] = alt;
     394    return bb_ioctl_or_warn(fd, cmd, args, string);
     395}
     396#define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt,#cmd)
     397#else
     398static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt)
     399{
     400    if (!ioctl(fd, cmd, args))
     401        return 0;
     402    args[0] = alt;
     403    return bb_ioctl_or_warn(fd, cmd, args);
     404}
     405#define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt)
     406#endif
     407
     408static void on_off(int value)
     409{
     410    puts(value ? " (on)" : " (off)");
     411}
     412
     413static void print_flag_on_off(int get_arg, const char *s, unsigned long arg)
     414{
     415    if (get_arg) {
     416        printf(" setting %s to %ld", s, arg);
     417        on_off(arg);
     418    }
     419}
     420
     421static void print_value_on_off(const char *str, unsigned long argp)
     422{
     423    printf(" %s\t= %2ld", str, argp);
     424    on_off(argp != 0);
     425}
     426
    241427#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
    242 static const char *const minor_str[MINOR_MAX + 2] = {
     428static void print_ascii(const char *p, int length)
     429{
     430#if BB_BIG_ENDIAN
     431#define LE_ONLY(x)
     432    enum { ofs = 0 };
     433#else
     434#define LE_ONLY(x) x
     435    /* every 16bit word is big-endian (i.e. inverted) */
     436    /* accessing bytes in 1,0, 3,2, 5,4... sequence */
     437    int ofs = 1;
     438#endif
     439
     440    length *= 2;
     441    /* find first non-space & print it */
     442    while (length && p[ofs] != ' ') {
     443        p++;
     444        LE_ONLY(ofs = -ofs;)
     445        length--;
     446    }
     447    while (length && p[ofs]) {
     448        bb_putchar(p[ofs]);
     449        p++;
     450        LE_ONLY(ofs = -ofs;)
     451        length--;
     452    }
     453    bb_putchar('\n');
     454#undef LE_ONLY
     455}
     456
     457static void xprint_ascii(uint16_t *val, int i, const char *string, int n)
     458{
     459    if (val[i]) {
     460        printf("\t%-20s", string);
     461        print_ascii((void*)&val[i], n);
     462    }
     463}
     464
     465static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode)
     466{
     467    uint16_t ii;
     468    uint8_t err_dma = 0;
     469
     470    for (ii = 0; ii <= MODE_MAX; ii++) {
     471        if (mode_sel & 0x0001) {
     472            printf("*%cdma%u ", cc, ii);
     473            if (*have_mode)
     474                err_dma = 1;
     475            *have_mode = 1;
     476        } else if (mode_sup & 0x0001)
     477            printf("%cdma%u ", cc, ii);
     478
     479        mode_sup >>= 1;
     480        mode_sel >>= 1;
     481    }
     482    return err_dma;
     483}
     484
     485static const char pkt_str[] ALIGN1 =
     486    "Direct-access device" "\0"             /* word 0, bits 12-8 = 00 */
     487    "Sequential-access device" "\0"         /* word 0, bits 12-8 = 01 */
     488    "Printer" "\0"                          /* word 0, bits 12-8 = 02 */
     489    "Processor" "\0"                        /* word 0, bits 12-8 = 03 */
     490    "Write-once device" "\0"                /* word 0, bits 12-8 = 04 */
     491    "CD-ROM" "\0"                           /* word 0, bits 12-8 = 05 */
     492    "Scanner" "\0"                          /* word 0, bits 12-8 = 06 */
     493    "Optical memory" "\0"                   /* word 0, bits 12-8 = 07 */
     494    "Medium changer" "\0"                   /* word 0, bits 12-8 = 08 */
     495    "Communications device" "\0"            /* word 0, bits 12-8 = 09 */
     496    "ACS-IT8 device" "\0"                   /* word 0, bits 12-8 = 0a */
     497    "ACS-IT8 device" "\0"                   /* word 0, bits 12-8 = 0b */
     498    "Array controller" "\0"                 /* word 0, bits 12-8 = 0c */
     499    "Enclosure services" "\0"               /* word 0, bits 12-8 = 0d */
     500    "Reduced block command device" "\0"     /* word 0, bits 12-8 = 0e */
     501    "Optical card reader/writer" "\0"       /* word 0, bits 12-8 = 0f */
     502;
     503
     504static const char ata1_cfg_str[] ALIGN1 =       /* word 0 in ATA-1 mode */
     505    "reserved" "\0"                         /* bit 0 */
     506    "hard sectored" "\0"                    /* bit 1 */
     507    "soft sectored" "\0"                    /* bit 2 */
     508    "not MFM encoded " "\0"                 /* bit 3 */
     509    "head switch time > 15us" "\0"          /* bit 4 */
     510    "spindle motor control option" "\0"     /* bit 5 */
     511    "fixed drive" "\0"                      /* bit 6 */
     512    "removable drive" "\0"                  /* bit 7 */
     513    "disk xfer rate <= 5Mbs" "\0"           /* bit 8 */
     514    "disk xfer rate > 5Mbs, <= 10Mbs" "\0"  /* bit 9 */
     515    "disk xfer rate > 5Mbs" "\0"            /* bit 10 */
     516    "rotational speed tol." "\0"            /* bit 11 */
     517    "data strobe offset option" "\0"        /* bit 12 */
     518    "track offset option" "\0"              /* bit 13 */
     519    "format speed tolerance gap reqd" "\0"  /* bit 14 */
     520    "ATAPI"                                 /* bit 14 */
     521;
     522
     523static const char minor_str[] ALIGN1 =
    243524    /* word 81 value: */
    244     "Unspecified",                                  /* 0x0000 */
    245     "ATA-1 X3T9.2 781D prior to rev.4",             /* 0x0001 */
    246     "ATA-1 published, ANSI X3.221-1994",            /* 0x0002 */
    247     "ATA-1 X3T9.2 781D rev.4",                      /* 0x0003 */
    248     "ATA-2 published, ANSI X3.279-1996",            /* 0x0004 */
    249     "ATA-2 X3T10 948D prior to rev.2k",             /* 0x0005 */
    250     "ATA-3 X3T10 2008D rev.1",                      /* 0x0006 */
    251     "ATA-2 X3T10 948D rev.2k",                      /* 0x0007 */
    252     "ATA-3 X3T10 2008D rev.0",                      /* 0x0008 */
    253     "ATA-2 X3T10 948D rev.3",                       /* 0x0009 */
    254     "ATA-3 published, ANSI X3.298-199x",            /* 0x000a */
    255     "ATA-3 X3T10 2008D rev.6",                      /* 0x000b */
    256     "ATA-3 X3T13 2008D rev.7 and 7a",               /* 0x000c */
    257     "ATA/ATAPI-4 X3T13 1153D rev.6",                /* 0x000d */
    258     "ATA/ATAPI-4 T13 1153D rev.13",                 /* 0x000e */
    259     "ATA/ATAPI-4 X3T13 1153D rev.7",                /* 0x000f */
    260     "ATA/ATAPI-4 T13 1153D rev.18",                 /* 0x0010 */
    261     "ATA/ATAPI-4 T13 1153D rev.15",                 /* 0x0011 */
    262     "ATA/ATAPI-4 published, ANSI INCITS 317-1998",  /* 0x0012 */
    263     "ATA/ATAPI-5 T13 1321D rev.3",                  /* 0x0013 */
    264     "ATA/ATAPI-4 T13 1153D rev.14",                 /* 0x0014 */
    265     "ATA/ATAPI-5 T13 1321D rev.1",                  /* 0x0015 */
    266     "ATA/ATAPI-5 published, ANSI INCITS 340-2000",  /* 0x0016 */
    267     "ATA/ATAPI-4 T13 1153D rev.17",                 /* 0x0017 */
    268     "ATA/ATAPI-6 T13 1410D rev.0",                  /* 0x0018 */
    269     "ATA/ATAPI-6 T13 1410D rev.3a",                 /* 0x0019 */
    270     "ATA/ATAPI-7 T13 1532D rev.1",                  /* 0x001a */
    271     "ATA/ATAPI-6 T13 1410D rev.2",                  /* 0x001b */
    272     "ATA/ATAPI-6 T13 1410D rev.1",                  /* 0x001c */
    273     "ATA/ATAPI-7 published, ANSI INCITS 397-2005",  /* 0x001d */
    274     "ATA/ATAPI-7 T13 1532D rev.0",                  /* 0x001e */
    275     "Reserved"                                      /* 0x001f */
    276     "Reserved"                                      /* 0x0020 */
    277     "ATA/ATAPI-7 T13 1532D rev.4a",                 /* 0x0021 */
    278     "ATA/ATAPI-6 published, ANSI INCITS 361-2002",  /* 0x0022 */
    279     "Reserved"                                      /* 0x0023-0xfffe */
    280 };
    281 #endif
     525    "Unspecified" "\0"                                  /* 0x0000 */
     526    "ATA-1 X3T9.2 781D prior to rev.4" "\0"             /* 0x0001 */
     527    "ATA-1 published, ANSI X3.221-1994" "\0"            /* 0x0002 */
     528    "ATA-1 X3T9.2 781D rev.4" "\0"                      /* 0x0003 */
     529    "ATA-2 published, ANSI X3.279-1996" "\0"            /* 0x0004 */
     530    "ATA-2 X3T10 948D prior to rev.2k" "\0"             /* 0x0005 */
     531    "ATA-3 X3T10 2008D rev.1" "\0"                      /* 0x0006 */
     532    "ATA-2 X3T10 948D rev.2k" "\0"                      /* 0x0007 */
     533    "ATA-3 X3T10 2008D rev.0" "\0"                      /* 0x0008 */
     534    "ATA-2 X3T10 948D rev.3" "\0"                       /* 0x0009 */
     535    "ATA-3 published, ANSI X3.298-199x" "\0"            /* 0x000a */
     536    "ATA-3 X3T10 2008D rev.6" "\0"                      /* 0x000b */
     537    "ATA-3 X3T13 2008D rev.7 and 7a" "\0"               /* 0x000c */
     538    "ATA/ATAPI-4 X3T13 1153D rev.6" "\0"                /* 0x000d */
     539    "ATA/ATAPI-4 T13 1153D rev.13" "\0"                 /* 0x000e */
     540    "ATA/ATAPI-4 X3T13 1153D rev.7" "\0"                /* 0x000f */
     541    "ATA/ATAPI-4 T13 1153D rev.18" "\0"                 /* 0x0010 */
     542    "ATA/ATAPI-4 T13 1153D rev.15" "\0"                 /* 0x0011 */
     543    "ATA/ATAPI-4 published, ANSI INCITS 317-1998" "\0"  /* 0x0012 */
     544    "ATA/ATAPI-5 T13 1321D rev.3" "\0"                  /* 0x0013 */
     545    "ATA/ATAPI-4 T13 1153D rev.14" "\0"                 /* 0x0014 */
     546    "ATA/ATAPI-5 T13 1321D rev.1" "\0"                  /* 0x0015 */
     547    "ATA/ATAPI-5 published, ANSI INCITS 340-2000" "\0"  /* 0x0016 */
     548    "ATA/ATAPI-4 T13 1153D rev.17" "\0"                 /* 0x0017 */
     549    "ATA/ATAPI-6 T13 1410D rev.0" "\0"                  /* 0x0018 */
     550    "ATA/ATAPI-6 T13 1410D rev.3a" "\0"                 /* 0x0019 */
     551    "ATA/ATAPI-7 T13 1532D rev.1" "\0"                  /* 0x001a */
     552    "ATA/ATAPI-6 T13 1410D rev.2" "\0"                  /* 0x001b */
     553    "ATA/ATAPI-6 T13 1410D rev.1" "\0"                  /* 0x001c */
     554    "ATA/ATAPI-7 published, ANSI INCITS 397-2005" "\0"  /* 0x001d */
     555    "ATA/ATAPI-7 T13 1532D rev.0" "\0"                  /* 0x001e */
     556    "reserved" "\0"                                     /* 0x001f */
     557    "reserved" "\0"                                     /* 0x0020 */
     558    "ATA/ATAPI-7 T13 1532D rev.4a" "\0"                 /* 0x0021 */
     559    "ATA/ATAPI-6 published, ANSI INCITS 361-2002" "\0"  /* 0x0022 */
     560    "reserved"                                          /* 0x0023-0xfffe */
     561;
    282562static const char actual_ver[MINOR_MAX + 2] ALIGN1 = {
    283563       /* word 81 value: */
     
    320600};
    321601
    322 /* words 82-84: cmds/feats supported */
    323 #define CMDS_W82        0x77ff  /* word 82: defined command locations*/
    324 #define CMDS_W83        0x3fff  /* word 83: defined command locations*/
    325 #define CMDS_W84        0x002f  /* word 83: defined command locations*/
    326 #define SUPPORT_48_BIT      0x0400
    327 #define NUM_CMD_FEAT_STR    48
    328 
    329 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY
    330 static const char *const cmd_feat_str[] = {
    331     "",                 /* word 82 bit 15: obsolete  */
    332     "NOP cmd",              /* word 82 bit 14 */
    333     "READ BUFFER cmd",          /* word 82 bit 13 */
    334     "WRITE BUFFER cmd",         /* word 82 bit 12 */
    335     "",                 /* word 82 bit 11: obsolete  */
    336     "Host Protected Area feature set",  /* word 82 bit 10 */
    337     "DEVICE RESET cmd",         /* word 82 bit  9 */
    338     "SERVICE interrupt",            /* word 82 bit  8 */
    339     "Release interrupt",            /* word 82 bit  7 */
    340     "Look-ahead",               /* word 82 bit  6 */
    341     "Write cache",              /* word 82 bit  5 */
    342     "PACKET command feature set",       /* word 82 bit  4 */
    343     "Power Management feature set",     /* word 82 bit  3 */
    344     "Removable Media feature set",      /* word 82 bit  2 */
    345     "Security Mode feature set",        /* word 82 bit  1 */
    346     "SMART feature set",            /* word 82 bit  0 */
    347                         /* -------------- */
    348     "",                 /* word 83 bit 15: !valid bit */
    349     "",                 /* word 83 bit 14:  valid bit */
    350     "FLUSH CACHE EXT cmd",          /* word 83 bit 13 */
    351     "Mandatory FLUSH CACHE cmd ",       /* word 83 bit 12 */
    352     "Device Configuration Overlay feature set ",
    353     "48-bit Address feature set ",      /* word 83 bit 10 */
    354     "",
    355     "SET MAX security extension",       /* word 83 bit  8 */
    356     "Address Offset Reserved Area Boot",    /* word 83 bit  7 */
    357     "SET FEATURES subcommand required to spinup after power up",
    358     "Power-Up In Standby feature set",  /* word 83 bit  5 */
    359     "Removable Media Status Notification feature set",
    360     "Adv. Power Management feature set",    /* word 83 bit  3 */
    361     "CFA feature set",          /* word 83 bit  2 */
    362     "READ/WRITE DMA QUEUED",        /* word 83 bit  1 */
    363     "DOWNLOAD MICROCODE cmd",       /* word 83 bit  0 */
    364                         /* -------------- */
    365     "",                 /* word 84 bit 15: !valid bit */
    366     "",                 /* word 84 bit 14:  valid bit */
    367     "",                 /* word 84 bit 13:  reserved */
    368     "",                 /* word 84 bit 12:  reserved */
    369     "",                 /* word 84 bit 11:  reserved */
    370     "",                 /* word 84 bit 10:  reserved */
    371     "",                 /* word 84 bit  9:  reserved */
    372     "",                 /* word 84 bit  8:  reserved */
    373     "",                 /* word 84 bit  7:  reserved */
    374     "",                 /* word 84 bit  6:  reserved */
    375     "General Purpose Logging feature set",  /* word 84 bit  5 */
    376     "",                 /* word 84 bit  4:  reserved */
    377     "Media Card Pass Through Command feature set ",
    378     "Media serial number ",         /* word 84 bit  2 */
    379     "SMART self-test ",         /* word 84 bit  1 */
    380     "SMART error logging "          /* word 84 bit  0 */
    381 };
    382 
    383 static void identify(uint16_t *id_supplied) ATTRIBUTE_NORETURN;
    384 static void identify_from_stdin(void) ATTRIBUTE_NORETURN;
    385 #else
    386 void identify_from_stdin(void);
    387 #endif
    388 
    389 
    390 /* words 85-87: cmds/feats enabled */
    391 /* use cmd_feat_str[] to display what commands and features have
    392  * been enabled with words 85-87
    393  */
    394 
    395 /* words 89, 90, SECU ERASE TIME */
    396 #define ERASE_BITS      0x00ff
    397 
    398 /* word 92: master password revision */
    399 /* NOVAL_0 or  NOVAL_1 means no support for master password revision */
    400 
    401 /* word 93: hw reset result */
    402 #define CBLID           0x2000  /* CBLID status */
    403 #define RST0            0x0001  /* 1=reset to device #0 */
    404 #define DEV_DET         0x0006  /* how device num determined */
    405 #define JUMPER_VAL      0x0002  /* device num determined by jumper */
    406 #define CSEL_VAL        0x0004  /* device num determined by CSEL_VAL */
    407 
    408 /* word 127: removable media status notification feature set support */
    409 #define RM_STAT_BITS    0x0003
    410 #define RM_STAT_SUP     0x0001
    411 
    412 /* word 128: security */
    413 #define SECU_ENABLED    0x0002
    414 #define SECU_LEVEL      0x0010
    415 #define NUM_SECU_STR    6
    416 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY
    417 static const char *const secu_str[] = {
    418     "supported",            /* word 128, bit 0 */
    419     "enabled",          /* word 128, bit 1 */
    420     "locked",           /* word 128, bit 2 */
    421     "frozen",           /* word 128, bit 3 */
    422     "expired: security count",  /* word 128, bit 4 */
    423     "supported: enhanced erase" /* word 128, bit 5 */
    424 };
    425 #endif
    426 
    427 /* word 160: CFA power mode */
    428 #define VALID_W160              0x8000  /* 1=word valid */
    429 #define PWR_MODE_REQ            0x2000  /* 1=CFA power mode req'd by some cmds*/
    430 #define PWR_MODE_OFF            0x1000  /* 1=CFA power moded disabled */
    431 #define MAX_AMPS                0x0fff  /* value = max current in ma */
    432 
    433 /* word 255: integrity */
    434 #define SIG                     0x00ff  /* signature location */
    435 #define SIG_VAL                 0x00a5  /* signature value */
    436 
    437 #define TIMING_MB               64
    438 #define TIMING_BUF_MB           1
    439 #define TIMING_BUF_BYTES        (TIMING_BUF_MB * 1024 * 1024)
    440 #define BUFCACHE_FACTOR         2
    441 
    442 #undef DO_FLUSHCACHE            /* under construction: force cache flush on -W0 */
    443 
    444 /* Busybox messages and functions */
    445 #if ENABLE_IOCTL_HEX2STR_ERROR
    446 static int ioctl_alt_func(int fd, int cmd, unsigned char *args, int alt, const char *string)
    447 {
    448     if (!ioctl(fd, cmd, args))
    449         return 0;
    450     args[0] = alt;
    451     return bb_ioctl_or_warn(fd, cmd, args, string);
    452 }
    453 #define ioctl_alt_or_warn(fd,cmd,args,alt) ioctl_alt_func(fd,cmd,args,alt,#cmd)
    454 #else
    455 static int ioctl_alt_func(int fd, int cmd, unsigned char *args, int alt)
    456 {
    457     if (!ioctl(fd, cmd, args))
    458         return 0;
    459     args[0] = alt;
    460     return bb_ioctl_or_warn(fd, cmd, args);
    461 }
    462 #define ioctl_alt_or_warn(fd,cmd,args,alt) ioctl_alt_func(fd,cmd,args,alt)
    463 #endif
    464 
    465 static void on_off(int value)
    466 {
    467     puts(value ? " (on)" : " (off)");
    468 }
    469 
    470 static void print_flag_on_off(int get_arg, const char *s, unsigned long arg)
    471 {
    472     if (get_arg) {
    473         printf(" setting %s to %ld", s, arg);
    474         on_off(arg);
    475     }
    476 }
    477 
    478 static void print_value_on_off(const char *str, unsigned long argp)
    479 {
    480     printf(" %s\t= %2ld", str, argp);
    481     on_off(argp != 0);
    482 }
    483 
    484 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY
    485 static void print_ascii(uint16_t *p, uint8_t length);
    486 
    487 static void xprint_ascii(uint16_t *val, int i, const char *string, int n)
    488 {
    489     if (val[i]) {
    490         printf("\t%-20s", string);
    491         print_ascii(&val[i], n);
    492     }
    493 }
    494 #endif
    495 /* end of busybox specific stuff */
    496 
    497 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY
    498 static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode)
    499 {
    500     uint16_t ii;
    501     uint8_t err_dma = 0;
    502 
    503     for (ii = 0; ii <= MODE_MAX; ii++) {
    504         if (mode_sel & 0x0001) {
    505             printf("*%cdma%u ", cc, ii);
    506             if (*have_mode)
    507                 err_dma = 1;
    508             *have_mode = 1;
    509         } else if (mode_sup & 0x0001)
    510             printf("%cdma%u ", cc, ii);
    511 
    512         mode_sup >>= 1;
    513         mode_sel >>= 1;
    514     }
    515     return err_dma;
    516 }
    517 
    518 static void print_ascii(uint16_t *p, uint8_t length)
    519 {
    520     uint8_t ii;
    521     char cl;
    522 
    523     /* find first non-space & print it */
    524     for (ii = 0; ii < length; ii++) {
    525         if ((char)((*p)>>8) != ' ')
    526             break;
    527         cl = (char)(*p);
    528         if (cl != ' ') {
    529             if (cl != '\0')
    530                 printf("%c", cl);
    531             p++;
    532             ii++;
    533             break;
    534         }
    535         p++;
    536     }
    537     /* print the rest */
    538     for (; ii< length; ii++) {
    539         if (!(*p))
    540             break; /* some older devices have NULLs */
    541         printf("%c%c", (char)((*p)>>8), (char)(*p));
    542         p++;
    543     }
    544     puts("");
    545 }
     602static const char cmd_feat_str[] ALIGN1 =
     603    "" "\0"                                     /* word 82 bit 15: obsolete  */
     604    "NOP cmd" "\0"                              /* word 82 bit 14 */
     605    "READ BUFFER cmd" "\0"                      /* word 82 bit 13 */
     606    "WRITE BUFFER cmd" "\0"                     /* word 82 bit 12 */
     607    "" "\0"                                     /* word 82 bit 11: obsolete  */
     608    "Host Protected Area feature set" "\0"      /* word 82 bit 10 */
     609    "DEVICE RESET cmd" "\0"                     /* word 82 bit  9 */
     610    "SERVICE interrupt" "\0"                    /* word 82 bit  8 */
     611    "Release interrupt" "\0"                    /* word 82 bit  7 */
     612    "Look-ahead" "\0"                           /* word 82 bit  6 */
     613    "Write cache" "\0"                          /* word 82 bit  5 */
     614    "PACKET command feature set" "\0"           /* word 82 bit  4 */
     615    "Power Management feature set" "\0"         /* word 82 bit  3 */
     616    "Removable Media feature set" "\0"          /* word 82 bit  2 */
     617    "Security Mode feature set" "\0"            /* word 82 bit  1 */
     618    "SMART feature set" "\0"                    /* word 82 bit  0 */
     619                                                /* -------------- */
     620    "" "\0"                                     /* word 83 bit 15: !valid bit */
     621    "" "\0"                                     /* word 83 bit 14:  valid bit */
     622    "FLUSH CACHE EXT cmd" "\0"                  /* word 83 bit 13 */
     623    "Mandatory FLUSH CACHE cmd " "\0"           /* word 83 bit 12 */
     624    "Device Configuration Overlay feature set " "\0"
     625    "48-bit Address feature set " "\0"          /* word 83 bit 10 */
     626    "" "\0"
     627    "SET MAX security extension" "\0"           /* word 83 bit  8 */
     628    "Address Offset Reserved Area Boot" "\0"    /* word 83 bit  7 */
     629    "SET FEATURES subcommand required to spinup after power up" "\0"
     630    "Power-Up In Standby feature set" "\0"      /* word 83 bit  5 */
     631    "Removable Media Status Notification feature set" "\0"
     632    "Adv. Power Management feature set" "\0"    /* word 83 bit  3 */
     633    "CFA feature set" "\0"                      /* word 83 bit  2 */
     634    "READ/WRITE DMA QUEUED" "\0"                /* word 83 bit  1 */
     635    "DOWNLOAD MICROCODE cmd" "\0"               /* word 83 bit  0 */
     636                                                /* -------------- */
     637    "" "\0"                                     /* word 84 bit 15: !valid bit */
     638    "" "\0"                                     /* word 84 bit 14:  valid bit */
     639    "" "\0"                                     /* word 84 bit 13:  reserved */
     640    "" "\0"                                     /* word 84 bit 12:  reserved */
     641    "" "\0"                                     /* word 84 bit 11:  reserved */
     642    "" "\0"                                     /* word 84 bit 10:  reserved */
     643    "" "\0"                                     /* word 84 bit  9:  reserved */
     644    "" "\0"                                     /* word 84 bit  8:  reserved */
     645    "" "\0"                                     /* word 84 bit  7:  reserved */
     646    "" "\0"                                     /* word 84 bit  6:  reserved */
     647    "General Purpose Logging feature set" "\0"  /* word 84 bit  5 */
     648    "" "\0"                                     /* word 84 bit  4:  reserved */
     649    "Media Card Pass Through Command feature set " "\0"
     650    "Media serial number " "\0"                 /* word 84 bit  2 */
     651    "SMART self-test " "\0"                     /* word 84 bit  1 */
     652    "SMART error logging "                      /* word 84 bit  0 */
     653;
     654
     655static const char secu_str[] ALIGN1 =
     656    "supported" "\0"                /* word 128, bit 0 */
     657    "enabled" "\0"                  /* word 128, bit 1 */
     658    "locked" "\0"                   /* word 128, bit 2 */
     659    "frozen" "\0"                   /* word 128, bit 3 */
     660    "expired: security count" "\0"  /* word 128, bit 4 */
     661    "supported: enhanced erase"     /* word 128, bit 5 */
     662;
    546663
    547664// Parse 512 byte disk identification block and print much crap.
    548 
    549 static void identify(uint16_t *id_supplied)
    550 {
    551     uint16_t buf[256];
    552     uint16_t *val, ii, jj, kk;
     665static void identify(uint16_t *val) NORETURN;
     666static void identify(uint16_t *val)
     667{
     668    uint16_t ii, jj, kk;
    553669    uint16_t like_std = 1, std = 0, min_std = 0xffff;
    554670    uint16_t dev = NO_DEV, eqpt = NO_DEV;
     
    558674    uint64_t bbbig; /* (:) */
    559675    const char *strng;
    560 
    561     // Adjust for endianness if necessary.
    562 
    563     if (BB_BIG_ENDIAN) {
    564         swab(id_supplied, buf, sizeof(buf));
    565         val = buf;
    566     } else
    567         val = id_supplied;
    568 
    569     chksum &= 0xff;
    570 
    571     /* check if we recognise the device type */
    572     puts("");
     676#if BB_BIG_ENDIAN
     677    uint16_t buf[256];
     678
     679    // Adjust for endianness
     680    swab(val, buf, sizeof(buf));
     681    val = buf;
     682#endif
     683    /* check if we recognize the device type */
     684    bb_putchar('\n');
    573685    if (!(val[GEN_CONFIG] & NOT_ATA)) {
    574686        dev = ATA_DEV;
     
    581693        dev = ATAPI_DEV;
    582694        eqpt = (val[GEN_CONFIG] & EQPT_TYPE) >> SHIFT_EQPT;
    583         printf("ATAPI %s, with ", pkt_str[eqpt]);
     695        printf("ATAPI %s, with ", eqpt <= 0xf ? nth_string(pkt_str, eqpt) : "unknown");
    584696        like_std = 3;
    585697    } else
    586         /*"Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n"*/
     698        /* "Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n" */
    587699        bb_error_msg_and_die("unknown device type");
    588700
     
    619731            if (like_std < 3) like_std = 3;
    620732            std = actual_ver[val[MINOR]];
    621             if (std) printf("\n\tUsed: %s ", minor_str[val[MINOR]]);
    622 
     733            if (std)
     734                printf("\n\tUsed: %s ", nth_string(minor_str, val[MINOR]));
    623735        }
    624736        /* looks like when they up-issue the std, they obsolete one;
     
    687799            printf("& some of %u\n", like_std);
    688800        else
    689             puts("");
     801            bb_putchar('\n');
    690802    } else {
    691803        /* TBD: do CDROM stuff more thoroughly.  For now... */
     
    704816            }
    705817        }
    706         printf("%s\n", kk ? "" : "\n\tLikely used CD-ROM ATAPI-1");
     818        puts(kk ? "" : "\n\tLikely used CD-ROM ATAPI-1");
    707819        /* the cdrom stuff is more like ATA-2 than anything else, so: */
    708820        like_std = 2;
     
    718830        for (ii = 1; ii < 15; ii++) {
    719831            if (jj & 0x0001)
    720                 printf("\t%s\n", ata1_cfg_str[ii]);
     832                printf("\t%s\n", nth_string(ata1_cfg_str, ii));
    721833            jj >>=1;
    722834        }
     
    730842            strng ="50us";
    731843        else
    732             strng = "Unknown";
     844            strng = "unknown";
    733845        printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */
    734846
     
    738850            strng = "16 bytes";
    739851        else
    740             strng = "Unknown";
     852            strng = "unknown";
    741853        puts(strng);
    742854    } else {
    743855        /* addressing...CHS? See section 6.2 of ATA specs 4 or 5 */
    744856        ll = (uint32_t)val[LBA_SECTS_MSB] << 16 | val[LBA_SECTS_LSB];
    745         mm = 0; bbbig = 0;
     857        mm = 0;
     858        bbbig = 0;
    746859        if ((ll > 0x00FBFC10) && (!val[LCYLS]))
    747860            printf("\tCHS addressing not supported\n");
    748861        else {
    749862            jj = val[WHATS_VALID] & OK_W54_58;
    750             printf("\tLogical\t\tmax\tcurrent\n\tcylinders\t%u\t%u\n\theads\t\t%u\t%u\n\tsectors/track\t%u\t%u\n\t--\n",
    751                     val[LCYLS],jj?val[LCYLS_CUR]:0, val[LHEADS],jj?val[LHEADS_CUR]:0, val[LSECTS],jj?val[LSECTS_CUR]:0);
     863            printf("\tLogical\t\tmax\tcurrent\n"
     864                "\tcylinders\t%u\t%u\n"
     865                "\theads\t\t%u\t%u\n"
     866                "\tsectors/track\t%u\t%u\n"
     867                "\t--\n",
     868                val[LCYLS],
     869                jj ? val[LCYLS_CUR] : 0,
     870                val[LHEADS],
     871                jj ? val[LHEADS_CUR] : 0,
     872                val[LSECTS],
     873                jj ? val[LSECTS_CUR] : 0);
    752874
    753875            if ((min_std == 1) && (val[TRACK_BYTES] || val[SECT_BYTES]))
    754                 printf("\tbytes/track: %u\tbytes/sector: %u\n", val[TRACK_BYTES], val[SECT_BYTES]);
     876                printf("\tbytes/track: %u\tbytes/sector: %u\n",
     877                    val[TRACK_BYTES], val[SECT_BYTES]);
    755878
    756879            if (jj) {
     
    787910            printf("(%"PRIu64" GB)\n", bbbig/1000);
    788911        else
    789             puts("");
     912            bb_putchar('\n');
    790913    }
    791914
     
    794917
    795918    if (dev == ATAPI_DEV) {
    796         if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP)) printf("Cmd queuing, ");
    797         if (val[CAPAB_0] & OVLP_SUP) printf("Cmd overlap, ");
     919        if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP))
     920            printf("Cmd queuing, ");
     921        if (val[CAPAB_0] & OVLP_SUP)
     922            printf("Cmd overlap, ");
    798923    }
    799924    if (val[CAPAB_0] & LBA_SUP) printf("LBA, ");
     
    801926    if (like_std != 1) {
    802927        printf("IORDY%s(can%s be disabled)\n",
    803                 !(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "",
    804                 (val[CAPAB_0] & IORDY_OFF) ? "" :"not");
     928            !(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "",
     929            (val[CAPAB_0] & IORDY_OFF) ? "" :"not");
    805930    } else
    806931        printf("no IORDY\n");
     
    808933    if ((like_std == 1) && val[BUF_TYPE]) {
    809934        printf("\tBuffer type: %04x: %s%s\n", val[BUF_TYPE],
    810                 (val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector",
    811                 (val[BUF_TYPE] > 2) ? " with read caching ability" : "");
     935            (val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector",
     936            (val[BUF_TYPE] > 2) ? " with read caching ability" : "");
    812937    }
    813938
     
    826951            printf("\tCan%s perform double-word IO\n", (!val[DWORD_IO]) ? "not" : "");
    827952        else {
    828             printf("\tStandby timer values: spec'd by %s", (val[CAPAB_0] & STD_STBY) ? "Standard" : "Vendor");
     953            printf("\tStandby timer values: spec'd by %s",
     954                (val[CAPAB_0] & STD_STBY) ? "standard" : "vendor");
    829955            if ((like_std > 3) && ((val[CAPAB_1] & VALID) == VALID_VAL))
    830                 printf(", %s device specific minimum\n", (val[CAPAB_1] & MIN_STANDBY_TIMER) ? "with" : "no");
     956                printf(", %s device specific minimum\n",
     957                    (val[CAPAB_1] & MIN_STANDBY_TIMER) ? "with" : "no");
    831958            else
    832                 puts("");
     959                bb_putchar('\n');
    833960        }
    834961        printf("\tR/W multiple sector transfer: ");
     
    856983        if (like_std > 5 && val[ACOUSTIC]) {
    857984            printf("\tRecommended acoustic management value: %u, current value: %u\n",
    858                     (val[ACOUSTIC] >> 8) & 0x00ff, val[ACOUSTIC] & 0x00ff);
     985                (val[ACOUSTIC] >> 8) & 0x00ff,
     986                val[ACOUSTIC] & 0x00ff);
    859987        }
    860988    } else {
     
    865993        if (val[PKT_REL] || val[SVC_NBSY]) {
    866994            printf("\tOverlap support:");
    867             if (val[PKT_REL]) printf(" %uus to release bus.", val[PKT_REL]);
    868             if (val[SVC_NBSY]) printf(" %uus to clear BSY after SERVICE cmd.", val[SVC_NBSY]);
    869             puts("");
     995            if (val[PKT_REL])
     996                printf(" %uus to release bus.", val[PKT_REL]);
     997            if (val[SVC_NBSY])
     998                printf(" %uus to clear BSY after SERVICE cmd.",
     999                    val[SVC_NBSY]);
     1000            bb_putchar('\n');
    8701001        }
    8711002    }
     
    8941025        }
    8951026        if (err_dma || !have_mode) printf("(?)");
    896         puts("");
     1027        bb_putchar('\n');
    8971028
    8981029        if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP))
     
    9051036            if (val[DMA_TIME_MIN]) printf(" min=%uns", val[DMA_TIME_MIN]);
    9061037            if (val[DMA_TIME_NORM]) printf(" recommended=%uns", val[DMA_TIME_NORM]);
    907             puts("");
     1038            bb_putchar('\n');
    9081039        }
    9091040    }
     
    9191050            jj >>=1;
    9201051        }
    921         puts("");
     1052        bb_putchar('\n');
    9221053    } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) {
    9231054        for (ii = 0; ii <= val[PIO_MODE]>>8; ii++)
    9241055            printf("pio%d ", ii);
    925         puts("");
     1056        bb_putchar('\n');
    9261057    } else
    927         printf("unknown\n");
     1058        puts("unknown");
    9281059
    9291060    if (val[WHATS_VALID] & OK_W64_70) {
    9301061        if (val[PIO_NO_FLOW] || val[PIO_FLOW]) {
    9311062            printf("\t\tCycle time:");
    932             if (val[PIO_NO_FLOW]) printf(" no flow control=%uns", val[PIO_NO_FLOW]);
    933             if (val[PIO_FLOW]) printf("  IORDY flow control=%uns", val[PIO_FLOW]);
    934             puts("");
     1063            if (val[PIO_NO_FLOW])
     1064                printf(" no flow control=%uns", val[PIO_NO_FLOW]);
     1065            if (val[PIO_FLOW])
     1066                printf("  IORDY flow control=%uns", val[PIO_FLOW]);
     1067            bb_putchar('\n');
    9351068        }
    9361069    }
    9371070
    9381071    if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) {
    939         printf("Commands/features:\n\tEnabled\tSupported:\n");
     1072        printf("Commands/features:\n"
     1073            "\tEnabled\tSupported:\n");
    9401074        jj = val[CMDS_SUPP_0];
    9411075        kk = val[CMDS_EN_0];
    9421076        for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++) {
    943             if ((jj & 0x8000) && (*cmd_feat_str[ii] != '\0')) {
    944                 printf("\t%s\t%s\n", (kk & 0x8000) ? "   *" : "", cmd_feat_str[ii]);
     1077            const char *feat_str = nth_string(cmd_feat_str, ii);
     1078            if ((jj & 0x8000) && (*feat_str != '\0')) {
     1079                printf("\t%s\t%s\n", (kk & 0x8000) ? "   *" : "", feat_str);
    9451080            }
    9461081            jj <<= 1;
     
    9581093    /* Removable Media Status Notification feature set */
    9591094    if ((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP)
    960         printf("\t%s supported\n", cmd_feat_str[27]);
     1095        printf("\t%s supported\n", nth_string(cmd_feat_str, 27));
    9611096
    9621097    /* security */
     
    9701105        if (jj) {
    9711106            for (ii = 0; ii < NUM_SECU_STR; ii++) {
    972                 printf("\t%s\t%s\n", (!(jj & 0x0001)) ? "not" : "",  secu_str[ii]);
     1107                printf("\t%s\t%s\n",
     1108                    (!(jj & 0x0001)) ? "not" : "",
     1109                    nth_string(secu_str, ii));
    9731110                jj >>=1;
    9741111            }
    9751112            if (val[SECU_STATUS] & SECU_ENABLED) {
    976                 printf("\tSecurity level %s\n", (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high");
     1113                printf("\tSecurity level %s\n",
     1114                    (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high");
    9771115            }
    9781116        }
     
    9801118        kk =  val[ENH_ERASE_TIME] & ERASE_BITS;
    9811119        if (jj || kk) {
    982             printf("\t");
     1120            bb_putchar('\t');
    9831121            if (jj) printf("%umin for %sSECURITY ERASE UNIT. ", jj==ERASE_BITS ? 508 : jj<<1, "");
    9841122            if (kk) printf("%umin for %sSECURITY ERASE UNIT. ", kk==ERASE_BITS ? 508 : kk<<1, "ENHANCED ");
    985             puts("");
     1123            bb_putchar('\n');
    9861124        }
    9871125    }
     
    9901128    jj = val[HWRST_RSLT];
    9911129    if ((jj & VALID) == VALID_VAL) {
    992         if (!(oo = (jj & RST0)))
     1130        oo = (jj & RST0);
     1131        if (!oo)
    9931132            jj >>= 8;
    9941133        if ((jj & DEV_DET) == JUMPER_VAL)
     
    9981137        else
    9991138            strng = "";
    1000         printf("HW reset results:\n\tCBLID- %s Vih\n\tDevice num = %i%s\n",
    1001                 (val[HWRST_RSLT] & CBLID) ? "above" : "below", !(oo), strng);
     1139        printf("HW reset results:\n"
     1140            "\tCBLID- %s Vih\n"
     1141            "\tDevice num = %i%s\n",
     1142            (val[HWRST_RSLT] & CBLID) ? "above" : "below",
     1143            !(oo), strng);
    10021144    }
    10031145
     
    10051147    if ((like_std > 4) && (eqpt != CDROM)) {
    10061148        if (val[CFA_PWR_MODE] & VALID_W160) {
    1007             printf("CFA power mode 1:\n\t%s%s\n", (val[CFA_PWR_MODE] & PWR_MODE_OFF) ? "disabled" : "enabled",
    1008                     (val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : "");
    1009 
     1149            printf("CFA power mode 1:\n"
     1150                "\t%s%s\n",
     1151                (val[CFA_PWR_MODE] & PWR_MODE_OFF) ? "disabled" : "enabled",
     1152                (val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : "");
    10101153            if (val[CFA_PWR_MODE] & MAX_AMPS)
    10111154                printf("\tMaximum current = %uma\n", val[CFA_PWR_MODE] & MAX_AMPS);
     
    10181161    exit(EXIT_SUCCESS);
    10191162}
    1020 #endif
    1021 
    1022 static smallint get_identity, get_geom;
    1023 static smallint do_flush;
    1024 static smallint do_ctimings, do_timings;
    1025 static smallint reread_partn;
    1026 
    1027 static smallint set_piomode, noisy_piomode;
    1028 static smallint set_readahead, get_readahead;
    1029 static smallint set_readonly, get_readonly;
    1030 static smallint set_unmask, get_unmask;
    1031 static smallint set_mult, get_mult;
    1032 static smallint set_dma_q, get_dma_q;
    1033 static smallint set_nowerr, get_nowerr;
    1034 static smallint set_keep, get_keep;
    1035 static smallint set_io32bit, get_io32bit;
    1036 static int piomode;
    1037 static unsigned long Xreadahead;
    1038 static unsigned long readonly;
    1039 static unsigned long unmask;
    1040 static unsigned long mult;
    1041 static unsigned long dma_q;
    1042 static unsigned long nowerr;
    1043 static unsigned long keep;
    1044 static unsigned long io32bit;
    1045 #if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
    1046 static unsigned long dma;
    1047 static smallint set_dma, get_dma;
    1048 #endif
    1049 #ifdef HDIO_DRIVE_CMD
    1050 static smallint set_xfermode, get_xfermode;
    1051 static smallint set_dkeep, get_dkeep;
    1052 static smallint set_standby, get_standby;
    1053 static smallint set_lookahead, get_lookahead;
    1054 static smallint set_prefetch, get_prefetch;
    1055 static smallint set_defects, get_defects;
    1056 static smallint set_wcache, get_wcache;
    1057 static smallint set_doorlock, get_doorlock;
    1058 static smallint set_seagate, get_seagate;
    1059 static smallint set_standbynow, get_standbynow;
    1060 static smallint set_sleepnow, get_sleepnow;
    1061 static smallint get_powermode;
    1062 static smallint set_apmmode, get_apmmode;
    1063 static int xfermode_requested;
    1064 static unsigned long dkeep;
    1065 static unsigned long standby_requested;
    1066 static unsigned long lookahead;
    1067 static unsigned long prefetch;
    1068 static unsigned long defects;
    1069 static unsigned long wcache;
    1070 static unsigned long doorlock;
    1071 static unsigned long apmmode;
    1072 #endif
    1073 USE_FEATURE_HDPARM_GET_IDENTITY(        static smallint get_IDentity;)
    1074 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  static smallint set_busstate, get_busstate;)
    1075 USE_FEATURE_HDPARM_HDIO_DRIVE_RESET(    static smallint perform_reset;)
    1076 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  static smallint perform_tristate;)
    1077 USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(static smallint unregister_hwif;)
    1078 USE_FEATURE_HDPARM_HDIO_SCAN_HWIF(      static smallint scan_hwif;)
    1079 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  static unsigned long busstate;)
    1080 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  static unsigned long tristate;)
    1081 USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(static unsigned long hwif;)
    1082 #if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
    1083 static unsigned long hwif_data;
    1084 static unsigned long hwif_ctrl;
    1085 static unsigned long hwif_irq;
    10861163#endif
    10871164
     
    10981175
    10991176#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
    1100 static const char *const cfg_str[] = {
    1101     "",      "HardSect",   "SoftSect",   "NotMFM",
    1102     "HdSw>15uSec", "SpinMotCtl", "Fixed",     "Removeable",
    1103     "DTR<=5Mbs",   "DTR>5Mbs",   "DTR>10Mbs", "RotSpdTol>.5%",
    1104     "dStbOff",     "TrkOff",     "FmtGapReq", "nonMagnetic"
    1105 };
    1106 
    1107 static const char *const BuffType[] = {
    1108     "Unknown", "1Sect", "DualPort", "DualPortCache"
    1109 };
    1110 
    1111 static void dump_identity(const struct hd_driveid *id)
     1177static const char cfg_str[] ALIGN1 =
     1178    """\0"            "HardSect""\0"   "SoftSect""\0"  "NotMFM""\0"
     1179    "HdSw>15uSec""\0" "SpinMotCtl""\0" "Fixed""\0"     "Removeable""\0"
     1180    "DTR<=5Mbs""\0"   "DTR>5Mbs""\0"   "DTR>10Mbs""\0" "RotSpdTol>.5%""\0"
     1181    "dStbOff""\0"     "TrkOff""\0"     "FmtGapReq""\0" "nonMagnetic"
     1182;
     1183
     1184static const char BuffType[] ALIGN1 =
     1185    "unknown""\0"     "1Sect""\0"      "DualPort""\0" "DualPortCache"
     1186;
     1187
     1188static NOINLINE void dump_identity(const struct hd_driveid *id)
    11121189{
    11131190    int i;
    1114     const unsigned short int *id_regs = (const void*) id;
     1191    const unsigned short *id_regs = (const void*) id;
    11151192
    11161193    printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n Config={",
     
    11181195    for (i = 0; i <= 15; i++) {
    11191196        if (id->config & (1<<i))
    1120             printf(" %s", cfg_str[i]);
     1197            printf(" %s", nth_string(cfg_str, i));
    11211198    }
    11221199    printf(" }\n RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n"
    1123             " BuffType=(%u) %s, BuffSize=%ukB, MaxMultSect=%u",
    1124                 id->cyls, id->heads, id->sectors, id->track_bytes,
    1125                 id->sector_bytes, id->ecc_bytes,
    1126                 id->buf_type, BuffType[(id->buf_type > 3) ? 0 :  id->buf_type],
    1127                 id->buf_size/2, id->max_multsect);
     1200        " BuffType=(%u) %s, BuffSize=%ukB, MaxMultSect=%u",
     1201        id->cyls, id->heads, id->sectors, id->track_bytes,
     1202        id->sector_bytes, id->ecc_bytes,
     1203        id->buf_type,
     1204        nth_string(BuffType, (id->buf_type > 3) ? 0 : id->buf_type),
     1205        id->buf_size/2, id->max_multsect);
    11281206    if (id->max_multsect) {
    11291207        printf(", MultSect=");
     
    11351213            printf("off");
    11361214    }
    1137     puts("");
     1215    bb_putchar('\n');
    11381216
    11391217    if (!(id->field_valid & 1))
     
    11501228        printf(", LBAsects=%u", id->lba_capacity);
    11511229
    1152     printf("\n IORDY=%s", (id->capability & 8) ? (id->capability & 4) ?  "on/off" : "yes" : "no");
     1230    printf("\n IORDY=%s",
     1231        (id->capability & 8)
     1232            ? ((id->capability & 4) ? "on/off" : "yes")
     1233            : "no");
    11531234
    11541235    if (((id->capability & 8) || (id->field_valid & 2)) && (id->field_valid & 2))
     
    11651246    }
    11661247    if (id->field_valid & 2) {
    1167         if (id->eide_pio_modes & 1) printf("pio3 ");
    1168         if (id->eide_pio_modes & 2) printf("pio4 ");
    1169         if (id->eide_pio_modes &~3) printf("pio? ");
     1248        static const masks_labels_t pio_modes = {
     1249            .masks = { 1, 2, ~3 },
     1250            .labels = "pio3 \0""pio4 \0""pio? \0",
     1251        };
     1252        print_flags(&pio_modes, id->eide_pio_modes);
    11701253    }
    11711254    if (id->capability & 1) {
    11721255        if (id->dma_1word | id->dma_mword) {
     1256            static const int dma_wmode_masks[] = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 };
    11731257            printf("\n DMA modes:  ");
    1174             if (id->dma_1word & 0x100) printf("*");
    1175             if (id->dma_1word & 1) printf("sdma0 ");
    1176             if (id->dma_1word & 0x200) printf("*");
    1177             if (id->dma_1word & 2) printf("sdma1 ");
    1178             if (id->dma_1word & 0x400) printf("*");
    1179             if (id->dma_1word & 4) printf("sdma2 ");
    1180             if (id->dma_1word & 0xf800) printf("*");
    1181             if (id->dma_1word & 0xf8) printf("sdma? ");
    1182             if (id->dma_mword & 0x100) printf("*");
    1183             if (id->dma_mword & 1) printf("mdma0 ");
    1184             if (id->dma_mword & 0x200) printf("*");
    1185             if (id->dma_mword & 2) printf("mdma1 ");
    1186             if (id->dma_mword & 0x400) printf("*");
    1187             if (id->dma_mword & 4) printf("mdma2 ");
    1188             if (id->dma_mword & 0xf800) printf("*");
    1189             if (id->dma_mword & 0xf8) printf("mdma? ");
     1258            print_flags_separated(dma_wmode_masks,
     1259                "*\0""sdma0 \0""*\0""sdma1 \0""*\0""sdma2 \0""*\0""sdma? \0",
     1260                id->dma_1word, NULL);
     1261            print_flags_separated(dma_wmode_masks,
     1262                "*\0""mdma0 \0""*\0""mdma1 \0""*\0""mdma2 \0""*\0""mdma? \0",
     1263                id->dma_mword, NULL);
    11901264        }
    11911265    }
    11921266    if (((id->capability & 8) || (id->field_valid & 2)) && id->field_valid & 4) {
     1267        static const masks_labels_t ultra_modes1 = {
     1268            .masks = { 0x100, 0x001, 0x200, 0x002, 0x400, 0x004 },
     1269            .labels = "*\0""udma0 \0""*\0""udma1 \0""*\0""udma2 \0",
     1270        };
     1271
    11931272        printf("\n UDMA modes: ");
    1194         if (id->dma_ultra & 0x100) printf("*");
    1195         if (id->dma_ultra & 0x001) printf("udma0 ");
    1196         if (id->dma_ultra & 0x200) printf("*");
    1197         if (id->dma_ultra & 0x002) printf("udma1 ");
    1198         if (id->dma_ultra & 0x400) printf("*");
    1199         if (id->dma_ultra & 0x004) printf("udma2 ");
     1273        print_flags(&ultra_modes1, id->dma_ultra);
    12001274#ifdef __NEW_HD_DRIVE_ID
    12011275        if (id->hw_config & 0x2000) {
     
    12031277        if (id->word93 & 0x2000) {
    12041278#endif /* __NEW_HD_DRIVE_ID */
    1205             if (id->dma_ultra & 0x0800) printf("*");
    1206             if (id->dma_ultra & 0x0008) printf("udma3 ");
    1207             if (id->dma_ultra & 0x1000) printf("*");
    1208             if (id->dma_ultra & 0x0010) printf("udma4 ");
    1209             if (id->dma_ultra & 0x2000) printf("*");
    1210             if (id->dma_ultra & 0x0020) printf("udma5 ");
    1211             if (id->dma_ultra & 0x4000) printf("*");
    1212             if (id->dma_ultra & 0x0040) printf("udma6 ");
    1213             if (id->dma_ultra & 0x8000) printf("*");
    1214             if (id->dma_ultra & 0x0080) printf("udma7 ");
     1279            static const masks_labels_t ultra_modes2 = {
     1280                .masks = { 0x0800, 0x0008, 0x1000, 0x0010,
     1281                    0x2000, 0x0020, 0x4000, 0x0040,
     1282                    0x8000, 0x0080 },
     1283                .labels = "*\0""udma3 \0""*\0""udma4 \0"
     1284                    "*\0""udma5 \0""*\0""udma6 \0"
     1285                    "*\0""udma7 \0"
     1286            };
     1287            print_flags(&ultra_modes2, id->dma_ultra);
    12151288        }
    12161289    }
     
    12301303     || (id->major_rev_num && id->minor_rev_num <= 31)
    12311304    ) {
    1232         printf("\n Drive conforms to: %s: ", (id->minor_rev_num <= 31) ? minor_str[id->minor_rev_num] : "Unknown");
    1233         if (id->major_rev_num != 0x0000 &&  /* NOVAL_0 */
    1234             id->major_rev_num != 0xFFFF) {  /* NOVAL_1 */
     1305        printf("\n Drive conforms to: %s: ",
     1306            (id->minor_rev_num <= 31) ? nth_string(minor_str, id->minor_rev_num) : "unknown");
     1307        if (id->major_rev_num != 0x0000 /* NOVAL_0 */
     1308         && id->major_rev_num != 0xFFFF /* NOVAL_1 */
     1309        ) {
    12351310            for (i = 0; i <= 15; i++) {
    12361311                if (id->major_rev_num & (1<<i))
    1237                         printf(" ATA/ATAPI-%u", i);
     1312                    printf(" ATA/ATAPI-%u", i);
    12381313            }
    12391314        }
     
    12441319#endif
    12451320
    1246 static void flush_buffer_cache(int fd)
     1321static void flush_buffer_cache(/*int fd*/ void)
    12471322{
    12481323    fsync(fd);              /* flush buffers */
     
    12591334}
    12601335
    1261 static int seek_to_zero(int fd)
    1262 {
    1263     if (lseek(fd, (off_t) 0, SEEK_SET))
    1264         return 1;
    1265     return 0;
    1266 }
    1267 
    1268 static int read_big_block(int fd, char *buf)
     1336static void seek_to_zero(/*int fd*/ void)
     1337{
     1338    xlseek(fd, (off_t) 0, SEEK_SET);
     1339}
     1340
     1341static void read_big_block(/*int fd,*/ char *buf)
    12691342{
    12701343    int i;
    12711344
    1272     i = read(fd, buf, TIMING_BUF_BYTES);
    1273     if (i != TIMING_BUF_BYTES) {
    1274         bb_error_msg("read(%d bytes) failed (rc=%d)", TIMING_BUF_BYTES, i);
    1275         return 1;
    1276     }
     1345    xread(fd, buf, TIMING_BUF_BYTES);
    12771346    /* access all sectors of buf to ensure the read fully completed */
    12781347    for (i = 0; i < TIMING_BUF_BYTES; i += 512)
    12791348        buf[i] &= 1;
    1280     return 0;
    1281 }
    1282 
    1283 static int do_blkgetsize(int fd, unsigned long long *blksize64)
    1284 {
    1285     int rc;
    1286     unsigned blksize32 = 0;
    1287 
    1288     if (0 == ioctl(fd, BLKGETSIZE64, blksize64)) {  // returns bytes
    1289         *blksize64 /= 512;
    1290         return 0;
    1291     }
    1292     rc = ioctl_or_warn(fd, BLKGETSIZE, &blksize32); // returns sectors
    1293     *blksize64 = blksize32;
    1294     return rc;
    1295 }
    1296 
    1297 static void print_timing(unsigned t, double e)
    1298 {
    1299     if (t >= e)  /* more than 1MB/s */
    1300         printf("%4d MB in %.2f seconds = %.2f %cB/sec\n", t, e, t / e, 'M');
    1301     else
    1302         printf("%4d MB in %.2f seconds = %.2f %cB/sec\n", t, e, t / e * 1024, 'k');
    1303 }
    1304 
    1305 static void do_time(int flag, int fd)
    1306 /* flag = 0 time_cache, 1 time_device */
    1307 {
    1308     static const struct itimerval thousand = {{1000, 0}, {1000, 0}};
    1309 
    1310     struct itimerval itv;
     1349}
     1350
     1351static unsigned dev_size_mb(/*int fd*/ void)
     1352{
     1353    union {
     1354        unsigned long long blksize64;
     1355        unsigned blksize32;
     1356    } u;
     1357
     1358    if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // bytes
     1359        u.blksize64 /= (1024 * 1024);
     1360    } else {
     1361        xioctl(fd, BLKGETSIZE, &u.blksize32); // sectors
     1362        u.blksize64 = u.blksize32 / (2 * 1024);
     1363    }
     1364    if (u.blksize64 > UINT_MAX)
     1365        return UINT_MAX;
     1366    return u.blksize64;
     1367}
     1368
     1369static void print_timing(unsigned m, unsigned elapsed_us)
     1370{
     1371    unsigned sec = elapsed_us / 1000000;
     1372    unsigned hs = (elapsed_us % 1000000) / 10000;
     1373
     1374    printf("%5u MB in %u.%02u seconds = %u kB/s\n",
     1375        m, sec, hs,
     1376        /* "| 1" prevents div-by-0 */
     1377        (unsigned) ((unsigned long long)m * (1024 * 1000000) / (elapsed_us | 1))
     1378        // ~= (m * 1024) / (elapsed_us / 1000000)
     1379        // = kb / elapsed_sec
     1380    );
     1381}
     1382
     1383static void do_time(int cache /*,int fd*/)
     1384/* cache=1: time cache: repeatedly read N MB at offset 0
     1385 * cache=0: time device: linear read, starting at offset 0
     1386 */
     1387{
     1388    unsigned max_iterations, iterations;
     1389    unsigned start; /* doesn't need to be long long */
    13111390    unsigned elapsed, elapsed2;
    1312     unsigned max_iterations, total_MB, iterations;
    1313     unsigned long long blksize;
    1314     RESERVE_CONFIG_BUFFER(buf, TIMING_BUF_BYTES);
    1315 
    1316     if (mlock(buf, TIMING_BUF_BYTES)) {
    1317         bb_perror_msg("mlock");
    1318         goto quit2;
    1319     }
    1320 
    1321     max_iterations = 1024;
    1322     if (0 == do_blkgetsize(fd, &blksize)) {
    1323         max_iterations = blksize / (2 * 1024) / TIMING_BUF_MB;
    1324     }
    1325 
    1326     /* Clear out the device request queues & give them time to complete */
     1391    unsigned total_MB;
     1392    char *buf = xmalloc(TIMING_BUF_BYTES);
     1393
     1394    if (mlock(buf, TIMING_BUF_BYTES))
     1395        bb_perror_msg_and_die("mlock");
     1396
     1397    /* Clear out the device request queues & give them time to complete.
     1398     * NB: *small* delay. User is expected to have a clue and to not run
     1399     * heavy io in parallel with measurements. */
    13271400    sync();
    1328     sleep(2);
    1329     if (flag == 0) { /* Time cache */
    1330         if (seek_to_zero(fd))
    1331             goto quit;
    1332         if (read_big_block(fd, buf))
    1333             goto quit;
    1334         printf(" Timing buffer-cache reads:  ");
     1401    sleep(1);
     1402    if (cache) { /* Time cache */
     1403        seek_to_zero();
     1404        read_big_block(buf);
     1405        printf("Timing buffer-cache reads: ");
    13351406    } else { /* Time device */
    1336         printf(" Timing buffered disk reads: ");
    1337     }
    1338     fflush(stdout);
     1407        printf("Timing buffered disk reads:");
     1408    }
     1409    fflush_all();
     1410
     1411    /* Now do the timing */
    13391412    iterations = 0;
    1340     /*
    1341      * getitimer() is used rather than gettimeofday() because
    1342      * it is much more consistent (on my machine, at least).
    1343      */
    1344     setitimer(ITIMER_REAL, &thousand, NULL);
    1345     /* Now do the timing */
     1413    /* Max time to run (small for cache, avoids getting
     1414     * huge total_MB which can overlow unsigned type) */
     1415    elapsed2 = 510000; /* cache */
     1416    max_iterations = UINT_MAX;
     1417    if (!cache) {
     1418        elapsed2 = 3000000; /* not cache */
     1419        /* Don't want to read past the end! */
     1420        max_iterations = dev_size_mb() / TIMING_BUF_MB;
     1421    }
     1422    start = monotonic_us();
    13461423    do {
     1424        if (cache)
     1425            seek_to_zero();
     1426        read_big_block(buf);
     1427        elapsed = (unsigned)monotonic_us() - start;
    13471428        ++iterations;
    1348         if ((flag == 0) && seek_to_zero(fd))
    1349             goto quit;
    1350         if (read_big_block(fd, buf))
    1351             goto quit;
    1352         getitimer(ITIMER_REAL, &itv);
    1353         elapsed = (1000 - itv.it_value.tv_sec) * 1000000
    1354                 - itv.it_value.tv_usec;
    1355     } while (elapsed < 3000000 && iterations < max_iterations);
     1429    } while (elapsed < elapsed2 && iterations < max_iterations);
    13561430    total_MB = iterations * TIMING_BUF_MB;
    1357     if (flag == 0) {
    1358         /* Now remove the lseek() and getitimer() overheads from the elapsed time */
    1359         setitimer(ITIMER_REAL, &thousand, NULL);
     1431    //printf(" elapsed:%u iterations:%u ", elapsed, iterations);
     1432    if (cache) {
     1433        /* Cache: remove lseek() and monotonic_us() overheads
     1434         * from elapsed */
     1435        start = monotonic_us();
    13601436        do {
    1361             if (seek_to_zero(fd))
    1362                 goto quit;
    1363             getitimer(ITIMER_REAL, &itv);
    1364             elapsed2 = (1000 - itv.it_value.tv_sec) * 1000000
    1365                     - itv.it_value.tv_usec;
     1437            seek_to_zero();
     1438            elapsed2 = (unsigned)monotonic_us() - start;
    13661439        } while (--iterations);
     1440        //printf(" elapsed2:%u ", elapsed2);
    13671441        elapsed -= elapsed2;
    1368         total_MB *= BUFCACHE_FACTOR;
    1369         flush_buffer_cache(fd);
    1370     }
    1371     print_timing(total_MB, elapsed / 1000000.0);
    1372  quit:
     1442        total_MB *= 2; // BUFCACHE_FACTOR (why?)
     1443        flush_buffer_cache();
     1444    }
     1445    print_timing(total_MB, elapsed);
    13731446    munlock(buf, TIMING_BUF_BYTES);
    1374  quit2:
    1375     RELEASE_CONFIG_BUFFER(buf);
     1447    free(buf);
    13761448}
    13771449
     
    13911463
    13921464#ifdef HDIO_DRIVE_CMD
    1393 static void interpret_standby(unsigned standby)
    1394 {
    1395     unsigned t;
    1396 
     1465static void interpret_standby(uint8_t standby)
     1466{
    13971467    printf(" (");
    1398     if (standby == 0)
     1468    if (standby == 0) {
    13991469        printf("off");
    1400     else if (standby == 252)
    1401         printf("21 minutes");
    1402     else if (standby == 253)
     1470    } else if (standby <= 240 || standby == 252 || standby == 255) {
     1471        /* standby is in 5 sec units */
     1472        unsigned t = standby * 5;
     1473        printf("%u minutes %u seconds", t / 60, t % 60);
     1474    } else if (standby <= 251) {
     1475        unsigned t = (standby - 240); /* t is in 30 min units */;
     1476        printf("%u.%c hours", t / 2, (t & 1) ? '5' : '0');
     1477    }
     1478    if (standby == 253)
    14031479        printf("vendor-specific");
    1404     else if (standby == 254)
    1405         printf("Reserved");
    1406     else if (standby == 255)
    1407         printf("21 minutes + 15 seconds");
    1408     else if (standby <= 240) {
    1409         t = standby * 5;
    1410         printf("%u minutes + %u seconds", t / 60, t % 60);
    1411     } else if (standby <= 251) {
    1412         t = (standby - 240) * 30;
    1413         printf("%u hours + %u minutes", t / 60, t % 60);
    1414     } else
    1415         printf("illegal value");
     1480    if (standby == 254)
     1481        printf("reserved");
    14161482    printf(")\n");
    14171483}
     
    14331499static int translate_xfermode(const char *name)
    14341500{
    1435     int val, i;
     1501    int val;
     1502    unsigned i;
    14361503
    14371504    for (i = 0; i < ARRAY_SIZE(xfermode_val); i++) {
     
    14631530        printf("UltraDMA mode%u", xfermode - 64);
    14641531    else
    1465         printf("Unknown");
     1532        printf("unknown");
    14661533    printf(")\n");
    14671534}
     
    14761543static void process_dev(char *devname)
    14771544{
    1478     int fd;
     1545    /*int fd;*/
    14791546    long parm, multcount;
    14801547#ifndef HDIO_DRIVE_CMD
     
    14861553    const char *fmt = " %s\t= %2ld";
    14871554
    1488     fd = xopen(devname, O_RDONLY|O_NONBLOCK);
     1555    /*fd = xopen_nonblocking(devname);*/
     1556    xmove_fd(xopen_nonblocking(devname), fd);
    14891557    printf("\n%s:\n", devname);
    14901558
    1491     if (set_readahead) {
    1492         print_flag(get_readahead, "fs readahead", Xreadahead);
     1559    if (getset_readahead == IS_SET) {
     1560        print_flag(getset_readahead, "fs readahead", Xreadahead);
    14931561        ioctl_or_warn(fd, BLKRASET, (int *)Xreadahead);
    14941562    }
     
    15001568#endif
    15011569#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
    1502     if (scan_hwif) {
     1570    if (scan_hwif == IS_SET) {
    15031571        printf(" attempting to scan hwif (0x%lx, 0x%lx, %lu)\n", hwif_data, hwif_ctrl, hwif_irq);
    15041572        args[0] = hwif_data;
     
    15241592        ioctl_or_warn(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode);
    15251593    }
    1526     if (set_io32bit) {
    1527         print_flag(get_io32bit, "32-bit IO_support flag", io32bit);
     1594    if (getset_io32bit == IS_SET) {
     1595        print_flag(getset_io32bit, "32-bit IO_support flag", io32bit);
    15281596        ioctl_or_warn(fd, HDIO_SET_32BIT, (int *)io32bit);
    15291597    }
    1530     if (set_mult) {
    1531         print_flag(get_mult, "multcount", mult);
     1598    if (getset_mult == IS_SET) {
     1599        print_flag(getset_mult, "multcount", mult);
    15321600#ifdef HDIO_DRIVE_CMD
    15331601        ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult);
     
    15361604#endif
    15371605    }
    1538     if (set_readonly) {
    1539         print_flag_on_off(get_readonly, "readonly", readonly);
     1606    if (getset_readonly == IS_SET) {
     1607        print_flag_on_off(getset_readonly, "readonly", readonly);
    15401608        ioctl_or_warn(fd, BLKROSET, &readonly);
    15411609    }
    1542     if (set_unmask) {
    1543         print_flag_on_off(get_unmask, "unmaskirq", unmask);
     1610    if (getset_unmask == IS_SET) {
     1611        print_flag_on_off(getset_unmask, "unmaskirq", unmask);
    15441612        ioctl_or_warn(fd, HDIO_SET_UNMASKINTR, (int *)unmask);
    15451613    }
    15461614#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
    1547     if (set_dma) {
    1548         print_flag_on_off(get_dma, "using_dma", dma);
     1615    if (getset_dma == IS_SET) {
     1616        print_flag_on_off(getset_dma, "using_dma", dma);
    15491617        ioctl_or_warn(fd, HDIO_SET_DMA, (int *)dma);
    15501618    }
    15511619#endif /* FEATURE_HDPARM_HDIO_GETSET_DMA */
    1552     if (set_dma_q) {
    1553         print_flag_on_off(get_dma_q, "DMA queue_depth", dma_q);
     1620#ifdef HDIO_SET_QDMA
     1621    if (getset_dma_q == IS_SET) {
     1622        print_flag_on_off(getset_dma_q, "DMA queue_depth", dma_q);
    15541623        ioctl_or_warn(fd, HDIO_SET_QDMA, (int *)dma_q);
    15551624    }
    1556     if (set_nowerr) {
    1557         print_flag_on_off(get_nowerr, "nowerr", nowerr);
     1625#endif
     1626    if (getset_nowerr == IS_SET) {
     1627        print_flag_on_off(getset_nowerr, "nowerr", nowerr);
    15581628        ioctl_or_warn(fd, HDIO_SET_NOWERR, (int *)nowerr);
    15591629    }
    1560     if (set_keep) {
    1561         print_flag_on_off(get_keep, "keep_settings", keep);
     1630    if (getset_keep == IS_SET) {
     1631        print_flag_on_off(getset_keep, "keep_settings", keep);
    15621632        ioctl_or_warn(fd, HDIO_SET_KEEPSETTINGS, (int *)keep);
    15631633    }
    15641634#ifdef HDIO_DRIVE_CMD
    1565     if (set_doorlock) {
     1635    if (getset_doorlock == IS_SET) {
    15661636        args[0] = doorlock ? WIN_DOORLOCK : WIN_DOORUNLOCK;
    15671637        args[2] = 0;
    1568         print_flag_on_off(get_doorlock, "drive doorlock", doorlock);
     1638        print_flag_on_off(getset_doorlock, "drive doorlock", doorlock);
    15691639        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    15701640        args[0] = WIN_SETFEATURES;
    15711641    }
    1572     if (set_dkeep) {
     1642    if (getset_dkeep == IS_SET) {
    15731643        /* lock/unlock the drive's "feature" settings */
    1574         print_flag_on_off(get_dkeep, "drive keep features", dkeep);
     1644        print_flag_on_off(getset_dkeep, "drive keep features", dkeep);
    15751645        args[2] = dkeep ? 0x66 : 0xcc;
    15761646        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    15771647    }
    1578     if (set_defects) {
     1648    if (getset_defects == IS_SET) {
    15791649        args[2] = defects ? 0x04 : 0x84;
    1580         print_flag(get_defects, "drive defect-mgmt", defects);
     1650        print_flag(getset_defects, "drive defect-mgmt", defects);
    15811651        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    15821652    }
    1583     if (set_prefetch) {
     1653    if (getset_prefetch == IS_SET) {
    15841654        args[1] = prefetch;
    15851655        args[2] = 0xab;
    1586         print_flag(get_prefetch, "drive prefetch", prefetch);
     1656        print_flag(getset_prefetch, "drive prefetch", prefetch);
    15871657        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    15881658        args[1] = 0;
     
    15911661        args[1] = xfermode_requested;
    15921662        args[2] = 3;
    1593         if (get_xfermode) {
    1594             print_flag(1, "xfermode", xfermode_requested);
    1595             interpret_xfermode(xfermode_requested);
    1596         }
     1663        print_flag(1, "xfermode", xfermode_requested);
     1664        interpret_xfermode(xfermode_requested);
    15971665        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    15981666        args[1] = 0;
    15991667    }
    1600     if (set_lookahead) {
     1668    if (getset_lookahead == IS_SET) {
    16011669        args[2] = lookahead ? 0xaa : 0x55;
    1602         print_flag_on_off(get_lookahead, "drive read-lookahead", lookahead);
     1670        print_flag_on_off(getset_lookahead, "drive read-lookahead", lookahead);
    16031671        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    16041672    }
    1605     if (set_apmmode) {
    1606         args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */; /* feature register */
     1673    if (getset_apmmode == IS_SET) {
     1674        /* feature register */
     1675        args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */;
    16071676        args[1] = apmmode; /* sector count register 1-255 */
    1608         if (get_apmmode)
    1609             printf(" setting APM level to %s 0x%02lX (%ld)\n", (apmmode == 255) ? "disabled" : "", apmmode, apmmode);
     1677        printf(" setting APM level to %s 0x%02lX (%ld)\n",
     1678            (apmmode == 255) ? "disabled" : "",
     1679            apmmode, apmmode);
    16101680        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    16111681        args[1] = 0;
    16121682    }
    1613     if (set_wcache) {
     1683    if (getset_wcache == IS_SET) {
    16141684#ifdef DO_FLUSHCACHE
    16151685#ifndef WIN_FLUSHCACHE
    16161686#define WIN_FLUSHCACHE 0xe7
    16171687#endif
    1618         static unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };
    16191688#endif /* DO_FLUSHCACHE */
    16201689        args[2] = wcache ? 0x02 : 0x82;
    1621         print_flag_on_off(get_wcache, "drive write-caching", wcache);
     1690        print_flag_on_off(getset_wcache, "drive write-caching", wcache);
    16221691#ifdef DO_FLUSHCACHE
    16231692        if (!wcache)
     
    16421711#define WIN_STANDBYNOW2 0x94
    16431712#endif
    1644         if (get_standbynow) printf(" issuing standby command\n");
     1713        printf(" issuing standby command\n");
    16451714        args[0] = WIN_STANDBYNOW1;
    1646         ioctl_alt_or_warn(fd, HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2);
     1715        ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2);
    16471716    }
    16481717    if (set_sleepnow) {
     
    16531722#define WIN_SLEEPNOW2 0x99
    16541723#endif
    1655         if (get_sleepnow) printf(" issuing sleep command\n");
     1724        printf(" issuing sleep command\n");
    16561725        args[0] = WIN_SLEEPNOW1;
    1657         ioctl_alt_or_warn(fd, HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2);
     1726        ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2);
    16581727    }
    16591728    if (set_seagate) {
    16601729        args[0] = 0xfb;
    1661         if (get_seagate) printf(" disabling Seagate auto powersaving mode\n");
     1730        printf(" disabling Seagate auto powersaving mode\n");
    16621731        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    16631732    }
    1664     if (set_standby) {
     1733    if (getset_standby == IS_SET) {
    16651734        args[0] = WIN_SETIDLE1;
    16661735        args[1] = standby_requested;
    1667         if (get_standby) {
    1668             print_flag(1, "standby", standby_requested);
    1669             interpret_standby(standby_requested);
    1670         }
     1736        print_flag(1, "standby", standby_requested);
     1737        interpret_standby(standby_requested);
    16711738        ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
    16721739        args[1] = 0;
     
    16751742    if (force_operation) {
    16761743        char buf[512];
    1677         flush_buffer_cache(fd);
     1744        flush_buffer_cache();
    16781745        if (-1 == read(fd, buf, sizeof(buf)))
    1679             bb_perror_msg("read(%d bytes) failed (rc=%d)", sizeof(buf), -1);
    1680     }
    1681 #endif  /* HDIO_DRIVE_CMD */
    1682 
    1683     if (get_mult || get_identity) {
     1746            bb_perror_msg("read of 512 bytes failed");
     1747    }
     1748#endif  /* HDIO_DRIVE_CMD */
     1749    if (getset_mult || get_identity) {
    16841750        multcount = -1;
    16851751        if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) {
    1686             if (get_mult && ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn. */
     1752            /* To be coherent with ioctl_or_warn. */
     1753            if (getset_mult && ENABLE_IOCTL_HEX2STR_ERROR)
    16871754                bb_perror_msg("HDIO_GET_MULTCOUNT");
    16881755            else
    16891756                bb_perror_msg("ioctl %#x failed", HDIO_GET_MULTCOUNT);
    1690         } else if (get_mult) {
     1757        } else if (getset_mult) {
    16911758            printf(fmt, "multcount", multcount);
    16921759            on_off(multcount != 0);
    16931760        }
    16941761    }
    1695     if (get_io32bit) {
     1762    if (getset_io32bit) {
    16961763        if (!ioctl_or_warn(fd, HDIO_GET_32BIT, &parm)) {
    16971764            printf(" IO_support\t=%3ld (", parm);
     
    17101777        }
    17111778    }
    1712     if (get_unmask) {
    1713         if(!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, (unsigned long *)parm))
     1779    if (getset_unmask) {
     1780        if (!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, &parm))
    17141781            print_value_on_off("unmaskirq", parm);
    17151782    }
    1716 
    1717 
    17181783#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
    1719     if (get_dma) {
     1784    if (getset_dma) {
    17201785        if (!ioctl_or_warn(fd, HDIO_GET_DMA, &parm)) {
    17211786            printf(fmt, "using_dma", parm);
     
    17271792    }
    17281793#endif
    1729     if (get_dma_q) {
    1730         if(!ioctl_or_warn(fd, HDIO_GET_QDMA, (unsigned long *)parm))
     1794#ifdef HDIO_GET_QDMA
     1795    if (getset_dma_q) {
     1796        if (!ioctl_or_warn(fd, HDIO_GET_QDMA, &parm))
    17311797            print_value_on_off("queue_depth", parm);
    17321798    }
    1733     if (get_keep) {
    1734         if(!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, (unsigned long *)parm))
     1799#endif
     1800    if (getset_keep) {
     1801        if (!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, &parm))
    17351802            print_value_on_off("keepsettings", parm);
    17361803    }
    1737 
    1738     if (get_nowerr) {
    1739         if(!ioctl_or_warn(fd, HDIO_GET_NOWERR, (unsigned long *)parm))
     1804    if (getset_nowerr) {
     1805        if (!ioctl_or_warn(fd, HDIO_GET_NOWERR, &parm))
    17401806            print_value_on_off("nowerr", parm);
    17411807    }
    1742     if (get_readonly) {
    1743         if(!ioctl_or_warn(fd, BLKROGET, (unsigned long *)parm))
     1808    if (getset_readonly) {
     1809        if (!ioctl_or_warn(fd, BLKROGET, &parm))
    17441810            print_value_on_off("readonly", parm);
    17451811    }
    1746     if (get_readahead) {
    1747         if(!ioctl_or_warn(fd, BLKRAGET, (unsigned long *)parm))
     1812    if (getset_readahead) {
     1813        if (!ioctl_or_warn(fd, BLKRAGET, &parm))
    17481814            print_value_on_off("readahead", parm);
    17491815    }
     
    17541820            if (!ioctl_or_warn(fd, HDIO_GETGEO, &g))
    17551821                printf(" geometry\t= %u/%u/%u, sectors = %ld, start = %ld\n",
    1756                         g.cylinders, g.heads, g.sectors, parm, g.start);
     1822                    g.cylinders, g.heads, g.sectors, parm, g.start);
    17571823        }
    17581824    }
     
    17681834
    17691835        args[0] = WIN_CHECKPOWERMODE1;
    1770         if (ioctl_alt_or_warn(fd, HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2)) {
     1836        if (ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2)) {
    17711837            if (errno != EIO || args[0] != 0 || args[1] != 0)
    17721838                state = "unknown";
     
    18171883        args1[0] = WIN_IDENTIFY;
    18181884        args1[3] = 1;
    1819         if (!ioctl_alt_or_warn(fd, HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY))
     1885        if (!ioctl_alt_or_warn(HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY))
    18201886            identify((void *)(args1 + 4));
    18211887    }
    18221888#endif
    18231889#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
    1824     if (set_busstate) {
    1825         if (get_busstate) {
    1826             print_flag(1, "bus state", busstate);
    1827             bus_state_value(busstate);
    1828         }
     1890    if (getset_busstate == IS_SET) {
     1891        print_flag(1, "bus state", busstate);
     1892        bus_state_value(busstate);
    18291893        ioctl_or_warn(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate);
    18301894    }
    1831     if (get_busstate) {
     1895    if (getset_busstate) {
    18321896        if (!ioctl_or_warn(fd, HDIO_GET_BUSSTATE, &parm)) {
    18331897            printf(fmt, "bus state", parm);
     
    18401904
    18411905    if (do_ctimings)
    1842         do_time(0, fd); /* time cache */
     1906        do_time(1 /*,fd*/); /* time cache */
    18431907    if (do_timings)
    1844         do_time(1, fd); /* time device */
     1908        do_time(0 /*,fd*/); /* time device */
    18451909    if (do_flush)
    1846         flush_buffer_cache(fd);
     1910        flush_buffer_cache();
    18471911    close(fd);
    18481912}
     
    18581922}
    18591923
     1924static void identify_from_stdin(void) NORETURN;
    18601925static void identify_from_stdin(void)
    18611926{
     
    18651930    int i;
    18661931
    1867     xread(0, buf, 1280);
     1932    xread(STDIN_FILENO, buf, 1280);
    18681933
    18691934    // Convert the newline-separated hex data into an identify block.
     
    18791944    identify(sbuf);
    18801945}
     1946#else
     1947void identify_from_stdin(void);
    18811948#endif
    18821949
    18831950/* busybox specific stuff */
    1884 static void parse_opts(smallint *get, smallint *set, unsigned long *value, int min, int max)
    1885 {
    1886     if (get) {
    1887         *get = 1;
    1888     }
     1951static int parse_opts(unsigned long *value, int min, int max)
     1952{
    18891953    if (optarg) {
    1890         *set = 1;
    18911954        *value = xatol_range(optarg, min, max);
    1892     }
     1955        return IS_SET;
     1956    }
     1957    return IS_GET;
     1958}
     1959static int parse_opts_0_max(unsigned long *value, int max)
     1960{
     1961    return parse_opts(value, 0, max);
     1962}
     1963static int parse_opts_0_1(unsigned long *value)
     1964{
     1965    return parse_opts(value, 0, 1);
     1966}
     1967static int parse_opts_0_INTMAX(unsigned long *value)
     1968{
     1969    return parse_opts(value, 0, INT_MAX);
    18931970}
    18941971
     
    18961973{
    18971974    if (flag) {
    1898         *get = 1;
     1975        *get = IS_GET;
    18991976        if (optarg) {
    19001977            *value = translate_xfermode(optarg);
     
    19061983/*------- getopt short options --------*/
    19071984static const char hdparm_options[] ALIGN1 =
    1908     "gfu::n::p:r::m::c::k::a::B:tTh"
    1909     USE_FEATURE_HDPARM_GET_IDENTITY("iI")
    1910     USE_FEATURE_HDPARM_HDIO_GETSET_DMA("d::")
     1985    "gfu::n::p:r::m::c::k::a::B:tT"
     1986    IF_FEATURE_HDPARM_GET_IDENTITY("iI")
     1987    IF_FEATURE_HDPARM_HDIO_GETSET_DMA("d::")
    19111988#ifdef HDIO_DRIVE_CMD
    19121989    "S:D:P:X:K:A:L:W:CyYzZ"
    19131990#endif
    1914     USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("U:")
     1991    IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("U:")
    19151992#ifdef HDIO_GET_QDMA
    19161993#ifdef HDIO_SET_QDMA
     
    19201997#endif
    19211998#endif
    1922     USE_FEATURE_HDPARM_HDIO_DRIVE_RESET("w")
    1923     USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF("x::b:")
    1924     USE_FEATURE_HDPARM_HDIO_SCAN_HWIF("R:");
     1999    IF_FEATURE_HDPARM_HDIO_DRIVE_RESET("w")
     2000    IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF("x::b:")
     2001    IF_FEATURE_HDPARM_HDIO_SCAN_HWIF("R:");
    19252002/*-------------------------------------*/
    19262003
    19272004/* our main() routine: */
    1928 int hdparm_main(int argc, char **argv);
     2005int hdparm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    19292006int hdparm_main(int argc, char **argv)
    19302007{
     
    19342011    while ((c = getopt(argc, argv, hdparm_options)) >= 0) {
    19352012        flagcount++;
    1936         if (c == 'h') bb_show_usage(); /* EXIT */
    1937         USE_FEATURE_HDPARM_GET_IDENTITY(get_IDentity |= (c == 'I'));
    1938         USE_FEATURE_HDPARM_GET_IDENTITY(get_identity |= (c == 'i'));
     2013        IF_FEATURE_HDPARM_GET_IDENTITY(get_IDentity |= (c == 'I'));
     2014        IF_FEATURE_HDPARM_GET_IDENTITY(get_identity |= (c == 'i'));
    19392015        get_geom |= (c == 'g');
    19402016        do_flush |= (c == 'f');
    1941         if (c == 'u') parse_opts(&get_unmask, &set_unmask, &unmask, 0, 1);
    1942         USE_FEATURE_HDPARM_HDIO_GETSET_DMA(if (c == 'd') parse_opts(&get_dma, &set_dma, &dma, 0, 9));
    1943         if (c == 'n') parse_opts(&get_nowerr, &set_nowerr, &nowerr, 0, 1);
     2017        if (c == 'u') getset_unmask    = parse_opts_0_1(&unmask);
     2018    IF_FEATURE_HDPARM_HDIO_GETSET_DMA(
     2019        if (c == 'd') getset_dma       = parse_opts_0_max(&dma, 9);
     2020    )
     2021        if (c == 'n') getset_nowerr    = parse_opts_0_1(&nowerr);
    19442022        parse_xfermode((c == 'p'), &noisy_piomode, &set_piomode, &piomode);
    1945         if (c == 'r') parse_opts(&get_readonly, &set_readonly, &readonly, 0, 1);
    1946         if (c == 'm') parse_opts(&get_mult, &set_mult, &mult, 0, INT_MAX /*32*/);
    1947         if (c == 'c') parse_opts(&get_io32bit, &set_io32bit, &io32bit, 0, INT_MAX /*8*/);
    1948         if (c == 'k') parse_opts(&get_keep, &set_keep, &keep, 0, 1);
    1949         if (c == 'a') parse_opts(&get_readahead, &set_readahead, &Xreadahead, 0, INT_MAX);
    1950         if (c == 'B') parse_opts(&get_apmmode, &set_apmmode, &apmmode, 1, 255);
     2023        if (c == 'r') getset_readonly  = parse_opts_0_1(&readonly);
     2024        if (c == 'm') getset_mult      = parse_opts_0_INTMAX(&mult /*32*/);
     2025        if (c == 'c') getset_io32bit   = parse_opts_0_INTMAX(&io32bit /*8*/);
     2026        if (c == 'k') getset_keep      = parse_opts_0_1(&keep);
     2027        if (c == 'a') getset_readahead = parse_opts_0_INTMAX(&Xreadahead);
     2028        if (c == 'B') getset_apmmode   = parse_opts(&apmmode, 1, 255);
    19512029        do_flush |= do_timings |= (c == 't');
    19522030        do_flush |= do_ctimings |= (c == 'T');
    19532031#ifdef HDIO_DRIVE_CMD
    1954         if (c == 'S') parse_opts(&get_standby, &set_standby, &standby_requested, 0, INT_MAX);
    1955         if (c == 'D') parse_opts(&get_defects, &set_defects, &defects, 0, INT_MAX);
    1956         if (c == 'P') parse_opts(&get_prefetch, &set_prefetch, &prefetch, 0, INT_MAX);
     2032        if (c == 'S') getset_standby  = parse_opts_0_max(&standby_requested, 255);
     2033        if (c == 'D') getset_defects  = parse_opts_0_INTMAX(&defects);
     2034        if (c == 'P') getset_prefetch = parse_opts_0_INTMAX(&prefetch);
    19572035        parse_xfermode((c == 'X'), &get_xfermode, &set_xfermode, &xfermode_requested);
    1958         if (c == 'K') parse_opts(&get_dkeep, &set_dkeep, &prefetch, 0, 1);
    1959         if (c == 'A') parse_opts(&get_lookahead, &set_lookahead, &lookahead, 0, 1);
    1960         if (c == 'L') parse_opts(&get_doorlock, &set_doorlock, &doorlock, 0, 1);
    1961         if (c == 'W') parse_opts(&get_wcache, &set_wcache, &wcache, 0, 1);
     2036        if (c == 'K') getset_dkeep     = parse_opts_0_1(&prefetch);
     2037        if (c == 'A') getset_lookahead = parse_opts_0_1(&lookahead);
     2038        if (c == 'L') getset_doorlock  = parse_opts_0_1(&doorlock);
     2039        if (c == 'W') getset_wcache    = parse_opts_0_1(&wcache);
    19622040        get_powermode |= (c == 'C');
    1963         get_standbynow = set_standbynow |= (c == 'y');
    1964         get_sleepnow = set_sleepnow |= (c == 'Y');
     2041        set_standbynow |= (c == 'y');
     2042        set_sleepnow |= (c == 'Y');
    19652043        reread_partn |= (c == 'z');
    1966         get_seagate = set_seagate |= (c == 'Z');
    1967 #endif
    1968         USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') parse_opts(NULL, &unregister_hwif, &hwif, 0, INT_MAX));
     2044        set_seagate |= (c == 'Z');
     2045#endif
     2046        IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') unregister_hwif = parse_opts_0_INTMAX(&hwif));
    19692047#ifdef HDIO_GET_QDMA
    19702048        if (c == 'Q') {
    1971 #ifdef HDIO_SET_QDMA
    1972             parse_opts(&get_dma_q, &set_dma_q, &dma_q, 0, INT_MAX);
    1973 #else
    1974             parse_opts(&get_dma_q, NULL, NULL, 0, 0);
    1975 #endif
    1976         }
    1977 #endif
    1978         USE_FEATURE_HDPARM_HDIO_DRIVE_RESET(perform_reset = (c == 'r'));
    1979         USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'x') parse_opts(NULL, &perform_tristate, &tristate, 0, 1));
    1980         USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'b') parse_opts(&get_busstate, &set_busstate, &busstate, 0, 2));
     2049            getset_dma_q = parse_opts_0_INTMAX(&dma_q);
     2050        }
     2051#endif
     2052        IF_FEATURE_HDPARM_HDIO_DRIVE_RESET(perform_reset = (c == 'r'));
     2053        IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'x') perform_tristate = parse_opts_0_1(&tristate));
     2054        IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'b') getset_busstate = parse_opts_0_max(&busstate, 2));
    19812055#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
    19822056        if (c == 'R') {
    1983             parse_opts(NULL, &scan_hwif, &hwif_data, 0, INT_MAX);
    1984             hwif_ctrl = xatoi_u((argv[optind]) ? argv[optind] : "");
    1985             hwif_irq  = xatoi_u((argv[optind+1]) ? argv[optind+1] : "");
     2057            scan_hwif = parse_opts_0_INTMAX(&hwif_data);
     2058            hwif_ctrl = xatoi_positive((argv[optind]) ? argv[optind] : "");
     2059            hwif_irq  = xatoi_positive((argv[optind+1]) ? argv[optind+1] : "");
    19862060            /* Move past the 2 additional arguments */
    19872061            argv += 2;
     
    19922066    /* When no flags are given (flagcount = 0), -acdgkmnru is assumed. */
    19932067    if (!flagcount) {
    1994         get_mult = get_io32bit = get_unmask = get_keep = get_readonly = get_readahead = get_geom = 1;
    1995         USE_FEATURE_HDPARM_HDIO_GETSET_DMA(get_dma = 1);
     2068        getset_mult = getset_io32bit = getset_unmask = getset_keep = getset_readonly = getset_readahead = get_geom = IS_GET;
     2069        IF_FEATURE_HDPARM_HDIO_GETSET_DMA(getset_dma = IS_GET);
    19962070    }
    19972071    argv += optind;
     
    20002074        if (ENABLE_FEATURE_HDPARM_GET_IDENTITY && !isatty(STDIN_FILENO))
    20012075            identify_from_stdin(); /* EXIT */
    2002         else bb_show_usage();
     2076        bb_show_usage();
    20032077    }
    20042078
Note: See TracChangeset for help on using the changeset viewer.