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