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