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