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