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