source: MondoRescue/branches/3.3/mindi-busybox/miscutils/hdparm.c@ 3655

Last change on this file since 3655 was 3621, checked in by Bruno Cornec, 7 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

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