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