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