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