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