source: MondoRescue/branches/2.2.5/mindi-busybox/miscutils/hdparm.c@ 1765

Last change on this file since 1765 was 1765, checked in by Bruno Cornec, 16 years ago

Update to busybox 1.7.2

File size: 65.0 KB
Line 
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}
Note: See TracBrowser for help on using the repository browser.