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