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
131static 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
166static 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
242static 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
282static 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
330static 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
383static void identify(uint16_t *id_supplied) ATTRIBUTE_NORETURN;
384static void identify_from_stdin(void) ATTRIBUTE_NORETURN;
385#else
386void 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
417static 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
446static 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
455static 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
465static void on_off(int value)
466{
467	puts(value ? " (on)" : " (off)");
468}
469
470static 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
478static 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
485static void print_ascii(uint16_t *p, uint8_t length);
486
487static 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
498static 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
518static 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
549static 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
1022static smallint get_identity, get_geom;
1023static smallint do_flush;
1024static smallint do_ctimings, do_timings;
1025static smallint reread_partn;
1026
1027static smallint set_piomode, noisy_piomode;
1028static smallint set_readahead, get_readahead;
1029static smallint set_readonly, get_readonly;
1030static smallint set_unmask, get_unmask;
1031static smallint set_mult, get_mult;
1032static smallint set_dma_q, get_dma_q;
1033static smallint set_nowerr, get_nowerr;
1034static smallint set_keep, get_keep;
1035static smallint set_io32bit, get_io32bit;
1036static int piomode;
1037static unsigned long Xreadahead;
1038static unsigned long readonly;
1039static unsigned long unmask;
1040static unsigned long mult;
1041static unsigned long dma_q;
1042static unsigned long nowerr;
1043static unsigned long keep;
1044static unsigned long io32bit;
1045#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
1046static unsigned long dma;
1047static smallint set_dma, get_dma;
1048#endif
1049#ifdef HDIO_DRIVE_CMD
1050static smallint set_xfermode, get_xfermode;
1051static smallint set_dkeep, get_dkeep;
1052static smallint set_standby, get_standby;
1053static smallint set_lookahead, get_lookahead;
1054static smallint set_prefetch, get_prefetch;
1055static smallint set_defects, get_defects;
1056static smallint set_wcache, get_wcache;
1057static smallint set_doorlock, get_doorlock;
1058static smallint set_seagate, get_seagate;
1059static smallint set_standbynow, get_standbynow;
1060static smallint set_sleepnow, get_sleepnow;
1061static smallint get_powermode;
1062static smallint set_apmmode, get_apmmode;
1063static int xfermode_requested;
1064static unsigned long dkeep;
1065static unsigned long standby_requested;
1066static unsigned long lookahead;
1067static unsigned long prefetch;
1068static unsigned long defects;
1069static unsigned long wcache;
1070static unsigned long doorlock;
1071static unsigned long apmmode;
1072#endif
1073USE_FEATURE_HDPARM_GET_IDENTITY(        static smallint get_IDentity;)
1074USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  static smallint set_busstate, get_busstate;)
1075USE_FEATURE_HDPARM_HDIO_DRIVE_RESET(    static smallint perform_reset;)
1076USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  static smallint perform_tristate;)
1077USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(static smallint unregister_hwif;)
1078USE_FEATURE_HDPARM_HDIO_SCAN_HWIF(      static smallint scan_hwif;)
1079USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  static unsigned long busstate;)
1080USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(  static unsigned long tristate;)
1081USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(static unsigned long hwif;)
1082#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
1083static unsigned long hwif_data;
1084static unsigned long hwif_ctrl;
1085static 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
1100static 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
1107static const char *const BuffType[] = {
1108	"Unknown", "1Sect", "DualPort", "DualPortCache"
1109};
1110
1111static 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
1246static 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
1261static int seek_to_zero(int fd)
1262{
1263	if (lseek(fd, (off_t) 0, SEEK_SET))
1264		return 1;
1265	return 0;
1266}
1267
1268static 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
1283static 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
1297static 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
1305static 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
1379static 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
1393static 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
1419static 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! */
1426static 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
1433static 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
1449static 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
1470static 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
1476static 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
1851static 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
1860static 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 */
1884static 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
1895static 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 --------*/
1907static 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: */
1928int hdparm_main(int argc, char **argv);
1929int 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}
2011