blob: 84675285a9b0ef6e262d55e34e601171060b5ea2 [file] [log] [blame]
Eric Andersen3443bd72003-07-22 07:30:36 +00001/* vi: set sw=4 ts=4: */
2/*
3 * hdparm implementation for busybox
4 *
Glenn L McGrath5be6a202003-11-28 22:55:03 +00005 * Copyright (C) [2003] by [Matteo Croce] <3297627799@wind.it>
Glenn L McGrath07085852003-10-09 07:28:22 +00006 * Hacked by Tito <farmatito@tiscali.it> for size optimization.
Eric Andersen3443bd72003-07-22 07:30:36 +00007 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02008 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
Eric Andersen3443bd72003-07-22 07:30:36 +00009 *
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 */
Denys Vlasenkofb4da162016-11-22 23:14:24 +010014//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
Denys Vlasenkof5604222017-01-10 14:58:54 +010028//config: Enable the -I and -i options to obtain detailed information
Denys Vlasenkofb4da162016-11-22 23:14:24 +010029//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
Denys Vlasenkof5604222017-01-10 14:58:54 +010038//config: Enable the 'hdparm -R' option to register an IDE interface.
Denys Vlasenkofb4da162016-11-22 23:14:24 +010039//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
Denys Vlasenkof5604222017-01-10 14:58:54 +010046//config: Enable the 'hdparm -U' option to un-register an IDE interface.
Denys Vlasenkofb4da162016-11-22 23:14:24 +010047//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
Denys Vlasenkof5604222017-01-10 14:58:54 +010054//config: Enable the 'hdparm -w' option to perform a device reset.
Denys Vlasenkofb4da162016-11-22 23:14:24 +010055//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
Denys Vlasenkof5604222017-01-10 14:58:54 +010062//config: Enable the 'hdparm -x' option to tristate device for hotswap,
Denys Vlasenkofb4da162016-11-22 23:14:24 +010063//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
Denys Vlasenkof5604222017-01-10 14:58:54 +010071//config: Enable the 'hdparm -d' option to get/set using_dma flag.
Pere Orga5bc8c002011-04-11 03:29:49 +020072
Denys Vlasenkof88e3bf2016-11-22 23:54:17 +010073//applet:IF_HDPARM(APPLET(hdparm, BB_DIR_SBIN, BB_SUID_DROP))
74
75//kbuild:lib-$(CONFIG_HDPARM) += hdparm.o
76
Pere Orga5bc8c002011-04-11 03:29:49 +020077//usage:#define hdparm_trivial_usage
78//usage: "[OPTIONS] [DEVICE]"
79//usage:#define hdparm_full_usage "\n\n"
Denys Vlasenko66426762011-06-05 03:58:28 +020080//usage: " -a Get/set fs readahead"
Pere Orga5bc8c002011-04-11 03:29:49 +020081//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
Denys Vlasenko860d2bb2009-07-10 18:37:06 +0200127#include "libbb.h"
Denys Vlasenkoe6a2f4c2016-04-21 16:26:30 +0200128#include "common_bufsiz.h"
Denys Vlasenko860d2bb2009-07-10 18:37:06 +0200129/* must be _after_ libbb.h: */
Eric Andersen3443bd72003-07-22 07:30:36 +0000130#include <linux/hdreg.h>
Denys Vlasenkoda49f582009-07-08 02:58:38 +0200131#include <sys/mount.h>
Denys Vlasenkoaf3fd142009-09-22 23:16:39 +0200132#if !defined(BLKGETSIZE64)
133# define BLKGETSIZE64 _IOR(0x12,114,size_t)
134#endif
Eric Andersen3443bd72003-07-22 07:30:36 +0000135
Eric Andersen3443bd72003-07-22 07:30:36 +0000136/* 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) */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000158#define START_MODEL 27 /* ASCII model number */
159#define LENGTH_MODEL 20 /* 20 words (40 bytes or characters) */
Denis Vlasenko4b924f32007-05-30 00:29:55 +0000160#define SECTOR_XFER_MAX 47 /* r/w multiple: max sectors xfered */
Eric Andersen3443bd72003-07-22 07:30:36 +0000161#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 */
Denis Vlasenko4b924f32007-05-30 00:29:55 +0000169#define LSECTS_CUR 56 /* current logical sectors/track */
Eric Andersen3443bd72003-07-22 07:30:36 +0000170#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 */
Denis Vlasenko551ffdc2009-04-01 19:48:05 +0000180#define DMA_TIME_NORM 66 /* - manufacturer's recommended */
Eric Andersen3443bd72003-07-22 07:30:36 +0000181 /* 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
Glenn L McGrath07085852003-10-09 07:28:22 +0000202 in low byte, 0x40 in high byte. */
Denis Vlasenko551ffdc2009-04-01 19:48:05 +0000203#define PSWD_CODE 92 /* master password revision code */
Eric Andersen3443bd72003-07-22 07:30:36 +0000204#define HWRST_RSLT 93 /* hardware reset result */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000205#define ACOUSTIC 94 /* acoustic mgmt values ( >= ATA-6) */
Eric Andersen3443bd72003-07-22 07:30:36 +0000206#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. */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000210#define RM_STAT 127 /* removable media status notification feature set support */
Eric Andersen3443bd72003-07-22 07:30:36 +0000211#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 */
Glenn L McGrath07085852003-10-09 07:28:22 +0000230#define NOT_ATA 0x8000
Eric Andersen3443bd72003-07-22 07:30:36 +0000231#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
Eric Andersen3443bd72003-07-22 07:30:36 +0000248/* word 1: number of logical cylinders */
249#define LCYLS_MAX 0x3fff /* maximum allowable value */
250
Eric Andersenaff114c2004-04-14 17:51:38 +0000251/* word 2: specific configuration
Eric Andersen3443bd72003-07-22 07:30:36 +0000252 * (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) */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000257#define PWRD_NID_VAL 0x8c73 /* not (a) and (b) */
Eric Andersen3443bd72003-07-22 07:30:36 +0000258#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 */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000265#define STD_STBY 0x2000 /* 1=standard values supported (ATA); 0=vendor specific values */
Eric Andersen3443bd72003-07-22 07:30:36 +0000266#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 */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000282#define OK_W88 0x0004 /* the ultra_dma info is valid */
Eric Andersen3443bd72003-07-22 07:30:36 +0000283#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 */
Rob Landley0e6a3e12006-04-28 01:33:30 +0000302#define MINOR_MAX 0x22
Eric Andersen3443bd72003-07-22 07:30:36 +0000303/* 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*/
Glenn L McGrath07085852003-10-09 07:28:22 +0000307#define SUPPORT_48_BIT 0x0400
Eric Andersen3443bd72003-07-22 07:30:36 +0000308#define NUM_CMD_FEAT_STR 48
309
Eric Andersen3443bd72003-07-22 07:30:36 +0000310/* words 85-87: cmds/feats enabled */
311/* use cmd_feat_str[] to display what commands and features have
Glenn L McGrath07085852003-10-09 07:28:22 +0000312 * been enabled with words 85-87
Eric Andersen3443bd72003-07-22 07:30:36 +0000313 */
314
315/* words 89, 90, SECU ERASE TIME */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000316#define ERASE_BITS 0x00ff
Eric Andersen3443bd72003-07-22 07:30:36 +0000317
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 */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000322#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 */
Eric Andersen3443bd72003-07-22 07:30:36 +0000327
328/* word 127: removable media status notification feature set support */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000329#define RM_STAT_BITS 0x0003
330#define RM_STAT_SUP 0x0001
Glenn L McGrath07085852003-10-09 07:28:22 +0000331
Eric Andersen3443bd72003-07-22 07:30:36 +0000332/* word 128: security */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000333#define SECU_ENABLED 0x0002
334#define SECU_LEVEL 0x0010
335#define NUM_SECU_STR 6
Eric Andersen3443bd72003-07-22 07:30:36 +0000336
337/* word 160: CFA power mode */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000338#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 */
Eric Andersen3443bd72003-07-22 07:30:36 +0000342
343/* word 255: integrity */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000344#define SIG 0x00ff /* signature location */
345#define SIG_VAL 0x00a5 /* signature value */
Eric Andersen3443bd72003-07-22 07:30:36 +0000346
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000347#define TIMING_BUF_MB 1
348#define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024)
Glenn L McGrath07085852003-10-09 07:28:22 +0000349
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000350#undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */
Glenn L McGrath07085852003-10-09 07:28:22 +0000351
Denis Vlasenko892536f2007-09-27 10:23:34 +0000352
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200353#define IS_GET 1
354#define IS_SET 2
355
356
Denis Vlasenko892536f2007-09-27 10:23:34 +0000357enum { fd = 3 };
358
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000359
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;
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200366 smallint getset_readahead;
367 smallint getset_readonly;
368 smallint getset_unmask;
369 smallint getset_mult;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000370#ifdef HDIO_GET_QDMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200371 smallint getset_dma_q;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000372#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200373 smallint getset_nowerr;
374 smallint getset_keep;
375 smallint getset_io32bit;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000376 int piomode;
377 unsigned long Xreadahead;
378 unsigned long readonly;
379 unsigned long unmask;
380 unsigned long mult;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000381#ifdef HDIO_SET_QDMA
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000382 unsigned long dma_q;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000383#endif
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000384 unsigned long nowerr;
385 unsigned long keep;
386 unsigned long io32bit;
387#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
388 unsigned long dma;
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200389 smallint getset_dma;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000390#endif
391#ifdef HDIO_DRIVE_CMD
392 smallint set_xfermode, get_xfermode;
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200393 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;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000403 smallint get_powermode;
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200404 smallint getset_apmmode;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000405 int xfermode_requested;
406 unsigned long dkeep;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000407 unsigned long standby_requested; /* 0..255 */
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000408 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
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000415 IF_FEATURE_HDPARM_GET_IDENTITY( smallint get_IDentity;)
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200416 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( smallint getset_busstate;)
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000417 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;)
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000424#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
425 unsigned long hwif_data;
426 unsigned long hwif_ctrl;
427 unsigned long hwif_irq;
428#endif
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +0000429#ifdef DO_FLUSHCACHE
430 unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };
431#endif
Denys Vlasenko98a4c7c2010-02-04 15:00:15 +0100432} FIX_ALIASING;
Denys Vlasenkoe6a2f4c2016-04-21 16:26:30 +0200433#define G (*(struct globals*)bb_common_bufsiz1)
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000434#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 )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200442#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 )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000450#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 )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200460#define getset_dma (G.getset_dma )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000461#define set_xfermode (G.set_xfermode )
462#define get_xfermode (G.get_xfermode )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200463#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 )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000470#define set_seagate (G.set_seagate )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000471#define set_standbynow (G.set_standbynow )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000472#define set_sleepnow (G.set_sleepnow )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000473#define get_powermode (G.get_powermode )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200474#define getset_apmmode (G.getset_apmmode )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000475#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 )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200485#define getset_busstate (G.getset_busstate )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000486#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 )
Denys Vlasenko7b85ec32015-10-13 17:17:34 +0200496#define INIT_G() do { \
Denys Vlasenko47cfbf32016-04-21 18:18:48 +0200497 setup_common_bufsiz(); \
Denys Vlasenko7b85ec32015-10-13 17:17:34 +0200498 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
499} while (0)
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000500
501
Glenn L McGrath07085852003-10-09 07:28:22 +0000502/* Busybox messages and functions */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000503#if ENABLE_IOCTL_HEX2STR_ERROR
Denis Vlasenko892536f2007-09-27 10:23:34 +0000504static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt, const char *string)
Rob Landley5f8b5ec2006-04-29 16:03:40 +0000505{
506 if (!ioctl(fd, cmd, args))
507 return 0;
508 args[0] = alt;
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000509 return bb_ioctl_or_warn(fd, cmd, args, string);
Rob Landley5f8b5ec2006-04-29 16:03:40 +0000510}
Denis Vlasenko892536f2007-09-27 10:23:34 +0000511#define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt,#cmd)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000512#else
Denis Vlasenko892536f2007-09-27 10:23:34 +0000513static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000514{
515 if (!ioctl(fd, cmd, args))
516 return 0;
517 args[0] = alt;
518 return bb_ioctl_or_warn(fd, cmd, args);
519}
Denis Vlasenko892536f2007-09-27 10:23:34 +0000520#define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000521#endif
Rob Landley5f8b5ec2006-04-29 16:03:40 +0000522
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000523static void on_off(int value)
524{
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000525 puts(value ? " (on)" : " (off)");
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000526}
Glenn L McGrath07085852003-10-09 07:28:22 +0000527
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000528static void print_flag_on_off(int get_arg, const char *s, unsigned long arg)
Glenn L McGrath07085852003-10-09 07:28:22 +0000529{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +0000530 if (get_arg) {
Denys Vlasenko327f5502013-11-29 16:45:45 +0100531 printf(" setting %s to %lu", s, arg);
Glenn L McGrath07085852003-10-09 07:28:22 +0000532 on_off(arg);
533 }
534}
535
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000536static void print_value_on_off(const char *str, unsigned long argp)
Glenn L McGrath07085852003-10-09 07:28:22 +0000537{
Denys Vlasenko327f5502013-11-29 16:45:45 +0100538 printf(" %s\t= %2lu", str, argp);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000539 on_off(argp != 0);
Glenn L McGrath07085852003-10-09 07:28:22 +0000540}
Eric Andersen416c2422003-12-12 00:08:57 +0000541
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000542#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
Denis Vlasenko4daad902007-09-27 10:20:47 +0000543static 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}
Glenn L McGrath07085852003-10-09 07:28:22 +0000571
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000572static void xprint_ascii(uint16_t *val, int i, const char *string, int n)
Glenn L McGrath07085852003-10-09 07:28:22 +0000573{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +0000574 if (val[i]) {
575 printf("\t%-20s", string);
Denis Vlasenko4daad902007-09-27 10:20:47 +0000576 print_ascii((void*)&val[i], n);
Glenn L McGrath07085852003-10-09 07:28:22 +0000577 }
578}
Glenn L McGrath07085852003-10-09 07:28:22 +0000579
Glenn L McGrath07085852003-10-09 07:28:22 +0000580static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode)
581{
Eric Andersen3443bd72003-07-22 07:30:36 +0000582 uint16_t ii;
583 uint8_t err_dma = 0;
Glenn L McGrath07085852003-10-09 07:28:22 +0000584
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000585 for (ii = 0; ii <= MODE_MAX; ii++) {
586 if (mode_sel & 0x0001) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000587 printf("*%cdma%u ", cc, ii);
Rob Landleya3e4f382006-04-29 16:06:31 +0000588 if (*have_mode)
Glenn L McGrath07085852003-10-09 07:28:22 +0000589 err_dma = 1;
Eric Andersen3443bd72003-07-22 07:30:36 +0000590 *have_mode = 1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000591 } else if (mode_sup & 0x0001)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000592 printf("%cdma%u ", cc, ii);
Glenn L McGrath07085852003-10-09 07:28:22 +0000593
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000594 mode_sup >>= 1;
595 mode_sel >>= 1;
Eric Andersen3443bd72003-07-22 07:30:36 +0000596 }
597 return err_dma;
598}
Glenn L McGrath07085852003-10-09 07:28:22 +0000599
Denis Vlasenko91303402007-10-30 19:36:54 +0000600static 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.
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000780static void identify(uint16_t *val) NORETURN;
Denis Vlasenko4daad902007-09-27 10:20:47 +0000781static void identify(uint16_t *val)
Eric Andersen3443bd72003-07-22 07:30:36 +0000782{
Denis Vlasenko4daad902007-09-27 10:20:47 +0000783 uint16_t ii, jj, kk;
Eric Andersen3443bd72003-07-22 07:30:36 +0000784 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;
Rob Landley2e2d7522006-04-29 15:23:33 +0000789 uint64_t bbbig; /* (:) */
Rob Landleyadde7982006-05-16 15:32:30 +0000790 const char *strng;
Denis Vlasenko4daad902007-09-27 10:20:47 +0000791#if BB_BIG_ENDIAN
792 uint16_t buf[256];
Eric Andersen3443bd72003-07-22 07:30:36 +0000793
Denis Vlasenko4daad902007-09-27 10:20:47 +0000794 // Adjust for endianness
795 swab(val, buf, sizeof(buf));
796 val = buf;
797#endif
Denys Vlasenkob22bbff2009-07-04 16:50:43 +0200798 /* check if we recognize the device type */
Denis Vlasenko4daad902007-09-27 10:20:47 +0000799 bb_putchar('\n');
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000800 if (!(val[GEN_CONFIG] & NOT_ATA)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000801 dev = ATA_DEV;
802 printf("ATA device, with ");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000803 } else if (val[GEN_CONFIG]==CFA_SUPPORT_VAL) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000804 dev = ATA_DEV;
805 like_std = 4;
806 printf("CompactFlash ATA device, with ");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000807 } else if (!(val[GEN_CONFIG] & NOT_ATAPI)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000808 dev = ATAPI_DEV;
809 eqpt = (val[GEN_CONFIG] & EQPT_TYPE) >> SHIFT_EQPT;
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000810 printf("ATAPI %s, with ", eqpt <= 0xf ? nth_string(pkt_str, eqpt) : "unknown");
Eric Andersen3443bd72003-07-22 07:30:36 +0000811 like_std = 3;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000812 } else
Denis Vlasenko91303402007-10-30 19:36:54 +0000813 /* "Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n" */
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +0000814 bb_error_msg_and_die("unknown device type");
Eric Andersen3443bd72003-07-22 07:30:36 +0000815
Rob Landleyadde7982006-05-16 15:32:30 +0000816 printf("%sremovable media\n", !(val[GEN_CONFIG] & MEDIA_REMOVABLE) ? "non-" : "");
Eric Andersen3443bd72003-07-22 07:30:36 +0000817 /* Info from the specific configuration word says whether or not the
818 * ID command completed correctly. It is only defined, however in
Glenn L McGrath07085852003-10-09 07:28:22 +0000819 * ATA/ATAPI-5 & 6; it is reserved (value theoretically 0) in prior
Eric Andersen3443bd72003-07-22 07:30:36 +0000820 * 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 */
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000824 if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL)
825 || (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL)
826 ) {
Glenn L McGrath07085852003-10-09 07:28:22 +0000827 like_std = 5;
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000828 if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL))
Denys Vlasenkod60752f2015-10-07 22:42:45 +0200829 puts("powers-up in standby; SET FEATURES subcmd spins-up.");
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000830 if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE))
Denys Vlasenkod60752f2015-10-07 22:42:45 +0200831 puts("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n");
Eric Andersen3443bd72003-07-22 07:30:36 +0000832 }
833
834 /* output the model and serial numbers and the fw revision */
Glenn L McGrath07085852003-10-09 07:28:22 +0000835 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);
Eric Andersen3443bd72003-07-22 07:30:36 +0000840
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:");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000844 if (eqpt != CDROM) {
845 if (val[MINOR] && (val[MINOR] <= MINOR_MAX)) {
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000846 if (like_std < 3) like_std = 3;
Eric Andersen3443bd72003-07-22 07:30:36 +0000847 std = actual_ver[val[MINOR]];
Denys Vlasenkof3ea7922010-07-26 01:06:14 +0200848 if (std)
849 printf("\n\tUsed: %s ", nth_string(minor_str, val[MINOR]));
Eric Andersen3443bd72003-07-22 07:30:36 +0000850 }
851 /* looks like when they up-issue the std, they obsolete one;
Glenn L McGrath07085852003-10-09 07:28:22 +0000852 * thus, only the newest 4 issues need be supported. (That's
Eric Andersen3443bd72003-07-22 07:30:36 +0000853 * what "kk" and "min_std" are all about.) */
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000854 if (val[MAJOR] && (val[MAJOR] != NOVAL_1)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000855 printf("\n\tSupported: ");
856 jj = val[MAJOR] << 1;
857 kk = like_std >4 ? like_std-4: 0;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000858 for (ii = 14; (ii >0)&&(ii>kk); ii--) {
859 if (jj & 0x8000) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000860 printf("%u ", ii);
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000861 if (like_std < ii) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000862 like_std = ii;
863 kk = like_std >4 ? like_std-4: 0;
864 }
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000865 if (min_std > ii) min_std = ii;
Eric Andersen3443bd72003-07-22 07:30:36 +0000866 }
867 jj <<= 1;
868 }
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000869 if (like_std < 3) like_std = 3;
Eric Andersen3443bd72003-07-22 07:30:36 +0000870 }
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 */
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000875 if (like_std < std) like_std = std;
Glenn L McGrath07085852003-10-09 07:28:22 +0000876
Rob Landleya3e4f382006-04-29 16:06:31 +0000877 if (((std == 5) || (!std && (like_std < 6))) &&
Glenn L McGrath07085852003-10-09 07:28:22 +0000878 ((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
879 (( val[CMDS_SUPP_1] & CMDS_W83) > 0x00ff)) ||
880 ((( val[CMDS_SUPP_2] & VALID) == VALID_VAL) &&
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000881 ( val[CMDS_SUPP_2] & CMDS_W84) ) )
882 ) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000883 like_std = 6;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000884 } else if (((std == 4) || (!std && (like_std < 5))) &&
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000885 ((((val[INTEGRITY] & SIG) == SIG_VAL) && !chksum) ||
Glenn L McGrath07085852003-10-09 07:28:22 +0000886 (( val[HWRST_RSLT] & VALID) == VALID_VAL) ||
887 ((( val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
888 (( val[CMDS_SUPP_1] & CMDS_W83) > 0x001f)) ) )
889 {
Eric Andersen3443bd72003-07-22 07:30:36 +0000890 like_std = 5;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000891 } else if (((std == 3) || (!std && (like_std < 4))) &&
Glenn L McGrath07085852003-10-09 07:28:22 +0000892 ((((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]) ||
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000897 (( val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) )
898 ) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000899 like_std = 4;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000900 } else if (((std == 2) || (!std && (like_std < 3)))
901 && ((val[CMDS_SUPP_1] & VALID) == VALID_VAL)
902 ) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000903 like_std = 3;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000904 } else if (((std == 1) || (!std && (like_std < 2))) &&
Glenn L McGrath07085852003-10-09 07:28:22 +0000905 ((val[CAPAB_0] & (IORDY_SUP | IORDY_OFF)) ||
906 (val[WHATS_VALID] & OK_W64_70)) )
907 {
Eric Andersen3443bd72003-07-22 07:30:36 +0000908 like_std = 2;
909 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000910
Rob Landleya3e4f382006-04-29 16:06:31 +0000911 if (!std)
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000912 printf("\n\tLikely used: %u\n", like_std);
Rob Landleya3e4f382006-04-29 16:06:31 +0000913 else if (like_std > std)
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000914 printf("& some of %u\n", like_std);
Glenn L McGrath07085852003-10-09 07:28:22 +0000915 else
Denis Vlasenko4daad902007-09-27 10:20:47 +0000916 bb_putchar('\n');
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000917 } else {
Eric Andersen3443bd72003-07-22 07:30:36 +0000918 /* TBD: do CDROM stuff more thoroughly. For now... */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000919 kk = 0;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000920 if (val[CDR_MINOR] == 9) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000921 kk = 1;
922 printf("\n\tUsed: ATAPI for CD-ROMs, SFF-8020i, r2.5");
923 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000924 if (val[CDR_MAJOR] && (val[CDR_MAJOR] !=NOVAL_1)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000925 kk = 1;
926 printf("\n\tSupported: CD-ROM ATAPI");
927 jj = val[CDR_MAJOR] >> 1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000928 for (ii = 1; ii < 15; ii++) {
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000929 if (jj & 0x0001) printf("-%u ", ii);
Eric Andersen3443bd72003-07-22 07:30:36 +0000930 jj >>= 1;
931 }
932 }
Denis Vlasenkofeb7ae72007-10-01 12:05:12 +0000933 puts(kk ? "" : "\n\tLikely used CD-ROM ATAPI-1");
Eric Andersen3443bd72003-07-22 07:30:36 +0000934 /* the cdrom stuff is more like ATA-2 than anything else, so: */
935 like_std = 2;
936 }
937
Rob Landleya3e4f382006-04-29 16:06:31 +0000938 if (min_std == 0xffff)
Glenn L McGrath07085852003-10-09 07:28:22 +0000939 min_std = like_std > 4 ? like_std - 3 : 1;
Eric Andersen3443bd72003-07-22 07:30:36 +0000940
Denys Vlasenkod60752f2015-10-07 22:42:45 +0200941 puts("Configuration:");
Eric Andersen3443bd72003-07-22 07:30:36 +0000942 /* more info from the general configuration word */
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000943 if ((eqpt != CDROM) && (like_std == 1)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000944 jj = val[GEN_CONFIG] >> 1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000945 for (ii = 1; ii < 15; ii++) {
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000946 if (jj & 0x0001)
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000947 printf("\t%s\n", nth_string(ata1_cfg_str, ii));
Eric Andersen3443bd72003-07-22 07:30:36 +0000948 jj >>=1;
949 }
950 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000951 if (dev == ATAPI_DEV) {
Rob Landleyadde7982006-05-16 15:32:30 +0000952 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";
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000958 else
Denis Vlasenko91303402007-10-30 19:36:54 +0000959 strng = "unknown";
Rob Landleyadde7982006-05-16 15:32:30 +0000960 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
Denis Vlasenko91303402007-10-30 19:36:54 +0000967 strng = "unknown";
Rob Landleyadde7982006-05-16 15:32:30 +0000968 puts(strng);
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000969 } else {
Glenn L McGrath07085852003-10-09 07:28:22 +0000970 /* addressing...CHS? See section 6.2 of ATA specs 4 or 5 */
Eric Andersen3443bd72003-07-22 07:30:36 +0000971 ll = (uint32_t)val[LBA_SECTS_MSB] << 16 | val[LBA_SECTS_LSB];
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200972 mm = 0;
973 bbbig = 0;
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000974 if ((ll > 0x00FBFC10) && (!val[LCYLS]))
Denys Vlasenkod60752f2015-10-07 22:42:45 +0200975 puts("\tCHS addressing not supported");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000976 else {
Eric Andersen3443bd72003-07-22 07:30:36 +0000977 jj = val[WHATS_VALID] & OK_W54_58;
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200978 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);
Glenn L McGrath07085852003-10-09 07:28:22 +0000989
Rob Landleyadde7982006-05-16 15:32:30 +0000990 if ((min_std == 1) && (val[TRACK_BYTES] || val[SECT_BYTES]))
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200991 printf("\tbytes/track: %u\tbytes/sector: %u\n",
992 val[TRACK_BYTES], val[SECT_BYTES]);
Glenn L McGrath07085852003-10-09 07:28:22 +0000993
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000994 if (jj) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000995 mm = (uint32_t)val[CAPACITY_MSB] << 16 | val[CAPACITY_LSB];
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000996 if (like_std < 3) {
997 /* check Endian of capacity bytes */
Eric Andersen3443bd72003-07-22 07:30:36 +0000998 nn = val[LCYLS_CUR] * val[LHEADS_CUR] * val[LSECTS_CUR];
999 oo = (uint32_t)val[CAPACITY_LSB] << 16 | val[CAPACITY_MSB];
Rob Landleya3e4f382006-04-29 16:06:31 +00001000 if (abs(mm - nn) > abs(oo - nn))
Eric Andersen3443bd72003-07-22 07:30:36 +00001001 mm = oo;
1002 }
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001003 printf("\tCHS current addressable sectors:%11u\n", mm);
Glenn L McGrath07085852003-10-09 07:28:22 +00001004 }
Eric Andersen3443bd72003-07-22 07:30:36 +00001005 }
1006 /* LBA addressing */
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001007 printf("\tLBA user addressable sectors:%11u\n", ll);
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001008 if (((val[CMDS_SUPP_1] & VALID) == VALID_VAL)
1009 && (val[CMDS_SUPP_1] & SUPPORT_48_BIT)
1010 ) {
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001011 bbbig = (uint64_t)val[LBA_64_MSB] << 48 |
1012 (uint64_t)val[LBA_48_MSB] << 32 |
1013 (uint64_t)val[LBA_MID] << 16 |
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001014 val[LBA_LSB];
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001015 printf("\tLBA48 user addressable sectors:%11"PRIu64"\n", bbbig);
Eric Andersen3443bd72003-07-22 07:30:36 +00001016 }
Glenn L McGrath07085852003-10-09 07:28:22 +00001017
1018 if (!bbbig)
Rob Landley2e2d7522006-04-29 15:23:33 +00001019 bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001020 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);
Glenn L McGrath07085852003-10-09 07:28:22 +00001023
Rob Landleyadde7982006-05-16 15:32:30 +00001024 if (bbbig > 1000)
Rob Landley81dab2c2006-05-28 01:56:08 +00001025 printf("(%"PRIu64" GB)\n", bbbig/1000);
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00001026 else
Denis Vlasenko4daad902007-09-27 10:20:47 +00001027 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001028 }
1029
1030 /* hw support of commands (capabilities) */
Glenn L McGrath07085852003-10-09 07:28:22 +00001031 printf("Capabilities:\n\t");
1032
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001033 if (dev == ATAPI_DEV) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001034 if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP))
1035 printf("Cmd queuing, ");
1036 if (val[CAPAB_0] & OVLP_SUP)
1037 printf("Cmd overlap, ");
Eric Andersen3443bd72003-07-22 07:30:36 +00001038 }
Rob Landleyadde7982006-05-16 15:32:30 +00001039 if (val[CAPAB_0] & LBA_SUP) printf("LBA, ");
Glenn L McGrath07085852003-10-09 07:28:22 +00001040
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001041 if (like_std != 1) {
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00001042 printf("IORDY%s(can%s be disabled)\n",
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001043 !(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "",
1044 (val[CAPAB_0] & IORDY_OFF) ? "" :"not");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001045 } else
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001046 puts("no IORDY");
Glenn L McGrath07085852003-10-09 07:28:22 +00001047
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001048 if ((like_std == 1) && val[BUF_TYPE]) {
Rob Landleyadde7982006-05-16 15:32:30 +00001049 printf("\tBuffer type: %04x: %s%s\n", val[BUF_TYPE],
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001050 (val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector",
1051 (val[BUF_TYPE] > 2) ? " with read caching ability" : "");
Eric Andersen3443bd72003-07-22 07:30:36 +00001052 }
Rob Landleyadde7982006-05-16 15:32:30 +00001053
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001054 if ((min_std == 1) && (val[BUFFER__SIZE] && (val[BUFFER__SIZE] != NOVAL_1))) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001055 printf("\tBuffer size: %.1fkB\n", (float)val[BUFFER__SIZE]/2);
Eric Andersen3443bd72003-07-22 07:30:36 +00001056 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001057 if ((min_std < 4) && (val[RW_LONG])) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001058 printf("\tbytes avail on r/w long: %u\n", val[RW_LONG]);
Eric Andersen3443bd72003-07-22 07:30:36 +00001059 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001060 if ((eqpt != CDROM) && (like_std > 3)) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001061 printf("\tQueue depth: %u\n", (val[QUEUE_DEPTH] & DEPTH_BITS) + 1);
Eric Andersen3443bd72003-07-22 07:30:36 +00001062 }
Glenn L McGrath07085852003-10-09 07:28:22 +00001063
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001064 if (dev == ATA_DEV) {
Rob Landleya3e4f382006-04-29 16:06:31 +00001065 if (like_std == 1)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001066 printf("\tCan%s perform double-word IO\n", (!val[DWORD_IO]) ? "not" : "");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001067 else {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001068 printf("\tStandby timer values: spec'd by %s",
1069 (val[CAPAB_0] & STD_STBY) ? "standard" : "vendor");
Rob Landleya3e4f382006-04-29 16:06:31 +00001070 if ((like_std > 3) && ((val[CAPAB_1] & VALID) == VALID_VAL))
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001071 printf(", %s device specific minimum\n",
1072 (val[CAPAB_1] & MIN_STANDBY_TIMER) ? "with" : "no");
Glenn L McGrath07085852003-10-09 07:28:22 +00001073 else
Denis Vlasenko4daad902007-09-27 10:20:47 +00001074 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001075 }
1076 printf("\tR/W multiple sector transfer: ");
Rob Landleya3e4f382006-04-29 16:06:31 +00001077 if ((like_std < 3) && !(val[SECTOR_XFER_MAX] & SECTOR_XFER))
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001078 puts("not supported");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001079 else {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001080 printf("Max = %u\tCurrent = ", val[SECTOR_XFER_MAX] & SECTOR_XFER);
Rob Landleyadde7982006-05-16 15:32:30 +00001081 if (val[SECTOR_XFER_CUR] & MULTIPLE_SETTING_VALID)
1082 printf("%u\n", val[SECTOR_XFER_CUR] & SECTOR_XFER);
1083 else
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001084 puts("?");
Eric Andersen3443bd72003-07-22 07:30:36 +00001085 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001086 if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008)) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001087 /* We print out elsewhere whether the APM feature is enabled or
Denys Vlasenko60cb48c2013-01-14 15:57:44 +01001088 * not. If it's not enabled, let's not repeat the info; just print
1089 * nothing here. */
Glenn L McGrath07085852003-10-09 07:28:22 +00001090 printf("\tAdvancedPM level: ");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001091 if ((val[ADV_PWR] & 0xFF00) == 0x4000) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001092 uint8_t apm_level = val[ADV_PWR] & 0x00FF;
Eric Andersen3443bd72003-07-22 07:30:36 +00001093 printf("%u (0x%x)\n", apm_level, apm_level);
Glenn L McGrath07085852003-10-09 07:28:22 +00001094 }
1095 else
Eric Andersen3443bd72003-07-22 07:30:36 +00001096 printf("unknown setting (0x%04x)\n", val[ADV_PWR]);
Eric Andersen3443bd72003-07-22 07:30:36 +00001097 }
Rob Landleyadde7982006-05-16 15:32:30 +00001098 if (like_std > 5 && val[ACOUSTIC]) {
1099 printf("\tRecommended acoustic management value: %u, current value: %u\n",
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001100 (val[ACOUSTIC] >> 8) & 0x00ff,
1101 val[ACOUSTIC] & 0x00ff);
Eric Andersen3443bd72003-07-22 07:30:36 +00001102 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001103 } else {
Denys Vlasenko6830ade2013-01-15 13:58:01 +01001104 /* ATAPI */
Rob Landleyadde7982006-05-16 15:32:30 +00001105 if (eqpt != CDROM && (val[CAPAB_0] & SWRST_REQ))
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001106 puts("\tATA sw reset required");
Glenn L McGrath07085852003-10-09 07:28:22 +00001107
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001108 if (val[PKT_REL] || val[SVC_NBSY]) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001109 printf("\tOverlap support:");
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001110 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]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001115 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001116 }
1117 }
1118
1119 /* DMA stuff. Check that only one DMA mode is selected. */
1120 printf("\tDMA: ");
Rob Landleya3e4f382006-04-29 16:06:31 +00001121 if (!(val[CAPAB_0] & DMA_SUP))
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001122 puts("not supported");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001123 else {
Rob Landleyadde7982006-05-16 15:32:30 +00001124 if (val[DMA_MODE] && !val[SINGLE_DMA] && !val[MULTI_DMA])
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001125 printf(" sdma%u\n", (val[DMA_MODE] & MODE) >> 8);
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001126 if (val[SINGLE_DMA]) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001127 jj = val[SINGLE_DMA];
1128 kk = val[SINGLE_DMA] >> 8;
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001129 err_dma += mode_loop(jj, kk, 's', &have_mode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001130 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001131 if (val[MULTI_DMA]) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001132 jj = val[MULTI_DMA];
1133 kk = val[MULTI_DMA] >> 8;
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001134 err_dma += mode_loop(jj, kk, 'm', &have_mode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001135 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001136 if ((val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001137 jj = val[ULTRA_DMA];
1138 kk = val[ULTRA_DMA] >> 8;
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001139 err_dma += mode_loop(jj, kk, 'u', &have_mode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001140 }
Rob Landleyadde7982006-05-16 15:32:30 +00001141 if (err_dma || !have_mode) printf("(?)");
Denis Vlasenko4daad902007-09-27 10:20:47 +00001142 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001143
Rob Landleyadde7982006-05-16 15:32:30 +00001144 if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP))
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001145 puts("\t\tInterleaved DMA support");
Eric Andersen3443bd72003-07-22 07:30:36 +00001146
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001147 if ((val[WHATS_VALID] & OK_W64_70)
1148 && (val[DMA_TIME_MIN] || val[DMA_TIME_NORM])
1149 ) {
Rob Landleyadde7982006-05-16 15:32:30 +00001150 printf("\t\tCycle time:");
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001151 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]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001153 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001154 }
1155 }
1156
1157 /* Programmed IO stuff */
1158 printf("\tPIO: ");
Tim Rikerc1ef7bd2006-01-25 00:08:53 +00001159 /* If a drive supports mode n (e.g. 3), it also supports all modes less
Eric Andersen3443bd72003-07-22 07:30:36 +00001160 * than n (e.g. 3, 2, 1 and 0). Print all the modes. */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001161 if ((val[WHATS_VALID] & OK_W64_70) && (val[ADV_PIO_MODES] & PIO_SUP)) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001162 jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007;
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001163 for (ii = 0; ii <= PIO_MODE_MAX; ii++) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001164 if (jj & 0x0001) printf("pio%d ", ii);
Eric Andersen3443bd72003-07-22 07:30:36 +00001165 jj >>=1;
1166 }
Denis Vlasenko4daad902007-09-27 10:20:47 +00001167 bb_putchar('\n');
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001168 } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) {
Rob Landleya3e4f382006-04-29 16:06:31 +00001169 for (ii = 0; ii <= val[PIO_MODE]>>8; ii++)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001170 printf("pio%d ", ii);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001171 bb_putchar('\n');
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001172 } else
Denis Vlasenko91303402007-10-30 19:36:54 +00001173 puts("unknown");
Glenn L McGrath07085852003-10-09 07:28:22 +00001174
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001175 if (val[WHATS_VALID] & OK_W64_70) {
1176 if (val[PIO_NO_FLOW] || val[PIO_FLOW]) {
Rob Landleyadde7982006-05-16 15:32:30 +00001177 printf("\t\tCycle time:");
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001178 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]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001182 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001183 }
1184 }
1185
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001186 if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001187 puts("Commands/features:\n"
1188 "\tEnabled\tSupported:");
Eric Andersen3443bd72003-07-22 07:30:36 +00001189 jj = val[CMDS_SUPP_0];
1190 kk = val[CMDS_EN_0];
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001191 for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++) {
Denis Vlasenkobfc3d822007-11-04 04:10:17 +00001192 const char *feat_str = nth_string(cmd_feat_str, ii);
Denis Vlasenko91303402007-10-30 19:36:54 +00001193 if ((jj & 0x8000) && (*feat_str != '\0')) {
1194 printf("\t%s\t%s\n", (kk & 0x8000) ? " *" : "", feat_str);
Eric Andersen3443bd72003-07-22 07:30:36 +00001195 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001196 jj <<= 1;
1197 kk <<= 1;
1198 if (ii % 16 == 15) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001199 jj = val[CMDS_SUPP_0+1+(ii/16)];
1200 kk = val[CMDS_EN_0+1+(ii/16)];
1201 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001202 if (ii == 31) {
Rob Landleya3e4f382006-04-29 16:06:31 +00001203 if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL)
Glenn L McGrath07085852003-10-09 07:28:22 +00001204 ii +=16;
Eric Andersen3443bd72003-07-22 07:30:36 +00001205 }
1206 }
1207 }
Rob Landleyadde7982006-05-16 15:32:30 +00001208 /* Removable Media Status Notification feature set */
Denis Vlasenko67b23e62006-10-03 21:00:06 +00001209 if ((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP)
Denis Vlasenkobfc3d822007-11-04 04:10:17 +00001210 printf("\t%s supported\n", nth_string(cmd_feat_str, 27));
Glenn L McGrath07085852003-10-09 07:28:22 +00001211
Eric Andersen3443bd72003-07-22 07:30:36 +00001212 /* security */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001213 if ((eqpt != CDROM) && (like_std > 3)
1214 && (val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME])
1215 ) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001216 puts("Security:");
Rob Landleyadde7982006-05-16 15:32:30 +00001217 if (val[PSWD_CODE] && (val[PSWD_CODE] != NOVAL_1))
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001218 printf("\tMaster password revision code = %u\n", val[PSWD_CODE]);
Eric Andersen3443bd72003-07-22 07:30:36 +00001219 jj = val[SECU_STATUS];
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001220 if (jj) {
1221 for (ii = 0; ii < NUM_SECU_STR; ii++) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001222 printf("\t%s\t%s\n",
1223 (!(jj & 0x0001)) ? "not" : "",
1224 nth_string(secu_str, ii));
Eric Andersen3443bd72003-07-22 07:30:36 +00001225 jj >>=1;
1226 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001227 if (val[SECU_STATUS] & SECU_ENABLED) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001228 printf("\tSecurity level %s\n",
1229 (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high");
Eric Andersen3443bd72003-07-22 07:30:36 +00001230 }
1231 }
1232 jj = val[ERASE_TIME] & ERASE_BITS;
1233 kk = val[ENH_ERASE_TIME] & ERASE_BITS;
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001234 if (jj || kk) {
Denis Vlasenko7d60fc12008-06-05 06:51:06 +00001235 bb_putchar('\t');
Rob Landleyade7f952006-05-25 18:53:06 +00001236 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 ");
Denis Vlasenko4daad902007-09-27 10:20:47 +00001238 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001239 }
1240 }
1241
1242 /* reset result */
Rob Landleyadde7982006-05-16 15:32:30 +00001243 jj = val[HWRST_RSLT];
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001244 if ((jj & VALID) == VALID_VAL) {
Denis Vlasenko6bef3d12007-11-06 03:05:54 +00001245 oo = (jj & RST0);
1246 if (!oo)
Rob Landleyadde7982006-05-16 15:32:30 +00001247 jj >>= 8;
Rob Landleya3e4f382006-04-29 16:06:31 +00001248 if ((jj & DEV_DET) == JUMPER_VAL)
Rob Landleyadde7982006-05-16 15:32:30 +00001249 strng = " determined by the jumper";
Rob Landleya3e4f382006-04-29 16:06:31 +00001250 else if ((jj & DEV_DET) == CSEL_VAL)
Rob Landleyadde7982006-05-16 15:32:30 +00001251 strng = " determined by CSEL";
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00001252 else
Rob Landleyadde7982006-05-16 15:32:30 +00001253 strng = "";
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001254 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);
Eric Andersen3443bd72003-07-22 07:30:36 +00001259 }
1260
1261 /* more stuff from std 5 */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001262 if ((like_std > 4) && (eqpt != CDROM)) {
1263 if (val[CFA_PWR_MODE] & VALID_W160) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001264 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" : "");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001268 if (val[CFA_PWR_MODE] & MAX_AMPS)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001269 printf("\tMaximum current = %uma\n", val[CFA_PWR_MODE] & MAX_AMPS);
Eric Andersen3443bd72003-07-22 07:30:36 +00001270 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001271 if ((val[INTEGRITY] & SIG) == SIG_VAL) {
Rob Landleyadde7982006-05-16 15:32:30 +00001272 printf("Checksum: %scorrect\n", chksum ? "in" : "");
Eric Andersen3443bd72003-07-22 07:30:36 +00001273 }
1274 }
1275
Rob Landleyadde7982006-05-16 15:32:30 +00001276 exit(EXIT_SUCCESS);
Eric Andersen3443bd72003-07-22 07:30:36 +00001277}
1278#endif
1279
Eric Andersen3443bd72003-07-22 07:30:36 +00001280// 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
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001291#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
Denis Vlasenko91303402007-10-30 19:36:54 +00001292static const char cfg_str[] ALIGN1 =
Denis Vlasenko6b404432008-01-07 16:13:14 +00001293 """\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"
Denis Vlasenko91303402007-10-30 19:36:54 +00001297;
Eric Andersen3443bd72003-07-22 07:30:36 +00001298
Denis Vlasenko91303402007-10-30 19:36:54 +00001299static const char BuffType[] ALIGN1 =
1300 "unknown""\0" "1Sect""\0" "DualPort""\0" "DualPortCache"
1301;
Eric Andersen3443bd72003-07-22 07:30:36 +00001302
Denys Vlasenkoa7bb3c12009-10-08 12:28:08 +02001303static NOINLINE void dump_identity(const struct hd_driveid *id)
Eric Andersen3443bd72003-07-22 07:30:36 +00001304{
1305 int i;
Denis Vlasenko284d0fa2008-02-16 13:18:17 +00001306 const unsigned short *id_regs = (const void*) id;
Rob Landley0a7c8ef2006-02-22 17:01:00 +00001307
Glenn L McGrath07085852003-10-09 07:28:22 +00001308 printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n Config={",
1309 id->model, id->fw_rev, id->serial_no);
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001310 for (i = 0; i <= 15; i++) {
Rob Landleyade7f952006-05-25 18:53:06 +00001311 if (id->config & (1<<i))
Denis Vlasenkobfc3d822007-11-04 04:10:17 +00001312 printf(" %s", nth_string(cfg_str, i));
Rob Landleyadde7982006-05-16 15:32:30 +00001313 }
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001314 printf(" }\n RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n"
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001315 " 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);
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001321 if (id->max_multsect) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001322 printf(", MultSect=");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001323 if (!(id->multsect_valid & 1))
Eric Andersen3443bd72003-07-22 07:30:36 +00001324 printf("?%u?", id->multsect);
1325 else if (id->multsect)
1326 printf("%u", id->multsect);
1327 else
1328 printf("off");
1329 }
Denis Vlasenko4daad902007-09-27 10:20:47 +00001330 bb_putchar('\n');
Rob Landleyade7f952006-05-25 18:53:06 +00001331
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001332 if (!(id->field_valid & 1))
Rob Landleyade7f952006-05-25 18:53:06 +00001333 printf(" (maybe):");
1334
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001335 printf(" CurCHS=%u/%u/%u, CurSects=%lu, LBA=%s", id->cur_cyls, id->cur_heads,
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001336 id->cur_sectors,
1337 (BB_BIG_ENDIAN) ?
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001338 (unsigned long)(id->cur_capacity0 << 16) | id->cur_capacity1 :
1339 (unsigned long)(id->cur_capacity1 << 16) | id->cur_capacity0,
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001340 ((id->capability&2) == 0) ? "no" : "yes");
Rob Landleyade7f952006-05-25 18:53:06 +00001341
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001342 if (id->capability & 2)
Rob Landleyade7f952006-05-25 18:53:06 +00001343 printf(", LBAsects=%u", id->lba_capacity);
1344
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001345 printf("\n IORDY=%s",
1346 (id->capability & 8)
1347 ? ((id->capability & 4) ? "on/off" : "yes")
1348 : "no");
Rob Landleyade7f952006-05-25 18:53:06 +00001349
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001350 if (((id->capability & 8) || (id->field_valid & 2)) && (id->field_valid & 2))
Rob Landleyade7f952006-05-25 18:53:06 +00001351 printf(", tPIO={min:%u,w/IORDY:%u}", id->eide_pio, id->eide_pio_iordy);
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00001352
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001353 if ((id->capability & 1) && (id->field_valid & 2))
Rob Landleyade7f952006-05-25 18:53:06 +00001354 printf(", tDMA={min:%u,rec:%u}", id->eide_dma_min, id->eide_dma_time);
1355
1356 printf("\n PIO modes: ");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001357 if (id->tPIO <= 5) {
Rob Landleyade7f952006-05-25 18:53:06 +00001358 printf("pio0 ");
1359 if (id->tPIO >= 1) printf("pio1 ");
1360 if (id->tPIO >= 2) printf("pio2 ");
Eric Andersen3443bd72003-07-22 07:30:36 +00001361 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001362 if (id->field_valid & 2) {
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001363 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);
Rob Landleyade7f952006-05-25 18:53:06 +00001368 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001369 if (id->capability & 1) {
1370 if (id->dma_1word | id->dma_mword) {
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001371 static const int dma_wmode_masks[] = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 };
Rob Landleyade7f952006-05-25 18:53:06 +00001372 printf("\n DMA modes: ");
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001373 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,
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001377 "*\0""mdma0 \0""*\0""mdma1 \0""*\0""mdma2 \0""*\0""mdma? \0",
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001378 id->dma_mword, NULL);
Eric Andersen3443bd72003-07-22 07:30:36 +00001379 }
1380 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001381 if (((id->capability & 8) || (id->field_valid & 2)) && id->field_valid & 4) {
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001382 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 };
Denis Vlasenko7049ff82008-06-25 09:53:17 +00001386
Rob Landleyade7f952006-05-25 18:53:06 +00001387 printf("\n UDMA modes: ");
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001388 print_flags(&ultra_modes1, id->dma_ultra);
Eric Andersen3443bd72003-07-22 07:30:36 +00001389#ifdef __NEW_HD_DRIVE_ID
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001390 if (id->hw_config & 0x2000) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001391#else /* !__NEW_HD_DRIVE_ID */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001392 if (id->word93 & 0x2000) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001393#endif /* __NEW_HD_DRIVE_ID */
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001394 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);
Eric Andersen3443bd72003-07-22 07:30:36 +00001403 }
1404 }
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001405 printf("\n AdvancedPM=%s", (!(id_regs[83] & 8)) ? "no" : "yes");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001406 if (id_regs[83] & 8) {
1407 if (!(id_regs[86] & 8))
Glenn L McGrath07085852003-10-09 07:28:22 +00001408 printf(": disabled (255)");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001409 else if ((id_regs[91] & 0xFF00) != 0x4000)
Glenn L McGrath07085852003-10-09 07:28:22 +00001410 printf(": unknown setting");
1411 else
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001412 printf(": mode=0x%02X (%u)", id_regs[91] & 0xFF, id_regs[91] & 0xFF);
Glenn L McGrath07085852003-10-09 07:28:22 +00001413 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001414 if (id_regs[82] & 0x20)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001415 printf(" WriteCache=%s", (id_regs[85] & 0x20) ? "enabled" : "disabled");
Glenn L McGrath07085852003-10-09 07:28:22 +00001416#ifdef __NEW_HD_DRIVE_ID
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001417 if ((id->minor_rev_num && id->minor_rev_num <= 31)
1418 || (id->major_rev_num && id->minor_rev_num <= 31)
1419 ) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001420 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 ) {
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001425 for (i = 0; i <= 15; i++) {
Rob Landleyadde7982006-05-16 15:32:30 +00001426 if (id->major_rev_num & (1<<i))
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001427 printf(" ATA/ATAPI-%u", i);
Rob Landleyadde7982006-05-16 15:32:30 +00001428 }
Glenn L McGrath07085852003-10-09 07:28:22 +00001429 }
1430 }
Eric Andersen3443bd72003-07-22 07:30:36 +00001431#endif /* __NEW_HD_DRIVE_ID */
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001432 puts("\n\n * current active mode\n");
Eric Andersen3443bd72003-07-22 07:30:36 +00001433}
1434#endif
1435
Denis Vlasenko892536f2007-09-27 10:23:34 +00001436static void flush_buffer_cache(/*int fd*/ void)
Eric Andersen3443bd72003-07-22 07:30:36 +00001437{
Rob Landleya3e4f382006-04-29 16:06:31 +00001438 fsync(fd); /* flush buffers */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001439 ioctl_or_warn(fd, BLKFLSBUF, NULL); /* do it again, big time */
Eric Andersen3443bd72003-07-22 07:30:36 +00001440#ifdef HDIO_DRIVE_CMD
Glenn L McGrath07085852003-10-09 07:28:22 +00001441 sleep(1);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001442 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 }
Eric Andersen3443bd72003-07-22 07:30:36 +00001448#endif
1449}
1450
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001451static void seek_to_zero(/*int fd*/ void)
Eric Andersen3443bd72003-07-22 07:30:36 +00001452{
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001453 xlseek(fd, (off_t) 0, SEEK_SET);
Eric Andersen3443bd72003-07-22 07:30:36 +00001454}
1455
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001456static void read_big_block(/*int fd,*/ char *buf)
Eric Andersen3443bd72003-07-22 07:30:36 +00001457{
Rob Landleyadde7982006-05-16 15:32:30 +00001458 int i;
1459
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001460 xread(fd, buf, TIMING_BUF_BYTES);
Eric Andersen3443bd72003-07-22 07:30:36 +00001461 /* 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;
Eric Andersen3443bd72003-07-22 07:30:36 +00001464}
1465
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001466static unsigned dev_size_mb(/*int fd*/ void)
Rob Landleyadde7982006-05-16 15:32:30 +00001467{
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001468 union {
1469 unsigned long long blksize64;
1470 unsigned blksize32;
1471 } u;
Rob Landleyadde7982006-05-16 15:32:30 +00001472
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001473 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);
Rob Landleyadde7982006-05-16 15:32:30 +00001478 }
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001479 if (u.blksize64 > UINT_MAX)
1480 return UINT_MAX;
1481 return u.blksize64;
Rob Landleyadde7982006-05-16 15:32:30 +00001482}
Eric Andersen50af12d2003-08-06 08:47:59 +00001483
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001484static void print_timing(unsigned m, unsigned elapsed_us)
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001485{
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001486 unsigned sec = elapsed_us / 1000000;
1487 unsigned hs = (elapsed_us % 1000000) / 10000;
1488
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001489 printf("%5u MB in %u.%02u seconds = %u kB/s\n",
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001490 m, sec, hs,
Denis Vlasenko0afdfdf2007-09-28 13:41:41 +00001491 /* "| 1" prevents div-by-0 */
1492 (unsigned) ((unsigned long long)m * (1024 * 1000000) / (elapsed_us | 1))
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001493 // ~= (m * 1024) / (elapsed_us / 1000000)
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001494 // = kb / elapsed_sec
1495 );
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001496}
1497
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001498static 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 */
Eric Andersen3443bd72003-07-22 07:30:36 +00001502{
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001503 unsigned max_iterations, iterations;
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001504 unsigned start; /* doesn't need to be long long */
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001505 unsigned elapsed, elapsed2;
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001506 unsigned total_MB;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001507 char *buf = xmalloc(TIMING_BUF_BYTES);
Rob Landley4ae2f512006-05-19 17:24:26 +00001508
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001509 if (mlock(buf, TIMING_BUF_BYTES))
1510 bb_perror_msg_and_die("mlock");
Rob Landleyadde7982006-05-16 15:32:30 +00001511
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001512 /* 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. */
Rob Landleyadde7982006-05-16 15:32:30 +00001515 sync();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001516 sleep(1);
1517 if (cache) { /* Time cache */
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001518 seek_to_zero();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001519 read_big_block(buf);
1520 printf("Timing buffer-cache reads: ");
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001521 } else { /* Time device */
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001522 printf("Timing buffered disk reads:");
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001523 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +01001524 fflush_all();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001525
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001526 /* Now do the timing */
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001527 iterations = 0;
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001528 /* Max time to run (small for cache, avoids getting
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001529 * huge total_MB which can overlow unsigned type) */
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001530 elapsed2 = 510000; /* cache */
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001531 max_iterations = UINT_MAX;
1532 if (!cache) {
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001533 elapsed2 = 3000000; /* not cache */
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001534 /* Don't want to read past the end! */
1535 max_iterations = dev_size_mb() / TIMING_BUF_MB;
1536 }
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001537 start = monotonic_us();
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001538 do {
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001539 if (cache)
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001540 seek_to_zero();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001541 read_big_block(buf);
1542 elapsed = (unsigned)monotonic_us() - start;
1543 ++iterations;
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001544 } while (elapsed < elapsed2 && iterations < max_iterations);
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001545 total_MB = iterations * TIMING_BUF_MB;
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001546 //printf(" elapsed:%u iterations:%u ", elapsed, iterations);
1547 if (cache) {
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001548 /* Cache: remove lseek() and monotonic_us() overheads
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001549 * from elapsed */
1550 start = monotonic_us();
Rob Landleyadde7982006-05-16 15:32:30 +00001551 do {
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001552 seek_to_zero();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001553 elapsed2 = (unsigned)monotonic_us() - start;
Rob Landleyadde7982006-05-16 15:32:30 +00001554 } while (--iterations);
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001555 //printf(" elapsed2:%u ", elapsed2);
Rob Landleyadde7982006-05-16 15:32:30 +00001556 elapsed -= elapsed2;
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001557 total_MB *= 2; // BUFCACHE_FACTOR (why?)
Denis Vlasenko892536f2007-09-27 10:23:34 +00001558 flush_buffer_cache();
Glenn L McGrath07085852003-10-09 07:28:22 +00001559 }
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001560 print_timing(total_MB, elapsed);
Rob Landley4ae2f512006-05-19 17:24:26 +00001561 munlock(buf, TIMING_BUF_BYTES);
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001562 free(buf);
Eric Andersen3443bd72003-07-22 07:30:36 +00001563}
1564
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001565#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001566static void bus_state_value(unsigned value)
Eric Andersen3443bd72003-07-22 07:30:36 +00001567{
Rob Landleyadde7982006-05-16 15:32:30 +00001568 if (value == BUSSTATE_ON)
1569 on_off(1);
1570 else if (value == BUSSTATE_OFF)
1571 on_off(0);
1572 else if (value == BUSSTATE_TRISTATE)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001573 puts(" (tristate)");
Rob Landleyadde7982006-05-16 15:32:30 +00001574 else
Denys Vlasenko327f5502013-11-29 16:45:45 +01001575 printf(" (unknown: %u)\n", value);
Eric Andersen3443bd72003-07-22 07:30:36 +00001576}
1577#endif
1578
1579#ifdef HDIO_DRIVE_CMD
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001580static void interpret_standby(uint8_t standby)
Eric Andersen3443bd72003-07-22 07:30:36 +00001581{
Rob Landley403777f2006-08-03 20:22:37 +00001582 printf(" (");
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001583 if (standby == 0) {
Rob Landleyadde7982006-05-16 15:32:30 +00001584 printf("off");
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001585 } else if (standby <= 240 || standby == 252 || standby == 255) {
1586 /* standby is in 5 sec units */
Denys Vlasenko2b132e52009-05-20 23:21:42 +02001587 unsigned t = standby * 5;
1588 printf("%u minutes %u seconds", t / 60, t % 60);
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001589 } else if (standby <= 251) {
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001590 unsigned t = (standby - 240); /* t is in 30 min units */;
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001591 printf("%u.%c hours", t / 2, (t & 1) ? '5' : '0');
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001592 }
1593 if (standby == 253)
1594 printf("vendor-specific");
1595 if (standby == 254)
1596 printf("reserved");
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001597 puts(")");
Eric Andersen3443bd72003-07-22 07:30:36 +00001598}
1599
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001600static 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"
Eric Andersen3443bd72003-07-22 07:30:36 +00001612};
1613
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001614static int translate_xfermode(const char *name)
Eric Andersen3443bd72003-07-22 07:30:36 +00001615{
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00001616 int val;
1617 unsigned i;
Eric Andersen3443bd72003-07-22 07:30:36 +00001618
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001619 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];
Glenn L McGrath07085852003-10-09 07:28:22 +00001623 }
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001624 /* Negative numbers are invalid and are caught later */
1625 val = bb_strtoi(name, NULL, 10);
1626 if (!errno)
Glenn L McGrath07085852003-10-09 07:28:22 +00001627 return val;
Glenn L McGrath07085852003-10-09 07:28:22 +00001628 return -1;
Eric Andersen3443bd72003-07-22 07:30:36 +00001629}
1630
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001631static void interpret_xfermode(unsigned xfermode)
Eric Andersen3443bd72003-07-22 07:30:36 +00001632{
1633 printf(" (");
Rob Landleyadde7982006-05-16 15:32:30 +00001634 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)
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001639 printf("PIO flow control mode%u", xfermode - 8);
Rob Landleyadde7982006-05-16 15:32:30 +00001640 else if (xfermode >= 16 && xfermode <= 23)
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001641 printf("singleword DMA mode%u", xfermode - 16);
Rob Landleyadde7982006-05-16 15:32:30 +00001642 else if (xfermode >= 32 && xfermode <= 39)
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001643 printf("multiword DMA mode%u", xfermode - 32);
Rob Landleyadde7982006-05-16 15:32:30 +00001644 else if (xfermode >= 64 && xfermode <= 71)
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001645 printf("UltraDMA mode%u", xfermode - 64);
Rob Landleyadde7982006-05-16 15:32:30 +00001646 else
Denis Vlasenko91303402007-10-30 19:36:54 +00001647 printf("unknown");
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001648 puts(")");
Eric Andersen3443bd72003-07-22 07:30:36 +00001649}
1650#endif /* HDIO_DRIVE_CMD */
1651
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001652static void print_flag(int flag, const char *s, unsigned long value)
Rob Landleyadde7982006-05-16 15:32:30 +00001653{
Denis Vlasenko67b23e62006-10-03 21:00:06 +00001654 if (flag)
Denys Vlasenko327f5502013-11-29 16:45:45 +01001655 printf(" setting %s to %lu\n", s, value);
Rob Landleyadde7982006-05-16 15:32:30 +00001656}
1657
Rob Landleya3e4f382006-04-29 16:06:31 +00001658static void process_dev(char *devname)
Eric Andersen3443bd72003-07-22 07:30:36 +00001659{
Denis Vlasenko892536f2007-09-27 10:23:34 +00001660 /*int fd;*/
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001661 long parm, multcount;
Eric Andersen3443bd72003-07-22 07:30:36 +00001662#ifndef HDIO_DRIVE_CMD
1663 int force_operation = 0;
1664#endif
Rob Landley39cf6452006-05-05 16:52:28 +00001665 /* Please restore args[n] to these values after each ioctl
1666 except for args[2] */
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001667 unsigned char args[4] = { WIN_SETFEATURES, 0, 0, 0 };
Rob Landleyadde7982006-05-16 15:32:30 +00001668 const char *fmt = " %s\t= %2ld";
Rob Landleye5b281f2006-04-29 15:49:18 +00001669
Bernhard Reutner-Fischera4830872009-10-26 23:27:08 +01001670 /*fd = xopen_nonblocking(devname);*/
1671 xmove_fd(xopen_nonblocking(devname), fd);
Rob Landleyade7f952006-05-25 18:53:06 +00001672 printf("\n%s:\n", devname);
Eric Andersen3443bd72003-07-22 07:30:36 +00001673
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001674 if (getset_readahead == IS_SET) {
1675 print_flag(getset_readahead, "fs readahead", Xreadahead);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001676 ioctl_or_warn(fd, BLKRASET, (int *)Xreadahead);
Eric Andersen3443bd72003-07-22 07:30:36 +00001677 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001678#if ENABLE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
1679 if (unregister_hwif) {
Rob Landley20deab02006-05-07 23:34:15 +00001680 printf(" attempting to unregister hwif#%lu\n", hwif);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001681 ioctl_or_warn(fd, HDIO_UNREGISTER_HWIF, (int *)(unsigned long)hwif);
Eric Andersen3443bd72003-07-22 07:30:36 +00001682 }
1683#endif
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001684#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001685 if (scan_hwif == IS_SET) {
Rob Landley20deab02006-05-07 23:34:15 +00001686 printf(" attempting to scan hwif (0x%lx, 0x%lx, %lu)\n", hwif_data, hwif_ctrl, hwif_irq);
Eric Andersen3443bd72003-07-22 07:30:36 +00001687 args[0] = hwif_data;
1688 args[1] = hwif_ctrl;
1689 args[2] = hwif_irq;
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001690 ioctl_or_warn(fd, HDIO_SCAN_HWIF, args);
Rob Landley39cf6452006-05-05 16:52:28 +00001691 args[0] = WIN_SETFEATURES;
1692 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001693 }
1694#endif
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001695 if (set_piomode) {
1696 if (noisy_piomode) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001697 printf(" attempting to ");
Eric Andersen3443bd72003-07-22 07:30:36 +00001698 if (piomode == 255)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001699 puts("auto-tune PIO mode");
Eric Andersen3443bd72003-07-22 07:30:36 +00001700 else if (piomode < 100)
Glenn L McGrath07085852003-10-09 07:28:22 +00001701 printf("set PIO mode to %d\n", piomode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001702 else if (piomode < 200)
Glenn L McGrath07085852003-10-09 07:28:22 +00001703 printf("set MDMA mode to %d\n", (piomode-100));
Eric Andersen3443bd72003-07-22 07:30:36 +00001704 else
Glenn L McGrath07085852003-10-09 07:28:22 +00001705 printf("set UDMA mode to %d\n", (piomode-200));
Eric Andersen3443bd72003-07-22 07:30:36 +00001706 }
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001707 ioctl_or_warn(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001708 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001709 if (getset_io32bit == IS_SET) {
1710 print_flag(getset_io32bit, "32-bit IO_support flag", io32bit);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001711 ioctl_or_warn(fd, HDIO_SET_32BIT, (int *)io32bit);
Eric Andersen3443bd72003-07-22 07:30:36 +00001712 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001713 if (getset_mult == IS_SET) {
1714 print_flag(getset_mult, "multcount", mult);
Rob Landleyade7f952006-05-25 18:53:06 +00001715#ifdef HDIO_DRIVE_CMD
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001716 ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult);
Rob Landleyade7f952006-05-25 18:53:06 +00001717#else
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001718 force_operation |= (!ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult));
Eric Andersen3443bd72003-07-22 07:30:36 +00001719#endif
1720 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001721 if (getset_readonly == IS_SET) {
1722 print_flag_on_off(getset_readonly, "readonly", readonly);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001723 ioctl_or_warn(fd, BLKROSET, &readonly);
Eric Andersen3443bd72003-07-22 07:30:36 +00001724 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001725 if (getset_unmask == IS_SET) {
1726 print_flag_on_off(getset_unmask, "unmaskirq", unmask);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001727 ioctl_or_warn(fd, HDIO_SET_UNMASKINTR, (int *)unmask);
Eric Andersen3443bd72003-07-22 07:30:36 +00001728 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001729#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001730 if (getset_dma == IS_SET) {
1731 print_flag_on_off(getset_dma, "using_dma", dma);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001732 ioctl_or_warn(fd, HDIO_SET_DMA, (int *)dma);
Eric Andersen3443bd72003-07-22 07:30:36 +00001733 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001734#endif /* FEATURE_HDPARM_HDIO_GETSET_DMA */
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001735#ifdef HDIO_SET_QDMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001736 if (getset_dma_q == IS_SET) {
1737 print_flag_on_off(getset_dma_q, "DMA queue_depth", dma_q);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001738 ioctl_or_warn(fd, HDIO_SET_QDMA, (int *)dma_q);
Eric Andersen3443bd72003-07-22 07:30:36 +00001739 }
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001740#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001741 if (getset_nowerr == IS_SET) {
1742 print_flag_on_off(getset_nowerr, "nowerr", nowerr);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001743 ioctl_or_warn(fd, HDIO_SET_NOWERR, (int *)nowerr);
Eric Andersen3443bd72003-07-22 07:30:36 +00001744 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001745 if (getset_keep == IS_SET) {
1746 print_flag_on_off(getset_keep, "keep_settings", keep);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001747 ioctl_or_warn(fd, HDIO_SET_KEEPSETTINGS, (int *)keep);
Eric Andersen3443bd72003-07-22 07:30:36 +00001748 }
1749#ifdef HDIO_DRIVE_CMD
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001750 if (getset_doorlock == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001751 args[0] = doorlock ? WIN_DOORLOCK : WIN_DOORUNLOCK;
Rob Landley39cf6452006-05-05 16:52:28 +00001752 args[2] = 0;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001753 print_flag_on_off(getset_doorlock, "drive doorlock", doorlock);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001754 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001755 args[0] = WIN_SETFEATURES;
Eric Andersen3443bd72003-07-22 07:30:36 +00001756 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001757 if (getset_dkeep == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001758 /* lock/unlock the drive's "feature" settings */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001759 print_flag_on_off(getset_dkeep, "drive keep features", dkeep);
Eric Andersen3443bd72003-07-22 07:30:36 +00001760 args[2] = dkeep ? 0x66 : 0xcc;
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001761 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001762 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001763 if (getset_defects == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001764 args[2] = defects ? 0x04 : 0x84;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001765 print_flag(getset_defects, "drive defect-mgmt", defects);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001766 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001767 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001768 if (getset_prefetch == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001769 args[1] = prefetch;
Rob Landleye5b281f2006-04-29 15:49:18 +00001770 args[2] = 0xab;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001771 print_flag(getset_prefetch, "drive prefetch", prefetch);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001772 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001773 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001774 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001775 if (set_xfermode) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001776 args[1] = xfermode_requested;
Rob Landleye5b281f2006-04-29 15:49:18 +00001777 args[2] = 3;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001778 print_flag(1, "xfermode", xfermode_requested);
1779 interpret_xfermode(xfermode_requested);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001780 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001781 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001782 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001783 if (getset_lookahead == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001784 args[2] = lookahead ? 0xaa : 0x55;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001785 print_flag_on_off(getset_lookahead, "drive read-lookahead", lookahead);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001786 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001787 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001788 if (getset_apmmode == IS_SET) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001789 /* feature register */
1790 args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */;
Rob Landleyadde7982006-05-16 15:32:30 +00001791 args[1] = apmmode; /* sector count register 1-255 */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001792 printf(" setting APM level to %s 0x%02lX (%ld)\n",
1793 (apmmode == 255) ? "disabled" : "",
1794 apmmode, apmmode);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001795 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001796 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001797 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001798 if (getset_wcache == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001799#ifdef DO_FLUSHCACHE
1800#ifndef WIN_FLUSHCACHE
1801#define WIN_FLUSHCACHE 0xe7
1802#endif
Eric Andersen3443bd72003-07-22 07:30:36 +00001803#endif /* DO_FLUSHCACHE */
Eric Andersen3443bd72003-07-22 07:30:36 +00001804 args[2] = wcache ? 0x02 : 0x82;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001805 print_flag_on_off(getset_wcache, "drive write-caching", wcache);
Eric Andersen3443bd72003-07-22 07:30:36 +00001806#ifdef DO_FLUSHCACHE
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001807 if (!wcache)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001808 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache);
Eric Andersen3443bd72003-07-22 07:30:36 +00001809#endif /* DO_FLUSHCACHE */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001810 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001811#ifdef DO_FLUSHCACHE
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001812 if (!wcache)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001813 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache);
Eric Andersen3443bd72003-07-22 07:30:36 +00001814#endif /* DO_FLUSHCACHE */
1815 }
Rob Landley39cf6452006-05-05 16:52:28 +00001816
1817 /* In code below, we do not preserve args[0], but the rest
1818 is preserved, including args[2] */
1819 args[2] = 0;
1820
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001821 if (set_standbynow) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001822#ifndef WIN_STANDBYNOW1
1823#define WIN_STANDBYNOW1 0xE0
1824#endif
1825#ifndef WIN_STANDBYNOW2
1826#define WIN_STANDBYNOW2 0x94
1827#endif
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001828 puts(" issuing standby command");
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001829 args[0] = WIN_STANDBYNOW1;
Denis Vlasenko892536f2007-09-27 10:23:34 +00001830 ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2);
Eric Andersen3443bd72003-07-22 07:30:36 +00001831 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001832 if (set_sleepnow) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001833#ifndef WIN_SLEEPNOW1
1834#define WIN_SLEEPNOW1 0xE6
1835#endif
1836#ifndef WIN_SLEEPNOW2
1837#define WIN_SLEEPNOW2 0x99
1838#endif
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001839 puts(" issuing sleep command");
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001840 args[0] = WIN_SLEEPNOW1;
Denis Vlasenko892536f2007-09-27 10:23:34 +00001841 ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2);
Eric Andersen3443bd72003-07-22 07:30:36 +00001842 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001843 if (set_seagate) {
Rob Landleye5b281f2006-04-29 15:49:18 +00001844 args[0] = 0xfb;
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001845 puts(" disabling Seagate auto powersaving mode");
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001846 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001847 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001848 if (getset_standby == IS_SET) {
Rob Landleye5b281f2006-04-29 15:49:18 +00001849 args[0] = WIN_SETIDLE1;
1850 args[1] = standby_requested;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001851 print_flag(1, "standby", standby_requested);
1852 interpret_standby(standby_requested);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001853 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001854 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001855 }
1856#else /* HDIO_DRIVE_CMD */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001857 if (force_operation) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001858 char buf[512];
Denis Vlasenko892536f2007-09-27 10:23:34 +00001859 flush_buffer_cache();
Eric Andersen3443bd72003-07-22 07:30:36 +00001860 if (-1 == read(fd, buf, sizeof(buf)))
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001861 bb_perror_msg("read of 512 bytes failed");
Eric Andersen3443bd72003-07-22 07:30:36 +00001862 }
Denys Vlasenkoe4dcba12010-10-28 18:57:19 +02001863#endif /* HDIO_DRIVE_CMD */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001864 if (getset_mult || get_identity) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001865 multcount = -1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001866 if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001867 /* To be coherent with ioctl_or_warn. */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001868 if (getset_mult && ENABLE_IOCTL_HEX2STR_ERROR)
Eric Andersen06d4ec22004-03-19 10:53:52 +00001869 bb_perror_msg("HDIO_GET_MULTCOUNT");
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001870 else
1871 bb_perror_msg("ioctl %#x failed", HDIO_GET_MULTCOUNT);
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001872 } else if (getset_mult) {
Rob Landleyadde7982006-05-16 15:32:30 +00001873 printf(fmt, "multcount", multcount);
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001874 on_off(multcount != 0);
Eric Andersen3443bd72003-07-22 07:30:36 +00001875 }
1876 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001877 if (getset_io32bit) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001878 if (!ioctl_or_warn(fd, HDIO_GET_32BIT, &parm)) {
Rob Landleyadde7982006-05-16 15:32:30 +00001879 printf(" IO_support\t=%3ld (", parm);
1880 if (parm == 0)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001881 puts("default 16-bit)");
Rob Landleyadde7982006-05-16 15:32:30 +00001882 else if (parm == 2)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001883 puts("16-bit)");
Rob Landleyadde7982006-05-16 15:32:30 +00001884 else if (parm == 1)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001885 puts("32-bit)");
Rob Landleyadde7982006-05-16 15:32:30 +00001886 else if (parm == 3)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001887 puts("32-bit w/sync)");
Rob Landleyadde7982006-05-16 15:32:30 +00001888 else if (parm == 8)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001889 puts("Request-Queue-Bypass)");
Rob Landleyadde7982006-05-16 15:32:30 +00001890 else
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001891 puts("\?\?\?)");
Eric Andersen3443bd72003-07-22 07:30:36 +00001892 }
1893 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001894 if (getset_unmask) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001895 if (!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001896 print_value_on_off("unmaskirq", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001897 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001898#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001899 if (getset_dma) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001900 if (!ioctl_or_warn(fd, HDIO_GET_DMA, &parm)) {
Rob Landleyadde7982006-05-16 15:32:30 +00001901 printf(fmt, "using_dma", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001902 if (parm == 8)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001903 puts(" (DMA-Assisted-PIO)");
Eric Andersen3443bd72003-07-22 07:30:36 +00001904 else
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001905 on_off(parm != 0);
Eric Andersen3443bd72003-07-22 07:30:36 +00001906 }
1907 }
1908#endif
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001909#ifdef HDIO_GET_QDMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001910 if (getset_dma_q) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001911 if (!ioctl_or_warn(fd, HDIO_GET_QDMA, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001912 print_value_on_off("queue_depth", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001913 }
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001914#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001915 if (getset_keep) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001916 if (!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001917 print_value_on_off("keepsettings", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001918 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001919 if (getset_nowerr) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001920 if (!ioctl_or_warn(fd, HDIO_GET_NOWERR, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001921 print_value_on_off("nowerr", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001922 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001923 if (getset_readonly) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001924 if (!ioctl_or_warn(fd, BLKROGET, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001925 print_value_on_off("readonly", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001926 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001927 if (getset_readahead) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001928 if (!ioctl_or_warn(fd, BLKRAGET, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001929 print_value_on_off("readahead", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001930 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001931 if (get_geom) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001932 if (!ioctl_or_warn(fd, BLKGETSIZE, &parm)) {
Rob Landley2584e9b2006-05-03 20:00:00 +00001933 struct hd_geometry g;
1934
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001935 if (!ioctl_or_warn(fd, HDIO_GETGEO, &g))
Rob Landleyadde7982006-05-16 15:32:30 +00001936 printf(" geometry\t= %u/%u/%u, sectors = %ld, start = %ld\n",
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001937 g.cylinders, g.heads, g.sectors, parm, g.start);
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001938 }
Eric Andersen3443bd72003-07-22 07:30:36 +00001939 }
1940#ifdef HDIO_DRIVE_CMD
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001941 if (get_powermode) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001942#ifndef WIN_CHECKPOWERMODE1
1943#define WIN_CHECKPOWERMODE1 0xE5
1944#endif
1945#ifndef WIN_CHECKPOWERMODE2
1946#define WIN_CHECKPOWERMODE2 0x98
1947#endif
Eric Andersen3443bd72003-07-22 07:30:36 +00001948 const char *state;
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001949
Rob Landleye5b281f2006-04-29 15:49:18 +00001950 args[0] = WIN_CHECKPOWERMODE1;
Denis Vlasenko892536f2007-09-27 10:23:34 +00001951 if (ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2)) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001952 if (errno != EIO || args[0] != 0 || args[1] != 0)
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001953 state = "unknown";
Eric Andersen3443bd72003-07-22 07:30:36 +00001954 else
1955 state = "sleeping";
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001956 } else
Glenn L McGrath07085852003-10-09 07:28:22 +00001957 state = (args[2] == 255) ? "active/idle" : "standby";
Rob Landley39cf6452006-05-05 16:52:28 +00001958 args[1] = args[2] = 0;
Glenn L McGrath07085852003-10-09 07:28:22 +00001959
Eric Andersen3443bd72003-07-22 07:30:36 +00001960 printf(" drive state is: %s\n", state);
1961 }
1962#endif
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001963#if ENABLE_FEATURE_HDPARM_HDIO_DRIVE_RESET
1964 if (perform_reset) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001965 ioctl_or_warn(fd, HDIO_DRIVE_RESET, NULL);
Eric Andersen3443bd72003-07-22 07:30:36 +00001966 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001967#endif /* FEATURE_HDPARM_HDIO_DRIVE_RESET */
1968#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
1969 if (perform_tristate) {
Rob Landleye5b281f2006-04-29 15:49:18 +00001970 args[0] = 0;
1971 args[1] = tristate;
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001972 ioctl_or_warn(fd, HDIO_TRISTATE_HWIF, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001973 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001974#endif /* FEATURE_HDPARM_HDIO_TRISTATE_HWIF */
1975#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
1976 if (get_identity) {
Denis Vlasenko7c282a22007-03-28 00:14:54 +00001977 struct hd_driveid id;
Eric Andersen3443bd72003-07-22 07:30:36 +00001978
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001979 if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) {
1980 if (multcount != -1) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001981 id.multsect = multcount;
1982 id.multsect_valid |= 1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001983 } else
Eric Andersen3443bd72003-07-22 07:30:36 +00001984 id.multsect_valid &= ~1;
1985 dump_identity(&id);
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001986 } else if (errno == -ENOMSG)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001987 puts(" no identification info available");
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001988 else if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */
Denis Vlasenko49a128a2007-07-17 21:42:59 +00001989 bb_perror_msg("HDIO_GET_IDENTITY");
Eric Andersen3443bd72003-07-22 07:30:36 +00001990 else
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001991 bb_perror_msg("ioctl %#x failed", HDIO_GET_IDENTITY);
Eric Andersen3443bd72003-07-22 07:30:36 +00001992 }
Glenn L McGrath07085852003-10-09 07:28:22 +00001993
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001994 if (get_IDentity) {
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001995 unsigned char args1[4+512]; /* = { ... } will eat 0.5k of rodata! */
Glenn L McGrath07085852003-10-09 07:28:22 +00001996
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001997 memset(args1, 0, sizeof(args1));
1998 args1[0] = WIN_IDENTIFY;
1999 args1[3] = 1;
Denis Vlasenko892536f2007-09-27 10:23:34 +00002000 if (!ioctl_alt_or_warn(HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY))
Rob Landley0753f4a2006-06-07 00:27:25 +00002001 identify((void *)(args1 + 4));
Eric Andersen3443bd72003-07-22 07:30:36 +00002002 }
2003#endif
Denis Vlasenko3bf00202007-02-18 13:36:04 +00002004#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002005 if (getset_busstate == IS_SET) {
2006 print_flag(1, "bus state", busstate);
2007 bus_state_value(busstate);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00002008 ioctl_or_warn(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate);
Eric Andersen3443bd72003-07-22 07:30:36 +00002009 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002010 if (getset_busstate) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00002011 if (!ioctl_or_warn(fd, HDIO_GET_BUSSTATE, &parm)) {
Rob Landleyadde7982006-05-16 15:32:30 +00002012 printf(fmt, "bus state", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00002013 bus_state_value(parm);
2014 }
2015 }
2016#endif
Glenn L McGrath07085852003-10-09 07:28:22 +00002017 if (reread_partn)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00002018 ioctl_or_warn(fd, BLKRRPART, NULL);
Glenn L McGrath07085852003-10-09 07:28:22 +00002019
Eric Andersen3443bd72003-07-22 07:30:36 +00002020 if (do_ctimings)
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00002021 do_time(1 /*,fd*/); /* time cache */
Eric Andersen3443bd72003-07-22 07:30:36 +00002022 if (do_timings)
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00002023 do_time(0 /*,fd*/); /* time device */
Eric Andersen3443bd72003-07-22 07:30:36 +00002024 if (do_flush)
Denis Vlasenko892536f2007-09-27 10:23:34 +00002025 flush_buffer_cache();
Rob Landleya3e4f382006-04-29 16:06:31 +00002026 close(fd);
Eric Andersen3443bd72003-07-22 07:30:36 +00002027}
2028
Denis Vlasenko3bf00202007-02-18 13:36:04 +00002029#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
Rob Landleya3e4f382006-04-29 16:06:31 +00002030static int fromhex(unsigned char c)
Eric Andersen3443bd72003-07-22 07:30:36 +00002031{
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +00002032 if (isdigit(c))
Eric Andersen3443bd72003-07-22 07:30:36 +00002033 return (c - '0');
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +00002034 if (c >= 'a' && c <= 'f')
2035 return (c - ('a' - 10));
Eric Andersen3443bd72003-07-22 07:30:36 +00002036 bb_error_msg_and_die("bad char: '%c' 0x%02x", c, c);
2037}
2038
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00002039static void identify_from_stdin(void) NORETURN;
Rob Landley0f0b6452006-05-03 18:28:06 +00002040static void identify_from_stdin(void)
Eric Andersen3443bd72003-07-22 07:30:36 +00002041{
Rob Landley0753f4a2006-06-07 00:27:25 +00002042 uint16_t sbuf[256];
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +00002043 unsigned char buf[1280];
2044 unsigned char *b = (unsigned char *)buf;
2045 int i;
Eric Andersen3443bd72003-07-22 07:30:36 +00002046
Bernhard Reutner-Fischer5e25ddb2008-05-19 09:48:17 +00002047 xread(STDIN_FILENO, buf, 1280);
Rob Landleyade7f952006-05-25 18:53:06 +00002048
Rob Landley0753f4a2006-06-07 00:27:25 +00002049 // Convert the newline-separated hex data into an identify block.
2050
Denis Vlasenko3bf00202007-02-18 13:36:04 +00002051 for (i = 0; i < 256; i++) {
Rob Landley0753f4a2006-06-07 00:27:25 +00002052 int j;
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00002053 for (j = 0; j < 4; j++)
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +00002054 sbuf[i] = (sbuf[i] << 4) + fromhex(*(b++));
Eric Andersen3443bd72003-07-22 07:30:36 +00002055 }
Rob Landley0753f4a2006-06-07 00:27:25 +00002056
2057 // Parse the data.
2058
Rob Landley6389ff12006-05-01 19:28:53 +00002059 identify(sbuf);
Eric Andersen3443bd72003-07-22 07:30:36 +00002060}
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00002061#else
2062void identify_from_stdin(void);
Eric Andersen3443bd72003-07-22 07:30:36 +00002063#endif
2064
Rob Landley20deab02006-05-07 23:34:15 +00002065/* busybox specific stuff */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002066static int parse_opts(unsigned long *value, int min, int max)
Eric Andersenb2aa7762004-04-05 13:08:08 +00002067{
Denis Vlasenko6429aab2006-09-23 12:22:11 +00002068 if (optarg) {
Denis Vlasenko13858992006-10-08 12:49:22 +00002069 *value = xatol_range(optarg, min, max);
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002070 return IS_SET;
Denis Vlasenko6429aab2006-09-23 12:22:11 +00002071 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002072 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);
Rob Landley20deab02006-05-07 23:34:15 +00002085}
2086
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00002087static void parse_xfermode(int flag, smallint *get, smallint *set, int *value)
Rob Landley20deab02006-05-07 23:34:15 +00002088{
2089 if (flag) {
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002090 *get = IS_GET;
Rob Landley20deab02006-05-07 23:34:15 +00002091 if (optarg) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00002092 *value = translate_xfermode(optarg);
2093 *set = (*value > -1);
Rob Landley20deab02006-05-07 23:34:15 +00002094 }
2095 }
2096}
2097
Rob Landley06208412006-05-31 22:52:57 +00002098/*------- getopt short options --------*/
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002099static const char hdparm_options[] ALIGN1 =
Denis Vlasenko4daad902007-09-27 10:20:47 +00002100 "gfu::n::p:r::m::c::k::a::B:tT"
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002101 IF_FEATURE_HDPARM_GET_IDENTITY("iI")
2102 IF_FEATURE_HDPARM_HDIO_GETSET_DMA("d::")
Rob Landley20deab02006-05-07 23:34:15 +00002103#ifdef HDIO_DRIVE_CMD
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002104 "S:D:P:X:K:A:L:W:CyYzZ"
Rob Landley20deab02006-05-07 23:34:15 +00002105#endif
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002106 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("U:")
Rob Landley20deab02006-05-07 23:34:15 +00002107#ifdef HDIO_GET_QDMA
2108#ifdef HDIO_SET_QDMA
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002109 "Q:"
Rob Landley20deab02006-05-07 23:34:15 +00002110#else
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002111 "Q"
Rob Landley20deab02006-05-07 23:34:15 +00002112#endif
2113#endif
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002114 IF_FEATURE_HDPARM_HDIO_DRIVE_RESET("w")
2115 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF("x::b:")
2116 IF_FEATURE_HDPARM_HDIO_SCAN_HWIF("R:");
Rob Landley20deab02006-05-07 23:34:15 +00002117/*-------------------------------------*/
2118
2119/* our main() routine: */
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00002120int hdparm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Rob Landley20deab02006-05-07 23:34:15 +00002121int hdparm_main(int argc, char **argv)
2122{
2123 int c;
Rob Landleyade7f952006-05-25 18:53:06 +00002124 int flagcount = 0;
Rob Landley20deab02006-05-07 23:34:15 +00002125
Denys Vlasenko16714242011-09-21 01:59:15 +02002126 INIT_G();
2127
Rob Landley06208412006-05-31 22:52:57 +00002128 while ((c = getopt(argc, argv, hdparm_options)) >= 0) {
Rob Landley20deab02006-05-07 23:34:15 +00002129 flagcount++;
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002130 IF_FEATURE_HDPARM_GET_IDENTITY(get_IDentity |= (c == 'I'));
2131 IF_FEATURE_HDPARM_GET_IDENTITY(get_identity |= (c == 'i'));
Rob Landleyadde7982006-05-16 15:32:30 +00002132 get_geom |= (c == 'g');
2133 do_flush |= (c == 'f');
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002134 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);
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00002139 parse_xfermode((c == 'p'), &noisy_piomode, &set_piomode, &piomode);
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002140 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);
Rob Landleyadde7982006-05-16 15:32:30 +00002146 do_flush |= do_timings |= (c == 't');
2147 do_flush |= do_ctimings |= (c == 'T');
Rob Landley20deab02006-05-07 23:34:15 +00002148#ifdef HDIO_DRIVE_CMD
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002149 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);
Rob Landleyade7f952006-05-25 18:53:06 +00002152 parse_xfermode((c == 'X'), &get_xfermode, &set_xfermode, &xfermode_requested);
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002153 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);
Rob Landleyade7f952006-05-25 18:53:06 +00002157 get_powermode |= (c == 'C');
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002158 set_standbynow |= (c == 'y');
2159 set_sleepnow |= (c == 'Y');
Rob Landleyadde7982006-05-16 15:32:30 +00002160 reread_partn |= (c == 'z');
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002161 set_seagate |= (c == 'Z');
Rob Landley20deab02006-05-07 23:34:15 +00002162#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002163 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') unregister_hwif = parse_opts_0_INTMAX(&hwif));
Rob Landley20deab02006-05-07 23:34:15 +00002164#ifdef HDIO_GET_QDMA
Rob Landley19802562006-05-08 15:35:46 +00002165 if (c == 'Q') {
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002166 getset_dma_q = parse_opts_0_INTMAX(&dma_q);
Rob Landley19802562006-05-08 15:35:46 +00002167 }
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00002168#endif
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002169 IF_FEATURE_HDPARM_HDIO_DRIVE_RESET(perform_reset = (c == 'r'));
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002170 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));
Rob Landley20deab02006-05-07 23:34:15 +00002172#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
2173 if (c == 'R') {
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002174 scan_hwif = parse_opts_0_INTMAX(&hwif_data);
Denys Vlasenko77832482010-08-12 14:14:45 +02002175 hwif_ctrl = xatoi_positive((argv[optind]) ? argv[optind] : "");
2176 hwif_irq = xatoi_positive((argv[optind+1]) ? argv[optind+1] : "");
Rob Landley20deab02006-05-07 23:34:15 +00002177 /* Move past the 2 additional arguments */
2178 argv += 2;
2179 argc -= 2;
2180 }
2181#endif
2182 }
Rob Landleyade7f952006-05-25 18:53:06 +00002183 /* When no flags are given (flagcount = 0), -acdgkmnru is assumed. */
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002184 if (!flagcount) {
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002185 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);
Rob Landleyade7f952006-05-25 18:53:06 +00002187 }
Rob Landley20deab02006-05-07 23:34:15 +00002188 argv += optind;
2189
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00002190 if (!*argv) {
Rob Landley6d8ce172006-06-07 21:22:42 +00002191 if (ENABLE_FEATURE_HDPARM_GET_IDENTITY && !isatty(STDIN_FILENO))
2192 identify_from_stdin(); /* EXIT */
Denis Vlasenko4daad902007-09-27 10:20:47 +00002193 bb_show_usage();
Rob Landley20deab02006-05-07 23:34:15 +00002194 }
2195
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00002196 do {
2197 process_dev(*argv++);
2198 } while (*argv);
2199
2200 return EXIT_SUCCESS;
Eric Andersen3443bd72003-07-22 07:30:36 +00002201}