hdparm: paranoia-induced fix against theoretical div-by-0 case
[people/mcb30/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 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)) { // bytes
1364                 u.blksize64 /= (1024 * 1024);
1365         } else {
1366                 xioctl(fd, BLKGETSIZE, &u.blksize32); // sectors
1367                 u.blksize64 = u.blksize32 / (2 * 1024);
1368         }
1369         if (u.blksize64 > UINT_MAX)
1370                 return UINT_MAX;
1371         return u.blksize64;
1372 }
1373
1374 static void print_timing(unsigned m, unsigned elapsed_us)
1375 {
1376         unsigned sec = elapsed_us / 1000000;
1377         unsigned hs = (elapsed_us % 1000000) / 10000;
1378
1379         printf("%5u MB in %u.%02u seconds = %u kB/s\n",
1380                 m, sec, hs,
1381                 /* "| 1" prevents div-by-0 */
1382                 (unsigned) ((unsigned long long)m * (1024 * 1000000) / (elapsed_us | 1))
1383                 // ~= (m * 1024) / (elapsed_us / 1000000)
1384                 // = kb / elapsed_sec
1385         );
1386 }
1387
1388 static void do_time(int cache /*,int fd*/)
1389 /* cache=1: time cache: repeatedly read N MB at offset 0
1390  * cache=0: time device: linear read, starting at offset 0
1391  */
1392 {
1393         unsigned max_iterations, iterations;
1394         unsigned start; /* doesn't need to be long long */
1395         unsigned elapsed, elapsed2;
1396         unsigned total_MB;
1397         char *buf = xmalloc(TIMING_BUF_BYTES);
1398
1399         if (mlock(buf, TIMING_BUF_BYTES))
1400                 bb_perror_msg_and_die("mlock");
1401
1402         /* Clear out the device request queues & give them time to complete.
1403          * NB: *small* delay. User is expected to have a clue and to not run
1404          * heavy io in parallel with measurements. */
1405         sync();
1406         sleep(1);
1407         if (cache) { /* Time cache */
1408                 seek_to_zero();
1409                 read_big_block(buf);
1410                 printf("Timing buffer-cache reads: ");
1411         } else { /* Time device */
1412                 printf("Timing buffered disk reads:");
1413         }
1414         fflush(stdout);
1415
1416         /* Now do the timing */
1417         iterations = 0;
1418         /* Max time to run (small for cache, avoids getting
1419          * huge total_MB which can overlow unsigned type) */
1420         elapsed2 = 510000; /* cache */
1421         max_iterations = UINT_MAX;
1422         if (!cache) {
1423                 elapsed2 = 3000000; /* not cache */
1424                 /* Don't want to read past the end! */
1425                 max_iterations = dev_size_mb() / TIMING_BUF_MB;
1426         }
1427         start = monotonic_us();
1428         do {
1429                 if (cache)
1430                         seek_to_zero();
1431                 read_big_block(buf);
1432                 elapsed = (unsigned)monotonic_us() - start;
1433                 ++iterations;
1434         } while (elapsed < elapsed2 && iterations < max_iterations);
1435         total_MB = iterations * TIMING_BUF_MB;
1436         //printf(" elapsed:%u iterations:%u ", elapsed, iterations);
1437         if (cache) {
1438                 /* Cache: remove lseek() and monotonic_us() overheads
1439                  * from elapsed */
1440                 start = monotonic_us();
1441                 do {
1442                         seek_to_zero();
1443                         elapsed2 = (unsigned)monotonic_us() - start;
1444                 } while (--iterations);
1445                 //printf(" elapsed2:%u ", elapsed2);
1446                 elapsed -= elapsed2;
1447                 total_MB *= 2; // BUFCACHE_FACTOR (why?)
1448                 flush_buffer_cache();
1449         }
1450         print_timing(total_MB, elapsed);
1451         munlock(buf, TIMING_BUF_BYTES);
1452         free(buf);
1453 }
1454
1455 #if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
1456 static void bus_state_value(unsigned value)
1457 {
1458         if (value == BUSSTATE_ON)
1459                 on_off(1);
1460         else if (value == BUSSTATE_OFF)
1461                 on_off(0);
1462         else if (value == BUSSTATE_TRISTATE)
1463                 printf(" (tristate)\n");
1464         else
1465                 printf(" (unknown: %d)\n", value);
1466 }
1467 #endif
1468
1469 #ifdef HDIO_DRIVE_CMD
1470 static void interpret_standby(unsigned standby)
1471 {
1472         unsigned t;
1473
1474         printf(" (");
1475         if (standby == 0)
1476                 printf("off");
1477         else if (standby == 252)
1478                 printf("21 minutes");
1479         else if (standby == 253)
1480                 printf("vendor-specific");
1481         else if (standby == 254)
1482                 printf("Reserved");
1483         else if (standby == 255)
1484                 printf("21 minutes + 15 seconds");
1485         else if (standby <= 240) {
1486                 t = standby * 5;
1487                 printf("%u minutes + %u seconds", t / 60, t % 60);
1488         } else if (standby <= 251) {
1489                 t = (standby - 240) * 30;
1490                 printf("%u hours + %u minutes", t / 60, t % 60);
1491         } else
1492                 printf("illegal value");
1493         printf(")\n");
1494 }
1495
1496 static const uint8_t xfermode_val[] ALIGN1 = {
1497          8,      9,     10,     11,     12,     13,     14,     15,
1498         16,     17,     18,     19,     20,     21,     22,     23,
1499         32,     33,     34,     35,     36,     37,     38,     39,
1500         64,     65,     66,     67,     68,     69,     70,     71
1501 };
1502 /* NB: we save size by _not_ storing terninating NUL! */
1503 static const char xfermode_name[][5] ALIGN1 = {
1504         "pio0", "pio1", "pio2", "pio3", "pio4", "pio5", "pio6", "pio7",
1505         "sdma0","sdma1","sdma2","sdma3","sdma4","sdma5","sdma6","sdma7",
1506         "mdma0","mdma1","mdma2","mdma3","mdma4","mdma5","mdma6","mdma7",
1507         "udma0","udma1","udma2","udma3","udma4","udma5","udma6","udma7"
1508 };
1509
1510 static int translate_xfermode(const char *name)
1511 {
1512         int val, i;
1513
1514         for (i = 0; i < ARRAY_SIZE(xfermode_val); i++) {
1515                 if (!strncmp(name, xfermode_name[i], 5))
1516                         if (strlen(name) <= 5)
1517                                 return xfermode_val[i];
1518         }
1519         /* Negative numbers are invalid and are caught later */
1520         val = bb_strtoi(name, NULL, 10);
1521         if (!errno)
1522                 return val;
1523         return -1;
1524 }
1525
1526 static void interpret_xfermode(unsigned xfermode)
1527 {
1528         printf(" (");
1529         if (xfermode == 0)
1530                 printf("default PIO mode");
1531         else if (xfermode == 1)
1532                 printf("default PIO mode, disable IORDY");
1533         else if (xfermode >= 8 && xfermode <= 15)
1534                 printf("PIO flow control mode%u", xfermode - 8);
1535         else if (xfermode >= 16 && xfermode <= 23)
1536                 printf("singleword DMA mode%u", xfermode - 16);
1537         else if (xfermode >= 32 && xfermode <= 39)
1538                 printf("multiword DMA mode%u", xfermode - 32);
1539         else if (xfermode >= 64 && xfermode <= 71)
1540                 printf("UltraDMA mode%u", xfermode - 64);
1541         else
1542                 printf("Unknown");
1543         printf(")\n");
1544 }
1545 #endif /* HDIO_DRIVE_CMD */
1546
1547 static void print_flag(int flag, const char *s, unsigned long value)
1548 {
1549         if (flag)
1550                 printf(" setting %s to %ld\n", s, value);
1551 }
1552
1553 static void process_dev(char *devname)
1554 {
1555         /*int fd;*/
1556         long parm, multcount;
1557 #ifndef HDIO_DRIVE_CMD
1558         int force_operation = 0;
1559 #endif
1560         /* Please restore args[n] to these values after each ioctl
1561            except for args[2] */
1562         unsigned char args[4] = { WIN_SETFEATURES, 0, 0, 0 };
1563         const char *fmt = " %s\t= %2ld";
1564
1565         /*fd = xopen(devname, O_RDONLY | O_NONBLOCK);*/
1566         xmove_fd(xopen(devname, O_RDONLY | O_NONBLOCK), fd);
1567         printf("\n%s:\n", devname);
1568
1569         if (set_readahead) {
1570                 print_flag(get_readahead, "fs readahead", Xreadahead);
1571                 ioctl_or_warn(fd, BLKRASET, (int *)Xreadahead);
1572         }
1573 #if ENABLE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
1574         if (unregister_hwif) {
1575                 printf(" attempting to unregister hwif#%lu\n", hwif);
1576                 ioctl_or_warn(fd, HDIO_UNREGISTER_HWIF, (int *)(unsigned long)hwif);
1577         }
1578 #endif
1579 #if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
1580         if (scan_hwif) {
1581                 printf(" attempting to scan hwif (0x%lx, 0x%lx, %lu)\n", hwif_data, hwif_ctrl, hwif_irq);
1582                 args[0] = hwif_data;
1583                 args[1] = hwif_ctrl;
1584                 args[2] = hwif_irq;
1585                 ioctl_or_warn(fd, HDIO_SCAN_HWIF, args);
1586                 args[0] = WIN_SETFEATURES;
1587                 args[1] = 0;
1588         }
1589 #endif
1590         if (set_piomode) {
1591                 if (noisy_piomode) {
1592                         printf(" attempting to ");
1593                         if (piomode == 255)
1594                                 printf("auto-tune PIO mode\n");
1595                         else if (piomode < 100)
1596                                 printf("set PIO mode to %d\n", piomode);
1597                         else if (piomode < 200)
1598                                 printf("set MDMA mode to %d\n", (piomode-100));
1599                         else
1600                                 printf("set UDMA mode to %d\n", (piomode-200));
1601                 }
1602                 ioctl_or_warn(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode);
1603         }
1604         if (set_io32bit) {
1605                 print_flag(get_io32bit, "32-bit IO_support flag", io32bit);
1606                 ioctl_or_warn(fd, HDIO_SET_32BIT, (int *)io32bit);
1607         }
1608         if (set_mult) {
1609                 print_flag(get_mult, "multcount", mult);
1610 #ifdef HDIO_DRIVE_CMD
1611                 ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult);
1612 #else
1613                 force_operation |= (!ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult));
1614 #endif
1615         }
1616         if (set_readonly) {
1617                 print_flag_on_off(get_readonly, "readonly", readonly);
1618                 ioctl_or_warn(fd, BLKROSET, &readonly);
1619         }
1620         if (set_unmask) {
1621                 print_flag_on_off(get_unmask, "unmaskirq", unmask);
1622                 ioctl_or_warn(fd, HDIO_SET_UNMASKINTR, (int *)unmask);
1623         }
1624 #if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
1625         if (set_dma) {
1626                 print_flag_on_off(get_dma, "using_dma", dma);
1627                 ioctl_or_warn(fd, HDIO_SET_DMA, (int *)dma);
1628         }
1629 #endif /* FEATURE_HDPARM_HDIO_GETSET_DMA */
1630         if (set_dma_q) {
1631                 print_flag_on_off(get_dma_q, "DMA queue_depth", dma_q);
1632                 ioctl_or_warn(fd, HDIO_SET_QDMA, (int *)dma_q);
1633         }
1634         if (set_nowerr) {
1635                 print_flag_on_off(get_nowerr, "nowerr", nowerr);
1636                 ioctl_or_warn(fd, HDIO_SET_NOWERR, (int *)nowerr);
1637         }
1638         if (set_keep) {
1639                 print_flag_on_off(get_keep, "keep_settings", keep);
1640                 ioctl_or_warn(fd, HDIO_SET_KEEPSETTINGS, (int *)keep);
1641         }
1642 #ifdef HDIO_DRIVE_CMD
1643         if (set_doorlock) {
1644                 args[0] = doorlock ? WIN_DOORLOCK : WIN_DOORUNLOCK;
1645                 args[2] = 0;
1646                 print_flag_on_off(get_doorlock, "drive doorlock", doorlock);
1647                 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1648                 args[0] = WIN_SETFEATURES;
1649         }
1650         if (set_dkeep) {
1651                 /* lock/unlock the drive's "feature" settings */
1652                 print_flag_on_off(get_dkeep, "drive keep features", dkeep);
1653                 args[2] = dkeep ? 0x66 : 0xcc;
1654                 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1655         }
1656         if (set_defects) {
1657                 args[2] = defects ? 0x04 : 0x84;
1658                 print_flag(get_defects, "drive defect-mgmt", defects);
1659                 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1660         }
1661         if (set_prefetch) {
1662                 args[1] = prefetch;
1663                 args[2] = 0xab;
1664                 print_flag(get_prefetch, "drive prefetch", prefetch);
1665                 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1666                 args[1] = 0;
1667         }
1668         if (set_xfermode) {
1669                 args[1] = xfermode_requested;
1670                 args[2] = 3;
1671                 if (get_xfermode) {
1672                         print_flag(1, "xfermode", xfermode_requested);
1673                         interpret_xfermode(xfermode_requested);
1674                 }
1675                 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1676                 args[1] = 0;
1677         }
1678         if (set_lookahead) {
1679                 args[2] = lookahead ? 0xaa : 0x55;
1680                 print_flag_on_off(get_lookahead, "drive read-lookahead", lookahead);
1681                 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1682         }
1683         if (set_apmmode) {
1684                 args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */; /* feature register */
1685                 args[1] = apmmode; /* sector count register 1-255 */
1686                 if (get_apmmode)
1687                         printf(" setting APM level to %s 0x%02lX (%ld)\n", (apmmode == 255) ? "disabled" : "", apmmode, apmmode);
1688                 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1689                 args[1] = 0;
1690         }
1691         if (set_wcache) {
1692 #ifdef DO_FLUSHCACHE
1693 #ifndef WIN_FLUSHCACHE
1694 #define WIN_FLUSHCACHE 0xe7
1695 #endif
1696 #endif /* DO_FLUSHCACHE */
1697                 args[2] = wcache ? 0x02 : 0x82;
1698                 print_flag_on_off(get_wcache, "drive write-caching", wcache);
1699 #ifdef DO_FLUSHCACHE
1700                 if (!wcache)
1701                         ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache);
1702 #endif /* DO_FLUSHCACHE */
1703                 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1704 #ifdef DO_FLUSHCACHE
1705                 if (!wcache)
1706                         ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache);
1707 #endif /* DO_FLUSHCACHE */
1708         }
1709
1710         /* In code below, we do not preserve args[0], but the rest
1711            is preserved, including args[2] */
1712         args[2] = 0;
1713
1714         if (set_standbynow) {
1715 #ifndef WIN_STANDBYNOW1
1716 #define WIN_STANDBYNOW1 0xE0
1717 #endif
1718 #ifndef WIN_STANDBYNOW2
1719 #define WIN_STANDBYNOW2 0x94
1720 #endif
1721                 if (get_standbynow) printf(" issuing standby command\n");
1722                 args[0] = WIN_STANDBYNOW1;
1723                 ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2);
1724         }
1725         if (set_sleepnow) {
1726 #ifndef WIN_SLEEPNOW1
1727 #define WIN_SLEEPNOW1 0xE6
1728 #endif
1729 #ifndef WIN_SLEEPNOW2
1730 #define WIN_SLEEPNOW2 0x99
1731 #endif
1732                 if (get_sleepnow) printf(" issuing sleep command\n");
1733                 args[0] = WIN_SLEEPNOW1;
1734                 ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2);
1735         }
1736         if (set_seagate) {
1737                 args[0] = 0xfb;
1738                 if (get_seagate) printf(" disabling Seagate auto powersaving mode\n");
1739                 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1740         }
1741         if (set_standby) {
1742                 args[0] = WIN_SETIDLE1;
1743                 args[1] = standby_requested;
1744                 if (get_standby) {
1745                         print_flag(1, "standby", standby_requested);
1746                         interpret_standby(standby_requested);
1747                 }
1748                 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
1749                 args[1] = 0;
1750         }
1751 #else   /* HDIO_DRIVE_CMD */
1752         if (force_operation) {
1753                 char buf[512];
1754                 flush_buffer_cache();
1755                 if (-1 == read(fd, buf, sizeof(buf)))
1756                         bb_perror_msg("read(%d bytes) failed (rc=-1)", sizeof(buf));
1757         }
1758 #endif  /* HDIO_DRIVE_CMD */
1759
1760         if (get_mult || get_identity) {
1761                 multcount = -1;
1762                 if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) {
1763                         if (get_mult && ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn. */
1764                                 bb_perror_msg("HDIO_GET_MULTCOUNT");
1765                         else
1766                                 bb_perror_msg("ioctl %#x failed", HDIO_GET_MULTCOUNT);
1767                 } else if (get_mult) {
1768                         printf(fmt, "multcount", multcount);
1769                         on_off(multcount != 0);
1770                 }
1771         }
1772         if (get_io32bit) {
1773                 if (!ioctl_or_warn(fd, HDIO_GET_32BIT, &parm)) {
1774                         printf(" IO_support\t=%3ld (", parm);
1775                         if (parm == 0)
1776                                 printf("default 16-bit)\n");
1777                         else if (parm == 2)
1778                                 printf("16-bit)\n");
1779                         else if (parm == 1)
1780                                 printf("32-bit)\n");
1781                         else if (parm == 3)
1782                                 printf("32-bit w/sync)\n");
1783                         else if (parm == 8)
1784                                 printf("Request-Queue-Bypass)\n");
1785                         else
1786                                 printf("\?\?\?)\n");
1787                 }
1788         }
1789         if (get_unmask) {
1790                 if(!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, (unsigned long *)parm))
1791                         print_value_on_off("unmaskirq", parm);
1792         }
1793
1794
1795 #if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
1796         if (get_dma) {
1797                 if (!ioctl_or_warn(fd, HDIO_GET_DMA, &parm)) {
1798                         printf(fmt, "using_dma", parm);
1799                         if (parm == 8)
1800                                 printf(" (DMA-Assisted-PIO)\n");
1801                         else
1802                                 on_off(parm != 0);
1803                 }
1804         }
1805 #endif
1806         if (get_dma_q) {
1807                 if(!ioctl_or_warn(fd, HDIO_GET_QDMA, (unsigned long *)parm))
1808                         print_value_on_off("queue_depth", parm);
1809         }
1810         if (get_keep) {
1811                 if(!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, (unsigned long *)parm))
1812                         print_value_on_off("keepsettings", parm);
1813         }
1814
1815         if (get_nowerr) {
1816                 if(!ioctl_or_warn(fd, HDIO_GET_NOWERR, (unsigned long *)parm))
1817                         print_value_on_off("nowerr", parm);
1818         }
1819         if (get_readonly) {
1820                 if(!ioctl_or_warn(fd, BLKROGET, (unsigned long *)parm))
1821                         print_value_on_off("readonly", parm);
1822         }
1823         if (get_readahead) {
1824                 if(!ioctl_or_warn(fd, BLKRAGET, (unsigned long *)parm))
1825                         print_value_on_off("readahead", parm);
1826         }
1827         if (get_geom) {
1828                 if (!ioctl_or_warn(fd, BLKGETSIZE, &parm)) {
1829                         struct hd_geometry g;
1830
1831                         if (!ioctl_or_warn(fd, HDIO_GETGEO, &g))
1832                                 printf(" geometry\t= %u/%u/%u, sectors = %ld, start = %ld\n",
1833                                                 g.cylinders, g.heads, g.sectors, parm, g.start);
1834                 }
1835         }
1836 #ifdef HDIO_DRIVE_CMD
1837         if (get_powermode) {
1838 #ifndef WIN_CHECKPOWERMODE1
1839 #define WIN_CHECKPOWERMODE1 0xE5
1840 #endif
1841 #ifndef WIN_CHECKPOWERMODE2
1842 #define WIN_CHECKPOWERMODE2 0x98
1843 #endif
1844                 const char *state;
1845
1846                 args[0] = WIN_CHECKPOWERMODE1;
1847                 if (ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2)) {
1848                         if (errno != EIO || args[0] != 0 || args[1] != 0)
1849                                 state = "unknown";
1850                         else
1851                                 state = "sleeping";
1852                 } else
1853                         state = (args[2] == 255) ? "active/idle" : "standby";
1854                 args[1] = args[2] = 0;
1855
1856                 printf(" drive state is:  %s\n", state);
1857         }
1858 #endif
1859 #if ENABLE_FEATURE_HDPARM_HDIO_DRIVE_RESET
1860         if (perform_reset) {
1861                 ioctl_or_warn(fd, HDIO_DRIVE_RESET, NULL);
1862         }
1863 #endif /* FEATURE_HDPARM_HDIO_DRIVE_RESET */
1864 #if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
1865         if (perform_tristate) {
1866                 args[0] = 0;
1867                 args[1] = tristate;
1868                 ioctl_or_warn(fd, HDIO_TRISTATE_HWIF, &args);
1869         }
1870 #endif /* FEATURE_HDPARM_HDIO_TRISTATE_HWIF */
1871 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY
1872         if (get_identity) {
1873                 struct hd_driveid id;
1874
1875                 if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) {
1876                         if (multcount != -1) {
1877                                 id.multsect = multcount;
1878                                 id.multsect_valid |= 1;
1879                         } else
1880                                 id.multsect_valid &= ~1;
1881                         dump_identity(&id);
1882                 } else if (errno == -ENOMSG)
1883                         printf(" no identification info available\n");
1884                 else if (ENABLE_IOCTL_HEX2STR_ERROR)  /* To be coherent with ioctl_or_warn */
1885                         bb_perror_msg("HDIO_GET_IDENTITY");
1886                 else
1887                         bb_perror_msg("ioctl %#x failed", HDIO_GET_IDENTITY);
1888         }
1889
1890         if (get_IDentity) {
1891                 unsigned char args1[4+512]; /* = { ... } will eat 0.5k of rodata! */
1892
1893                 memset(args1, 0, sizeof(args1));
1894                 args1[0] = WIN_IDENTIFY;
1895                 args1[3] = 1;
1896                 if (!ioctl_alt_or_warn(HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY))
1897                         identify((void *)(args1 + 4));
1898         }
1899 #endif
1900 #if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
1901         if (set_busstate) {
1902                 if (get_busstate) {
1903                         print_flag(1, "bus state", busstate);
1904                         bus_state_value(busstate);
1905                 }
1906                 ioctl_or_warn(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate);
1907         }
1908         if (get_busstate) {
1909                 if (!ioctl_or_warn(fd, HDIO_GET_BUSSTATE, &parm)) {
1910                         printf(fmt, "bus state", parm);
1911                         bus_state_value(parm);
1912                 }
1913         }
1914 #endif
1915         if (reread_partn)
1916                 ioctl_or_warn(fd, BLKRRPART, NULL);
1917
1918         if (do_ctimings)
1919                 do_time(1 /*,fd*/); /* time cache */
1920         if (do_timings)
1921                 do_time(0 /*,fd*/); /* time device */
1922         if (do_flush)
1923                 flush_buffer_cache();
1924         close(fd);
1925 }
1926
1927 #if ENABLE_FEATURE_HDPARM_GET_IDENTITY
1928 static int fromhex(unsigned char c)
1929 {
1930         if (isdigit(c))
1931                 return (c - '0');
1932         if (c >= 'a' && c <= 'f')
1933                 return (c - ('a' - 10));
1934         bb_error_msg_and_die("bad char: '%c' 0x%02x", c, c);
1935 }
1936
1937 static void identify_from_stdin(void) ATTRIBUTE_NORETURN;
1938 static void identify_from_stdin(void)
1939 {
1940         uint16_t sbuf[256];
1941         unsigned char buf[1280];
1942         unsigned char *b = (unsigned char *)buf;
1943         int i;
1944
1945         xread(0, buf, 1280);
1946
1947         // Convert the newline-separated hex data into an identify block.
1948
1949         for (i = 0; i < 256; i++) {
1950                 int j;
1951                 for (j = 0; j < 4; j++)
1952                         sbuf[i] = (sbuf[i] << 4) + fromhex(*(b++));
1953         }
1954
1955         // Parse the data.
1956
1957         identify(sbuf);
1958 }
1959 #else
1960 void identify_from_stdin(void);
1961 #endif
1962
1963 /* busybox specific stuff */
1964 static void parse_opts(smallint *get, smallint *set, unsigned long *value, int min, int max)
1965 {
1966         if (get) {
1967                 *get = 1;
1968         }
1969         if (optarg) {
1970                 *set = 1;
1971                 *value = xatol_range(optarg, min, max);
1972         }
1973 }
1974
1975 static void parse_xfermode(int flag, smallint *get, smallint *set, int *value)
1976 {
1977         if (flag) {
1978                 *get = 1;
1979                 if (optarg) {
1980                         *value = translate_xfermode(optarg);
1981                         *set = (*value > -1);
1982                 }
1983         }
1984 }
1985
1986 /*------- getopt short options --------*/
1987 static const char hdparm_options[] ALIGN1 =
1988         "gfu::n::p:r::m::c::k::a::B:tT"
1989         USE_FEATURE_HDPARM_GET_IDENTITY("iI")
1990         USE_FEATURE_HDPARM_HDIO_GETSET_DMA("d::")
1991 #ifdef HDIO_DRIVE_CMD
1992         "S:D:P:X:K:A:L:W:CyYzZ"
1993 #endif
1994         USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("U:")
1995 #ifdef HDIO_GET_QDMA
1996 #ifdef HDIO_SET_QDMA
1997         "Q:"
1998 #else
1999         "Q"
2000 #endif
2001 #endif
2002         USE_FEATURE_HDPARM_HDIO_DRIVE_RESET("w")
2003         USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF("x::b:")
2004         USE_FEATURE_HDPARM_HDIO_SCAN_HWIF("R:");
2005 /*-------------------------------------*/
2006
2007 /* our main() routine: */
2008 int hdparm_main(int argc, char **argv);
2009 int hdparm_main(int argc, char **argv)
2010 {
2011         int c;
2012         int flagcount = 0;
2013
2014         while ((c = getopt(argc, argv, hdparm_options)) >= 0) {
2015                 flagcount++;
2016                 USE_FEATURE_HDPARM_GET_IDENTITY(get_IDentity |= (c == 'I'));
2017                 USE_FEATURE_HDPARM_GET_IDENTITY(get_identity |= (c == 'i'));
2018                 get_geom |= (c == 'g');
2019                 do_flush |= (c == 'f');
2020                 if (c == 'u') parse_opts(&get_unmask, &set_unmask, &unmask, 0, 1);
2021                 USE_FEATURE_HDPARM_HDIO_GETSET_DMA(if (c == 'd') parse_opts(&get_dma, &set_dma, &dma, 0, 9));
2022                 if (c == 'n') parse_opts(&get_nowerr, &set_nowerr, &nowerr, 0, 1);
2023                 parse_xfermode((c == 'p'), &noisy_piomode, &set_piomode, &piomode);
2024                 if (c == 'r') parse_opts(&get_readonly, &set_readonly, &readonly, 0, 1);
2025                 if (c == 'm') parse_opts(&get_mult, &set_mult, &mult, 0, INT_MAX /*32*/);
2026                 if (c == 'c') parse_opts(&get_io32bit, &set_io32bit, &io32bit, 0, INT_MAX /*8*/);
2027                 if (c == 'k') parse_opts(&get_keep, &set_keep, &keep, 0, 1);
2028                 if (c == 'a') parse_opts(&get_readahead, &set_readahead, &Xreadahead, 0, INT_MAX);
2029                 if (c == 'B') parse_opts(&get_apmmode, &set_apmmode, &apmmode, 1, 255);
2030                 do_flush |= do_timings |= (c == 't');
2031                 do_flush |= do_ctimings |= (c == 'T');
2032 #ifdef HDIO_DRIVE_CMD
2033                 if (c == 'S') parse_opts(&get_standby, &set_standby, &standby_requested, 0, INT_MAX);
2034                 if (c == 'D') parse_opts(&get_defects, &set_defects, &defects, 0, INT_MAX);
2035                 if (c == 'P') parse_opts(&get_prefetch, &set_prefetch, &prefetch, 0, INT_MAX);
2036                 parse_xfermode((c == 'X'), &get_xfermode, &set_xfermode, &xfermode_requested);
2037                 if (c == 'K') parse_opts(&get_dkeep, &set_dkeep, &prefetch, 0, 1);
2038                 if (c == 'A') parse_opts(&get_lookahead, &set_lookahead, &lookahead, 0, 1);
2039                 if (c == 'L') parse_opts(&get_doorlock, &set_doorlock, &doorlock, 0, 1);
2040                 if (c == 'W') parse_opts(&get_wcache, &set_wcache, &wcache, 0, 1);
2041                 get_powermode |= (c == 'C');
2042                 get_standbynow = set_standbynow |= (c == 'y');
2043                 get_sleepnow = set_sleepnow |= (c == 'Y');
2044                 reread_partn |= (c == 'z');
2045                 get_seagate = set_seagate |= (c == 'Z');
2046 #endif
2047                 USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') parse_opts(NULL, &unregister_hwif, &hwif, 0, INT_MAX));
2048 #ifdef HDIO_GET_QDMA
2049                 if (c == 'Q') {
2050 #ifdef HDIO_SET_QDMA
2051                         parse_opts(&get_dma_q, &set_dma_q, &dma_q, 0, INT_MAX);
2052 #else
2053                         parse_opts(&get_dma_q, NULL, NULL, 0, 0);
2054 #endif
2055                 }
2056 #endif
2057                 USE_FEATURE_HDPARM_HDIO_DRIVE_RESET(perform_reset = (c == 'r'));
2058                 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'x') parse_opts(NULL, &perform_tristate, &tristate, 0, 1));
2059                 USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'b') parse_opts(&get_busstate, &set_busstate, &busstate, 0, 2));
2060 #if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
2061                 if (c == 'R') {
2062                         parse_opts(NULL, &scan_hwif, &hwif_data, 0, INT_MAX);
2063                         hwif_ctrl = xatoi_u((argv[optind]) ? argv[optind] : "");
2064                         hwif_irq  = xatoi_u((argv[optind+1]) ? argv[optind+1] : "");
2065                         /* Move past the 2 additional arguments */
2066                         argv += 2;
2067                         argc -= 2;
2068                 }
2069 #endif
2070         }
2071         /* When no flags are given (flagcount = 0), -acdgkmnru is assumed. */
2072         if (!flagcount) {
2073                 get_mult = get_io32bit = get_unmask = get_keep = get_readonly = get_readahead = get_geom = 1;
2074                 USE_FEATURE_HDPARM_HDIO_GETSET_DMA(get_dma = 1);
2075         }
2076         argv += optind;
2077
2078         if (!*argv) {
2079                 if (ENABLE_FEATURE_HDPARM_GET_IDENTITY && !isatty(STDIN_FILENO))
2080                         identify_from_stdin(); /* EXIT */
2081                 bb_show_usage();
2082         }
2083
2084         do {
2085                 process_dev(*argv++);
2086         } while (*argv);
2087
2088         return EXIT_SUCCESS;
2089 }