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