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