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