blob: 8e201ac358573372ddc47ebe49a5cd92274a23b1 [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 */
Pere Orga5bc8c002011-04-11 03:29:49 +020014
15//usage:#define hdparm_trivial_usage
16//usage: "[OPTIONS] [DEVICE]"
17//usage:#define hdparm_full_usage "\n\n"
Denys Vlasenko66426762011-06-05 03:58:28 +020018//usage: " -a Get/set fs readahead"
Pere Orga5bc8c002011-04-11 03:29:49 +020019//usage: "\n -A Set drive read-lookahead flag (0/1)"
20//usage: "\n -b Get/set bus state (0 == off, 1 == on, 2 == tristate)"
21//usage: "\n -B Set Advanced Power Management setting (1-255)"
22//usage: "\n -c Get/set IDE 32-bit IO setting"
23//usage: "\n -C Check IDE power mode status"
24//usage: IF_FEATURE_HDPARM_HDIO_GETSET_DMA(
25//usage: "\n -d Get/set using_dma flag")
26//usage: "\n -D Enable/disable drive defect-mgmt"
27//usage: "\n -f Flush buffer cache for device on exit"
28//usage: "\n -g Display drive geometry"
29//usage: "\n -h Display terse usage information"
30//usage: IF_FEATURE_HDPARM_GET_IDENTITY(
31//usage: "\n -i Display drive identification")
32//usage: IF_FEATURE_HDPARM_GET_IDENTITY(
33//usage: "\n -I Detailed/current information directly from drive")
34//usage: "\n -k Get/set keep_settings_over_reset flag (0/1)"
35//usage: "\n -K Set drive keep_features_over_reset flag (0/1)"
36//usage: "\n -L Set drive doorlock (0/1) (removable harddisks only)"
37//usage: "\n -m Get/set multiple sector count"
38//usage: "\n -n Get/set ignore-write-errors flag (0/1)"
39//usage: "\n -p Set PIO mode on IDE interface chipset (0,1,2,3,4,...)"
40//usage: "\n -P Set drive prefetch count"
41/* //usage: "\n -q Change next setting quietly" - not supported ib bbox */
42//usage: "\n -Q Get/set DMA tagged-queuing depth (if supported)"
43//usage: "\n -r Get/set readonly flag (DANGEROUS to set)"
44//usage: IF_FEATURE_HDPARM_HDIO_SCAN_HWIF(
45//usage: "\n -R Register an IDE interface (DANGEROUS)")
46//usage: "\n -S Set standby (spindown) timeout"
47//usage: "\n -t Perform device read timings"
48//usage: "\n -T Perform cache read timings"
49//usage: "\n -u Get/set unmaskirq flag (0/1)"
50//usage: IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(
51//usage: "\n -U Unregister an IDE interface (DANGEROUS)")
52//usage: "\n -v Defaults; same as -mcudkrag for IDE drives"
53//usage: "\n -V Display program version and exit immediately"
54//usage: IF_FEATURE_HDPARM_HDIO_DRIVE_RESET(
55//usage: "\n -w Perform device reset (DANGEROUS)")
56//usage: "\n -W Set drive write-caching flag (0/1) (DANGEROUS)"
57//usage: IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(
58//usage: "\n -x Tristate device for hotswap (0/1) (DANGEROUS)")
59//usage: "\n -X Set IDE xfer mode (DANGEROUS)"
60//usage: "\n -y Put IDE drive in standby mode"
61//usage: "\n -Y Put IDE drive to sleep"
62//usage: "\n -Z Disable Seagate auto-powersaving mode"
63//usage: "\n -z Reread partition table"
64
Denys Vlasenko860d2bb2009-07-10 18:37:06 +020065#include "libbb.h"
66/* must be _after_ libbb.h: */
Eric Andersen3443bd72003-07-22 07:30:36 +000067#include <linux/hdreg.h>
Denys Vlasenkoda49f582009-07-08 02:58:38 +020068#include <sys/mount.h>
Denys Vlasenkoaf3fd142009-09-22 23:16:39 +020069#if !defined(BLKGETSIZE64)
70# define BLKGETSIZE64 _IOR(0x12,114,size_t)
71#endif
Eric Andersen3443bd72003-07-22 07:30:36 +000072
Eric Andersen3443bd72003-07-22 07:30:36 +000073/* device types */
74/* ------------ */
75#define NO_DEV 0xffff
76#define ATA_DEV 0x0000
77#define ATAPI_DEV 0x0001
78
79/* word definitions */
80/* ---------------- */
81#define GEN_CONFIG 0 /* general configuration */
82#define LCYLS 1 /* number of logical cylinders */
83#define CONFIG 2 /* specific configuration */
84#define LHEADS 3 /* number of logical heads */
85#define TRACK_BYTES 4 /* number of bytes/track (ATA-1) */
86#define SECT_BYTES 5 /* number of bytes/sector (ATA-1) */
87#define LSECTS 6 /* number of logical sectors/track */
88#define START_SERIAL 10 /* ASCII serial number */
89#define LENGTH_SERIAL 10 /* 10 words (20 bytes or characters) */
90#define BUF_TYPE 20 /* buffer type (ATA-1) */
91#define BUFFER__SIZE 21 /* buffer size (ATA-1) */
92#define RW_LONG 22 /* extra bytes in R/W LONG cmd ( < ATA-4)*/
93#define START_FW_REV 23 /* ASCII firmware revision */
94#define LENGTH_FW_REV 4 /* 4 words (8 bytes or characters) */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000095#define START_MODEL 27 /* ASCII model number */
96#define LENGTH_MODEL 20 /* 20 words (40 bytes or characters) */
Denis Vlasenko4b924f32007-05-30 00:29:55 +000097#define SECTOR_XFER_MAX 47 /* r/w multiple: max sectors xfered */
Eric Andersen3443bd72003-07-22 07:30:36 +000098#define DWORD_IO 48 /* can do double-word IO (ATA-1 only) */
99#define CAPAB_0 49 /* capabilities */
100#define CAPAB_1 50
101#define PIO_MODE 51 /* max PIO mode supported (obsolete)*/
102#define DMA_MODE 52 /* max Singleword DMA mode supported (obs)*/
103#define WHATS_VALID 53 /* what fields are valid */
104#define LCYLS_CUR 54 /* current logical cylinders */
105#define LHEADS_CUR 55 /* current logical heads */
Denis Vlasenko4b924f32007-05-30 00:29:55 +0000106#define LSECTS_CUR 56 /* current logical sectors/track */
Eric Andersen3443bd72003-07-22 07:30:36 +0000107#define CAPACITY_LSB 57 /* current capacity in sectors */
108#define CAPACITY_MSB 58
109#define SECTOR_XFER_CUR 59 /* r/w multiple: current sectors xfered */
110#define LBA_SECTS_LSB 60 /* LBA: total number of user */
111#define LBA_SECTS_MSB 61 /* addressable sectors */
112#define SINGLE_DMA 62 /* singleword DMA modes */
113#define MULTI_DMA 63 /* multiword DMA modes */
114#define ADV_PIO_MODES 64 /* advanced PIO modes supported */
115 /* multiword DMA xfer cycle time: */
116#define DMA_TIME_MIN 65 /* - minimum */
Denis Vlasenko551ffdc2009-04-01 19:48:05 +0000117#define DMA_TIME_NORM 66 /* - manufacturer's recommended */
Eric Andersen3443bd72003-07-22 07:30:36 +0000118 /* minimum PIO xfer cycle time: */
119#define PIO_NO_FLOW 67 /* - without flow control */
120#define PIO_FLOW 68 /* - with IORDY flow control */
121#define PKT_REL 71 /* typical #ns from PKT cmd to bus rel */
122#define SVC_NBSY 72 /* typical #ns from SERVICE cmd to !BSY */
123#define CDR_MAJOR 73 /* CD ROM: major version number */
124#define CDR_MINOR 74 /* CD ROM: minor version number */
125#define QUEUE_DEPTH 75 /* queue depth */
126#define MAJOR 80 /* major version number */
127#define MINOR 81 /* minor version number */
128#define CMDS_SUPP_0 82 /* command/feature set(s) supported */
129#define CMDS_SUPP_1 83
130#define CMDS_SUPP_2 84
131#define CMDS_EN_0 85 /* command/feature set(s) enabled */
132#define CMDS_EN_1 86
133#define CMDS_EN_2 87
134#define ULTRA_DMA 88 /* ultra DMA modes */
135 /* time to complete security erase */
136#define ERASE_TIME 89 /* - ordinary */
137#define ENH_ERASE_TIME 90 /* - enhanced */
138#define ADV_PWR 91 /* current advanced power management level
Glenn L McGrath07085852003-10-09 07:28:22 +0000139 in low byte, 0x40 in high byte. */
Denis Vlasenko551ffdc2009-04-01 19:48:05 +0000140#define PSWD_CODE 92 /* master password revision code */
Eric Andersen3443bd72003-07-22 07:30:36 +0000141#define HWRST_RSLT 93 /* hardware reset result */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000142#define ACOUSTIC 94 /* acoustic mgmt values ( >= ATA-6) */
Eric Andersen3443bd72003-07-22 07:30:36 +0000143#define LBA_LSB 100 /* LBA: maximum. Currently only 48 */
144#define LBA_MID 101 /* bits are used, but addr 103 */
145#define LBA_48_MSB 102 /* has been reserved for LBA in */
146#define LBA_64_MSB 103 /* the future. */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000147#define RM_STAT 127 /* removable media status notification feature set support */
Eric Andersen3443bd72003-07-22 07:30:36 +0000148#define SECU_STATUS 128 /* security status */
149#define CFA_PWR_MODE 160 /* CFA power mode 1 */
150#define START_MEDIA 176 /* media serial number */
151#define LENGTH_MEDIA 20 /* 20 words (40 bytes or characters)*/
152#define START_MANUF 196 /* media manufacturer I.D. */
153#define LENGTH_MANUF 10 /* 10 words (20 bytes or characters) */
154#define INTEGRITY 255 /* integrity word */
155
156/* bit definitions within the words */
157/* -------------------------------- */
158
159/* many words are considered valid if bit 15 is 0 and bit 14 is 1 */
160#define VALID 0xc000
161#define VALID_VAL 0x4000
162/* many words are considered invalid if they are either all-0 or all-1 */
163#define NOVAL_0 0x0000
164#define NOVAL_1 0xffff
165
166/* word 0: gen_config */
Glenn L McGrath07085852003-10-09 07:28:22 +0000167#define NOT_ATA 0x8000
Eric Andersen3443bd72003-07-22 07:30:36 +0000168#define NOT_ATAPI 0x4000 /* (check only if bit 15 == 1) */
169#define MEDIA_REMOVABLE 0x0080
170#define DRIVE_NOT_REMOVABLE 0x0040 /* bit obsoleted in ATA 6 */
171#define INCOMPLETE 0x0004
172#define CFA_SUPPORT_VAL 0x848a /* 848a=CFA feature set support */
173#define DRQ_RESPONSE_TIME 0x0060
174#define DRQ_3MS_VAL 0x0000
175#define DRQ_INTR_VAL 0x0020
176#define DRQ_50US_VAL 0x0040
177#define PKT_SIZE_SUPPORTED 0x0003
178#define PKT_SIZE_12_VAL 0x0000
179#define PKT_SIZE_16_VAL 0x0001
180#define EQPT_TYPE 0x1f00
181#define SHIFT_EQPT 8
182
183#define CDROM 0x0005
184
Eric Andersen3443bd72003-07-22 07:30:36 +0000185/* word 1: number of logical cylinders */
186#define LCYLS_MAX 0x3fff /* maximum allowable value */
187
Eric Andersenaff114c2004-04-14 17:51:38 +0000188/* word 2: specific configuration
Eric Andersen3443bd72003-07-22 07:30:36 +0000189 * (a) require SET FEATURES to spin-up
190 * (b) require spin-up to fully reply to IDENTIFY DEVICE
191 */
192#define STBY_NID_VAL 0x37c8 /* (a) and (b) */
193#define STBY_ID_VAL 0x738c /* (a) and not (b) */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000194#define PWRD_NID_VAL 0x8c73 /* not (a) and (b) */
Eric Andersen3443bd72003-07-22 07:30:36 +0000195#define PWRD_ID_VAL 0xc837 /* not (a) and not (b) */
196
197/* words 47 & 59: sector_xfer_max & sector_xfer_cur */
198#define SECTOR_XFER 0x00ff /* sectors xfered on r/w multiple cmds*/
199#define MULTIPLE_SETTING_VALID 0x0100 /* 1=multiple sector setting is valid */
200
201/* word 49: capabilities 0 */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000202#define STD_STBY 0x2000 /* 1=standard values supported (ATA); 0=vendor specific values */
Eric Andersen3443bd72003-07-22 07:30:36 +0000203#define IORDY_SUP 0x0800 /* 1=support; 0=may be supported */
204#define IORDY_OFF 0x0400 /* 1=may be disabled */
205#define LBA_SUP 0x0200 /* 1=Logical Block Address support */
206#define DMA_SUP 0x0100 /* 1=Direct Memory Access support */
207#define DMA_IL_SUP 0x8000 /* 1=interleaved DMA support (ATAPI) */
208#define CMD_Q_SUP 0x4000 /* 1=command queuing support (ATAPI) */
209#define OVLP_SUP 0x2000 /* 1=overlap operation support (ATAPI) */
210#define SWRST_REQ 0x1000 /* 1=ATA SW reset required (ATAPI, obsolete */
211
212/* word 50: capabilities 1 */
213#define MIN_STANDBY_TIMER 0x0001 /* 1=device specific standby timer value minimum */
214
215/* words 51 & 52: PIO & DMA cycle times */
216#define MODE 0xff00 /* the mode is in the MSBs */
217
218/* word 53: whats_valid */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000219#define OK_W88 0x0004 /* the ultra_dma info is valid */
Eric Andersen3443bd72003-07-22 07:30:36 +0000220#define OK_W64_70 0x0002 /* see above for word descriptions */
221#define OK_W54_58 0x0001 /* current cyl, head, sector, cap. info valid */
222
223/*word 63,88: dma_mode, ultra_dma_mode*/
224#define MODE_MAX 7 /* bit definitions force udma <=7 (when
225 * udma >=8 comes out it'll have to be
226 * defined in a new dma_mode word!) */
227
228/* word 64: PIO transfer modes */
229#define PIO_SUP 0x00ff /* only bits 0 & 1 are used so far, */
230#define PIO_MODE_MAX 8 /* but all 8 bits are defined */
231
232/* word 75: queue_depth */
233#define DEPTH_BITS 0x001f /* bits used for queue depth */
234
235/* words 80-81: version numbers */
236/* NOVAL_0 or NOVAL_1 means device does not report version */
237
238/* word 81: minor version number */
Rob Landley0e6a3e12006-04-28 01:33:30 +0000239#define MINOR_MAX 0x22
Eric Andersen3443bd72003-07-22 07:30:36 +0000240/* words 82-84: cmds/feats supported */
241#define CMDS_W82 0x77ff /* word 82: defined command locations*/
242#define CMDS_W83 0x3fff /* word 83: defined command locations*/
243#define CMDS_W84 0x002f /* word 83: defined command locations*/
Glenn L McGrath07085852003-10-09 07:28:22 +0000244#define SUPPORT_48_BIT 0x0400
Eric Andersen3443bd72003-07-22 07:30:36 +0000245#define NUM_CMD_FEAT_STR 48
246
Eric Andersen3443bd72003-07-22 07:30:36 +0000247/* words 85-87: cmds/feats enabled */
248/* use cmd_feat_str[] to display what commands and features have
Glenn L McGrath07085852003-10-09 07:28:22 +0000249 * been enabled with words 85-87
Eric Andersen3443bd72003-07-22 07:30:36 +0000250 */
251
252/* words 89, 90, SECU ERASE TIME */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000253#define ERASE_BITS 0x00ff
Eric Andersen3443bd72003-07-22 07:30:36 +0000254
255/* word 92: master password revision */
256/* NOVAL_0 or NOVAL_1 means no support for master password revision */
257
258/* word 93: hw reset result */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000259#define CBLID 0x2000 /* CBLID status */
260#define RST0 0x0001 /* 1=reset to device #0 */
261#define DEV_DET 0x0006 /* how device num determined */
262#define JUMPER_VAL 0x0002 /* device num determined by jumper */
263#define CSEL_VAL 0x0004 /* device num determined by CSEL_VAL */
Eric Andersen3443bd72003-07-22 07:30:36 +0000264
265/* word 127: removable media status notification feature set support */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000266#define RM_STAT_BITS 0x0003
267#define RM_STAT_SUP 0x0001
Glenn L McGrath07085852003-10-09 07:28:22 +0000268
Eric Andersen3443bd72003-07-22 07:30:36 +0000269/* word 128: security */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000270#define SECU_ENABLED 0x0002
271#define SECU_LEVEL 0x0010
272#define NUM_SECU_STR 6
Eric Andersen3443bd72003-07-22 07:30:36 +0000273
274/* word 160: CFA power mode */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000275#define VALID_W160 0x8000 /* 1=word valid */
276#define PWR_MODE_REQ 0x2000 /* 1=CFA power mode req'd by some cmds*/
277#define PWR_MODE_OFF 0x1000 /* 1=CFA power moded disabled */
278#define MAX_AMPS 0x0fff /* value = max current in ma */
Eric Andersen3443bd72003-07-22 07:30:36 +0000279
280/* word 255: integrity */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000281#define SIG 0x00ff /* signature location */
282#define SIG_VAL 0x00a5 /* signature value */
Eric Andersen3443bd72003-07-22 07:30:36 +0000283
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000284#define TIMING_BUF_MB 1
285#define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024)
Glenn L McGrath07085852003-10-09 07:28:22 +0000286
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000287#undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */
Glenn L McGrath07085852003-10-09 07:28:22 +0000288
Denis Vlasenko892536f2007-09-27 10:23:34 +0000289
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200290#define IS_GET 1
291#define IS_SET 2
292
293
Denis Vlasenko892536f2007-09-27 10:23:34 +0000294enum { fd = 3 };
295
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000296
297struct globals {
298 smallint get_identity, get_geom;
299 smallint do_flush;
300 smallint do_ctimings, do_timings;
301 smallint reread_partn;
302 smallint set_piomode, noisy_piomode;
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200303 smallint getset_readahead;
304 smallint getset_readonly;
305 smallint getset_unmask;
306 smallint getset_mult;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000307#ifdef HDIO_GET_QDMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200308 smallint getset_dma_q;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000309#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200310 smallint getset_nowerr;
311 smallint getset_keep;
312 smallint getset_io32bit;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000313 int piomode;
314 unsigned long Xreadahead;
315 unsigned long readonly;
316 unsigned long unmask;
317 unsigned long mult;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000318#ifdef HDIO_SET_QDMA
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000319 unsigned long dma_q;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000320#endif
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000321 unsigned long nowerr;
322 unsigned long keep;
323 unsigned long io32bit;
324#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
325 unsigned long dma;
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200326 smallint getset_dma;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000327#endif
328#ifdef HDIO_DRIVE_CMD
329 smallint set_xfermode, get_xfermode;
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200330 smallint getset_dkeep;
331 smallint getset_standby;
332 smallint getset_lookahead;
333 smallint getset_prefetch;
334 smallint getset_defects;
335 smallint getset_wcache;
336 smallint getset_doorlock;
337 smallint set_seagate;
338 smallint set_standbynow;
339 smallint set_sleepnow;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000340 smallint get_powermode;
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200341 smallint getset_apmmode;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000342 int xfermode_requested;
343 unsigned long dkeep;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000344 unsigned long standby_requested; /* 0..255 */
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000345 unsigned long lookahead;
346 unsigned long prefetch;
347 unsigned long defects;
348 unsigned long wcache;
349 unsigned long doorlock;
350 unsigned long apmmode;
351#endif
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000352 IF_FEATURE_HDPARM_GET_IDENTITY( smallint get_IDentity;)
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200353 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( smallint getset_busstate;)
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000354 IF_FEATURE_HDPARM_HDIO_DRIVE_RESET( smallint perform_reset;)
355 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( smallint perform_tristate;)
356 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(smallint unregister_hwif;)
357 IF_FEATURE_HDPARM_HDIO_SCAN_HWIF( smallint scan_hwif;)
358 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( unsigned long busstate;)
359 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( unsigned long tristate;)
360 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(unsigned long hwif;)
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000361#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
362 unsigned long hwif_data;
363 unsigned long hwif_ctrl;
364 unsigned long hwif_irq;
365#endif
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +0000366#ifdef DO_FLUSHCACHE
367 unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };
368#endif
Denys Vlasenko98a4c7c2010-02-04 15:00:15 +0100369} FIX_ALIASING;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000370#define G (*(struct globals*)&bb_common_bufsiz1)
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000371#define get_identity (G.get_identity )
372#define get_geom (G.get_geom )
373#define do_flush (G.do_flush )
374#define do_ctimings (G.do_ctimings )
375#define do_timings (G.do_timings )
376#define reread_partn (G.reread_partn )
377#define set_piomode (G.set_piomode )
378#define noisy_piomode (G.noisy_piomode )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200379#define getset_readahead (G.getset_readahead )
380#define getset_readonly (G.getset_readonly )
381#define getset_unmask (G.getset_unmask )
382#define getset_mult (G.getset_mult )
383#define getset_dma_q (G.getset_dma_q )
384#define getset_nowerr (G.getset_nowerr )
385#define getset_keep (G.getset_keep )
386#define getset_io32bit (G.getset_io32bit )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000387#define piomode (G.piomode )
388#define Xreadahead (G.Xreadahead )
389#define readonly (G.readonly )
390#define unmask (G.unmask )
391#define mult (G.mult )
392#define dma_q (G.dma_q )
393#define nowerr (G.nowerr )
394#define keep (G.keep )
395#define io32bit (G.io32bit )
396#define dma (G.dma )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200397#define getset_dma (G.getset_dma )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000398#define set_xfermode (G.set_xfermode )
399#define get_xfermode (G.get_xfermode )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200400#define getset_dkeep (G.getset_dkeep )
401#define getset_standby (G.getset_standby )
402#define getset_lookahead (G.getset_lookahead )
403#define getset_prefetch (G.getset_prefetch )
404#define getset_defects (G.getset_defects )
405#define getset_wcache (G.getset_wcache )
406#define getset_doorlock (G.getset_doorlock )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000407#define set_seagate (G.set_seagate )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000408#define set_standbynow (G.set_standbynow )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000409#define set_sleepnow (G.set_sleepnow )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000410#define get_powermode (G.get_powermode )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200411#define getset_apmmode (G.getset_apmmode )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000412#define xfermode_requested (G.xfermode_requested )
413#define dkeep (G.dkeep )
414#define standby_requested (G.standby_requested )
415#define lookahead (G.lookahead )
416#define prefetch (G.prefetch )
417#define defects (G.defects )
418#define wcache (G.wcache )
419#define doorlock (G.doorlock )
420#define apmmode (G.apmmode )
421#define get_IDentity (G.get_IDentity )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200422#define getset_busstate (G.getset_busstate )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000423#define perform_reset (G.perform_reset )
424#define perform_tristate (G.perform_tristate )
425#define unregister_hwif (G.unregister_hwif )
426#define scan_hwif (G.scan_hwif )
427#define busstate (G.busstate )
428#define tristate (G.tristate )
429#define hwif (G.hwif )
430#define hwif_data (G.hwif_data )
431#define hwif_ctrl (G.hwif_ctrl )
432#define hwif_irq (G.hwif_irq )
Denys Vlasenko7b85ec32015-10-13 17:17:34 +0200433#define INIT_G() do { \
434 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \
435} while (0)
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000436
437
Glenn L McGrath07085852003-10-09 07:28:22 +0000438/* Busybox messages and functions */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000439#if ENABLE_IOCTL_HEX2STR_ERROR
Denis Vlasenko892536f2007-09-27 10:23:34 +0000440static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt, const char *string)
Rob Landley5f8b5ec2006-04-29 16:03:40 +0000441{
442 if (!ioctl(fd, cmd, args))
443 return 0;
444 args[0] = alt;
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000445 return bb_ioctl_or_warn(fd, cmd, args, string);
Rob Landley5f8b5ec2006-04-29 16:03:40 +0000446}
Denis Vlasenko892536f2007-09-27 10:23:34 +0000447#define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt,#cmd)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000448#else
Denis Vlasenko892536f2007-09-27 10:23:34 +0000449static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000450{
451 if (!ioctl(fd, cmd, args))
452 return 0;
453 args[0] = alt;
454 return bb_ioctl_or_warn(fd, cmd, args);
455}
Denis Vlasenko892536f2007-09-27 10:23:34 +0000456#define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000457#endif
Rob Landley5f8b5ec2006-04-29 16:03:40 +0000458
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000459static void on_off(int value)
460{
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000461 puts(value ? " (on)" : " (off)");
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000462}
Glenn L McGrath07085852003-10-09 07:28:22 +0000463
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000464static void print_flag_on_off(int get_arg, const char *s, unsigned long arg)
Glenn L McGrath07085852003-10-09 07:28:22 +0000465{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +0000466 if (get_arg) {
Denys Vlasenko327f5502013-11-29 16:45:45 +0100467 printf(" setting %s to %lu", s, arg);
Glenn L McGrath07085852003-10-09 07:28:22 +0000468 on_off(arg);
469 }
470}
471
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000472static void print_value_on_off(const char *str, unsigned long argp)
Glenn L McGrath07085852003-10-09 07:28:22 +0000473{
Denys Vlasenko327f5502013-11-29 16:45:45 +0100474 printf(" %s\t= %2lu", str, argp);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000475 on_off(argp != 0);
Glenn L McGrath07085852003-10-09 07:28:22 +0000476}
Eric Andersen416c2422003-12-12 00:08:57 +0000477
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000478#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
Denis Vlasenko4daad902007-09-27 10:20:47 +0000479static void print_ascii(const char *p, int length)
480{
481#if BB_BIG_ENDIAN
482#define LE_ONLY(x)
483 enum { ofs = 0 };
484#else
485#define LE_ONLY(x) x
486 /* every 16bit word is big-endian (i.e. inverted) */
487 /* accessing bytes in 1,0, 3,2, 5,4... sequence */
488 int ofs = 1;
489#endif
490
491 length *= 2;
492 /* find first non-space & print it */
493 while (length && p[ofs] != ' ') {
494 p++;
495 LE_ONLY(ofs = -ofs;)
496 length--;
497 }
498 while (length && p[ofs]) {
499 bb_putchar(p[ofs]);
500 p++;
501 LE_ONLY(ofs = -ofs;)
502 length--;
503 }
504 bb_putchar('\n');
505#undef LE_ONLY
506}
Glenn L McGrath07085852003-10-09 07:28:22 +0000507
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000508static void xprint_ascii(uint16_t *val, int i, const char *string, int n)
Glenn L McGrath07085852003-10-09 07:28:22 +0000509{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +0000510 if (val[i]) {
511 printf("\t%-20s", string);
Denis Vlasenko4daad902007-09-27 10:20:47 +0000512 print_ascii((void*)&val[i], n);
Glenn L McGrath07085852003-10-09 07:28:22 +0000513 }
514}
Glenn L McGrath07085852003-10-09 07:28:22 +0000515
Glenn L McGrath07085852003-10-09 07:28:22 +0000516static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode)
517{
Eric Andersen3443bd72003-07-22 07:30:36 +0000518 uint16_t ii;
519 uint8_t err_dma = 0;
Glenn L McGrath07085852003-10-09 07:28:22 +0000520
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000521 for (ii = 0; ii <= MODE_MAX; ii++) {
522 if (mode_sel & 0x0001) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000523 printf("*%cdma%u ", cc, ii);
Rob Landleya3e4f382006-04-29 16:06:31 +0000524 if (*have_mode)
Glenn L McGrath07085852003-10-09 07:28:22 +0000525 err_dma = 1;
Eric Andersen3443bd72003-07-22 07:30:36 +0000526 *have_mode = 1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000527 } else if (mode_sup & 0x0001)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000528 printf("%cdma%u ", cc, ii);
Glenn L McGrath07085852003-10-09 07:28:22 +0000529
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000530 mode_sup >>= 1;
531 mode_sel >>= 1;
Eric Andersen3443bd72003-07-22 07:30:36 +0000532 }
533 return err_dma;
534}
Glenn L McGrath07085852003-10-09 07:28:22 +0000535
Denis Vlasenko91303402007-10-30 19:36:54 +0000536static const char pkt_str[] ALIGN1 =
537 "Direct-access device" "\0" /* word 0, bits 12-8 = 00 */
538 "Sequential-access device" "\0" /* word 0, bits 12-8 = 01 */
539 "Printer" "\0" /* word 0, bits 12-8 = 02 */
540 "Processor" "\0" /* word 0, bits 12-8 = 03 */
541 "Write-once device" "\0" /* word 0, bits 12-8 = 04 */
542 "CD-ROM" "\0" /* word 0, bits 12-8 = 05 */
543 "Scanner" "\0" /* word 0, bits 12-8 = 06 */
544 "Optical memory" "\0" /* word 0, bits 12-8 = 07 */
545 "Medium changer" "\0" /* word 0, bits 12-8 = 08 */
546 "Communications device" "\0" /* word 0, bits 12-8 = 09 */
547 "ACS-IT8 device" "\0" /* word 0, bits 12-8 = 0a */
548 "ACS-IT8 device" "\0" /* word 0, bits 12-8 = 0b */
549 "Array controller" "\0" /* word 0, bits 12-8 = 0c */
550 "Enclosure services" "\0" /* word 0, bits 12-8 = 0d */
551 "Reduced block command device" "\0" /* word 0, bits 12-8 = 0e */
552 "Optical card reader/writer" "\0" /* word 0, bits 12-8 = 0f */
553;
554
555static const char ata1_cfg_str[] ALIGN1 = /* word 0 in ATA-1 mode */
556 "reserved" "\0" /* bit 0 */
557 "hard sectored" "\0" /* bit 1 */
558 "soft sectored" "\0" /* bit 2 */
559 "not MFM encoded " "\0" /* bit 3 */
560 "head switch time > 15us" "\0" /* bit 4 */
561 "spindle motor control option" "\0" /* bit 5 */
562 "fixed drive" "\0" /* bit 6 */
563 "removable drive" "\0" /* bit 7 */
564 "disk xfer rate <= 5Mbs" "\0" /* bit 8 */
565 "disk xfer rate > 5Mbs, <= 10Mbs" "\0" /* bit 9 */
566 "disk xfer rate > 5Mbs" "\0" /* bit 10 */
567 "rotational speed tol." "\0" /* bit 11 */
568 "data strobe offset option" "\0" /* bit 12 */
569 "track offset option" "\0" /* bit 13 */
570 "format speed tolerance gap reqd" "\0" /* bit 14 */
571 "ATAPI" /* bit 14 */
572;
573
574static const char minor_str[] ALIGN1 =
575 /* word 81 value: */
576 "Unspecified" "\0" /* 0x0000 */
577 "ATA-1 X3T9.2 781D prior to rev.4" "\0" /* 0x0001 */
578 "ATA-1 published, ANSI X3.221-1994" "\0" /* 0x0002 */
579 "ATA-1 X3T9.2 781D rev.4" "\0" /* 0x0003 */
580 "ATA-2 published, ANSI X3.279-1996" "\0" /* 0x0004 */
581 "ATA-2 X3T10 948D prior to rev.2k" "\0" /* 0x0005 */
582 "ATA-3 X3T10 2008D rev.1" "\0" /* 0x0006 */
583 "ATA-2 X3T10 948D rev.2k" "\0" /* 0x0007 */
584 "ATA-3 X3T10 2008D rev.0" "\0" /* 0x0008 */
585 "ATA-2 X3T10 948D rev.3" "\0" /* 0x0009 */
586 "ATA-3 published, ANSI X3.298-199x" "\0" /* 0x000a */
587 "ATA-3 X3T10 2008D rev.6" "\0" /* 0x000b */
588 "ATA-3 X3T13 2008D rev.7 and 7a" "\0" /* 0x000c */
589 "ATA/ATAPI-4 X3T13 1153D rev.6" "\0" /* 0x000d */
590 "ATA/ATAPI-4 T13 1153D rev.13" "\0" /* 0x000e */
591 "ATA/ATAPI-4 X3T13 1153D rev.7" "\0" /* 0x000f */
592 "ATA/ATAPI-4 T13 1153D rev.18" "\0" /* 0x0010 */
593 "ATA/ATAPI-4 T13 1153D rev.15" "\0" /* 0x0011 */
594 "ATA/ATAPI-4 published, ANSI INCITS 317-1998" "\0" /* 0x0012 */
595 "ATA/ATAPI-5 T13 1321D rev.3" "\0" /* 0x0013 */
596 "ATA/ATAPI-4 T13 1153D rev.14" "\0" /* 0x0014 */
597 "ATA/ATAPI-5 T13 1321D rev.1" "\0" /* 0x0015 */
598 "ATA/ATAPI-5 published, ANSI INCITS 340-2000" "\0" /* 0x0016 */
599 "ATA/ATAPI-4 T13 1153D rev.17" "\0" /* 0x0017 */
600 "ATA/ATAPI-6 T13 1410D rev.0" "\0" /* 0x0018 */
601 "ATA/ATAPI-6 T13 1410D rev.3a" "\0" /* 0x0019 */
602 "ATA/ATAPI-7 T13 1532D rev.1" "\0" /* 0x001a */
603 "ATA/ATAPI-6 T13 1410D rev.2" "\0" /* 0x001b */
604 "ATA/ATAPI-6 T13 1410D rev.1" "\0" /* 0x001c */
605 "ATA/ATAPI-7 published, ANSI INCITS 397-2005" "\0" /* 0x001d */
606 "ATA/ATAPI-7 T13 1532D rev.0" "\0" /* 0x001e */
607 "reserved" "\0" /* 0x001f */
608 "reserved" "\0" /* 0x0020 */
609 "ATA/ATAPI-7 T13 1532D rev.4a" "\0" /* 0x0021 */
610 "ATA/ATAPI-6 published, ANSI INCITS 361-2002" "\0" /* 0x0022 */
611 "reserved" /* 0x0023-0xfffe */
612;
613static const char actual_ver[MINOR_MAX + 2] ALIGN1 = {
614 /* word 81 value: */
615 0, /* 0x0000 WARNING: actual_ver[] array */
616 1, /* 0x0001 WARNING: corresponds */
617 1, /* 0x0002 WARNING: *exactly* */
618 1, /* 0x0003 WARNING: to the ATA/ */
619 2, /* 0x0004 WARNING: ATAPI version */
620 2, /* 0x0005 WARNING: listed in */
621 3, /* 0x0006 WARNING: the */
622 2, /* 0x0007 WARNING: minor_str */
623 3, /* 0x0008 WARNING: array */
624 2, /* 0x0009 WARNING: above. */
625 3, /* 0x000a WARNING: */
626 3, /* 0x000b WARNING: If you change */
627 3, /* 0x000c WARNING: that one, */
628 4, /* 0x000d WARNING: change this one */
629 4, /* 0x000e WARNING: too!!! */
630 4, /* 0x000f */
631 4, /* 0x0010 */
632 4, /* 0x0011 */
633 4, /* 0x0012 */
634 5, /* 0x0013 */
635 4, /* 0x0014 */
636 5, /* 0x0015 */
637 5, /* 0x0016 */
638 4, /* 0x0017 */
639 6, /* 0x0018 */
640 6, /* 0x0019 */
641 7, /* 0x001a */
642 6, /* 0x001b */
643 6, /* 0x001c */
644 7, /* 0x001d */
645 7, /* 0x001e */
646 0, /* 0x001f */
647 0, /* 0x0020 */
648 7, /* 0x0021 */
649 6, /* 0x0022 */
650 0 /* 0x0023-0xfffe */
651};
652
653static const char cmd_feat_str[] ALIGN1 =
654 "" "\0" /* word 82 bit 15: obsolete */
655 "NOP cmd" "\0" /* word 82 bit 14 */
656 "READ BUFFER cmd" "\0" /* word 82 bit 13 */
657 "WRITE BUFFER cmd" "\0" /* word 82 bit 12 */
658 "" "\0" /* word 82 bit 11: obsolete */
659 "Host Protected Area feature set" "\0" /* word 82 bit 10 */
660 "DEVICE RESET cmd" "\0" /* word 82 bit 9 */
661 "SERVICE interrupt" "\0" /* word 82 bit 8 */
662 "Release interrupt" "\0" /* word 82 bit 7 */
663 "Look-ahead" "\0" /* word 82 bit 6 */
664 "Write cache" "\0" /* word 82 bit 5 */
665 "PACKET command feature set" "\0" /* word 82 bit 4 */
666 "Power Management feature set" "\0" /* word 82 bit 3 */
667 "Removable Media feature set" "\0" /* word 82 bit 2 */
668 "Security Mode feature set" "\0" /* word 82 bit 1 */
669 "SMART feature set" "\0" /* word 82 bit 0 */
670 /* -------------- */
671 "" "\0" /* word 83 bit 15: !valid bit */
672 "" "\0" /* word 83 bit 14: valid bit */
673 "FLUSH CACHE EXT cmd" "\0" /* word 83 bit 13 */
674 "Mandatory FLUSH CACHE cmd " "\0" /* word 83 bit 12 */
675 "Device Configuration Overlay feature set " "\0"
676 "48-bit Address feature set " "\0" /* word 83 bit 10 */
677 "" "\0"
678 "SET MAX security extension" "\0" /* word 83 bit 8 */
679 "Address Offset Reserved Area Boot" "\0" /* word 83 bit 7 */
680 "SET FEATURES subcommand required to spinup after power up" "\0"
681 "Power-Up In Standby feature set" "\0" /* word 83 bit 5 */
682 "Removable Media Status Notification feature set" "\0"
683 "Adv. Power Management feature set" "\0" /* word 83 bit 3 */
684 "CFA feature set" "\0" /* word 83 bit 2 */
685 "READ/WRITE DMA QUEUED" "\0" /* word 83 bit 1 */
686 "DOWNLOAD MICROCODE cmd" "\0" /* word 83 bit 0 */
687 /* -------------- */
688 "" "\0" /* word 84 bit 15: !valid bit */
689 "" "\0" /* word 84 bit 14: valid bit */
690 "" "\0" /* word 84 bit 13: reserved */
691 "" "\0" /* word 84 bit 12: reserved */
692 "" "\0" /* word 84 bit 11: reserved */
693 "" "\0" /* word 84 bit 10: reserved */
694 "" "\0" /* word 84 bit 9: reserved */
695 "" "\0" /* word 84 bit 8: reserved */
696 "" "\0" /* word 84 bit 7: reserved */
697 "" "\0" /* word 84 bit 6: reserved */
698 "General Purpose Logging feature set" "\0" /* word 84 bit 5 */
699 "" "\0" /* word 84 bit 4: reserved */
700 "Media Card Pass Through Command feature set " "\0"
701 "Media serial number " "\0" /* word 84 bit 2 */
702 "SMART self-test " "\0" /* word 84 bit 1 */
703 "SMART error logging " /* word 84 bit 0 */
704;
705
706static const char secu_str[] ALIGN1 =
707 "supported" "\0" /* word 128, bit 0 */
708 "enabled" "\0" /* word 128, bit 1 */
709 "locked" "\0" /* word 128, bit 2 */
710 "frozen" "\0" /* word 128, bit 3 */
711 "expired: security count" "\0" /* word 128, bit 4 */
712 "supported: enhanced erase" /* word 128, bit 5 */
713;
714
715// Parse 512 byte disk identification block and print much crap.
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000716static void identify(uint16_t *val) NORETURN;
Denis Vlasenko4daad902007-09-27 10:20:47 +0000717static void identify(uint16_t *val)
Eric Andersen3443bd72003-07-22 07:30:36 +0000718{
Denis Vlasenko4daad902007-09-27 10:20:47 +0000719 uint16_t ii, jj, kk;
Eric Andersen3443bd72003-07-22 07:30:36 +0000720 uint16_t like_std = 1, std = 0, min_std = 0xffff;
721 uint16_t dev = NO_DEV, eqpt = NO_DEV;
722 uint8_t have_mode = 0, err_dma = 0;
723 uint8_t chksum = 0;
724 uint32_t ll, mm, nn, oo;
Rob Landley2e2d7522006-04-29 15:23:33 +0000725 uint64_t bbbig; /* (:) */
Rob Landleyadde7982006-05-16 15:32:30 +0000726 const char *strng;
Denis Vlasenko4daad902007-09-27 10:20:47 +0000727#if BB_BIG_ENDIAN
728 uint16_t buf[256];
Eric Andersen3443bd72003-07-22 07:30:36 +0000729
Denis Vlasenko4daad902007-09-27 10:20:47 +0000730 // Adjust for endianness
731 swab(val, buf, sizeof(buf));
732 val = buf;
733#endif
Denys Vlasenkob22bbff2009-07-04 16:50:43 +0200734 /* check if we recognize the device type */
Denis Vlasenko4daad902007-09-27 10:20:47 +0000735 bb_putchar('\n');
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000736 if (!(val[GEN_CONFIG] & NOT_ATA)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000737 dev = ATA_DEV;
738 printf("ATA device, with ");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000739 } else if (val[GEN_CONFIG]==CFA_SUPPORT_VAL) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000740 dev = ATA_DEV;
741 like_std = 4;
742 printf("CompactFlash ATA device, with ");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000743 } else if (!(val[GEN_CONFIG] & NOT_ATAPI)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000744 dev = ATAPI_DEV;
745 eqpt = (val[GEN_CONFIG] & EQPT_TYPE) >> SHIFT_EQPT;
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000746 printf("ATAPI %s, with ", eqpt <= 0xf ? nth_string(pkt_str, eqpt) : "unknown");
Eric Andersen3443bd72003-07-22 07:30:36 +0000747 like_std = 3;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000748 } else
Denis Vlasenko91303402007-10-30 19:36:54 +0000749 /* "Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n" */
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +0000750 bb_error_msg_and_die("unknown device type");
Eric Andersen3443bd72003-07-22 07:30:36 +0000751
Rob Landleyadde7982006-05-16 15:32:30 +0000752 printf("%sremovable media\n", !(val[GEN_CONFIG] & MEDIA_REMOVABLE) ? "non-" : "");
Eric Andersen3443bd72003-07-22 07:30:36 +0000753 /* Info from the specific configuration word says whether or not the
754 * ID command completed correctly. It is only defined, however in
Glenn L McGrath07085852003-10-09 07:28:22 +0000755 * ATA/ATAPI-5 & 6; it is reserved (value theoretically 0) in prior
Eric Andersen3443bd72003-07-22 07:30:36 +0000756 * standards. Since the values allowed for this word are extremely
757 * specific, it should be safe to check it now, even though we don't
758 * know yet what standard this device is using.
759 */
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000760 if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL)
761 || (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL)
762 ) {
Glenn L McGrath07085852003-10-09 07:28:22 +0000763 like_std = 5;
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000764 if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL))
Denys Vlasenkod60752f2015-10-07 22:42:45 +0200765 puts("powers-up in standby; SET FEATURES subcmd spins-up.");
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000766 if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE))
Denys Vlasenkod60752f2015-10-07 22:42:45 +0200767 puts("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n");
Eric Andersen3443bd72003-07-22 07:30:36 +0000768 }
769
770 /* output the model and serial numbers and the fw revision */
Glenn L McGrath07085852003-10-09 07:28:22 +0000771 xprint_ascii(val, START_MODEL, "Model Number:", LENGTH_MODEL);
772 xprint_ascii(val, START_SERIAL, "Serial Number:", LENGTH_SERIAL);
773 xprint_ascii(val, START_FW_REV, "Firmware Revision:", LENGTH_FW_REV);
774 xprint_ascii(val, START_MEDIA, "Media Serial Num:", LENGTH_MEDIA);
775 xprint_ascii(val, START_MANUF, "Media Manufacturer:", LENGTH_MANUF);
Eric Andersen3443bd72003-07-22 07:30:36 +0000776
777 /* major & minor standards version number (Note: these words were not
778 * defined until ATA-3 & the CDROM std uses different words.) */
779 printf("Standards:");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000780 if (eqpt != CDROM) {
781 if (val[MINOR] && (val[MINOR] <= MINOR_MAX)) {
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000782 if (like_std < 3) like_std = 3;
Eric Andersen3443bd72003-07-22 07:30:36 +0000783 std = actual_ver[val[MINOR]];
Denys Vlasenkof3ea7922010-07-26 01:06:14 +0200784 if (std)
785 printf("\n\tUsed: %s ", nth_string(minor_str, val[MINOR]));
Eric Andersen3443bd72003-07-22 07:30:36 +0000786 }
787 /* looks like when they up-issue the std, they obsolete one;
Glenn L McGrath07085852003-10-09 07:28:22 +0000788 * thus, only the newest 4 issues need be supported. (That's
Eric Andersen3443bd72003-07-22 07:30:36 +0000789 * what "kk" and "min_std" are all about.) */
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000790 if (val[MAJOR] && (val[MAJOR] != NOVAL_1)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000791 printf("\n\tSupported: ");
792 jj = val[MAJOR] << 1;
793 kk = like_std >4 ? like_std-4: 0;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000794 for (ii = 14; (ii >0)&&(ii>kk); ii--) {
795 if (jj & 0x8000) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000796 printf("%u ", ii);
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000797 if (like_std < ii) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000798 like_std = ii;
799 kk = like_std >4 ? like_std-4: 0;
800 }
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000801 if (min_std > ii) min_std = ii;
Eric Andersen3443bd72003-07-22 07:30:36 +0000802 }
803 jj <<= 1;
804 }
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000805 if (like_std < 3) like_std = 3;
Eric Andersen3443bd72003-07-22 07:30:36 +0000806 }
807 /* Figure out what standard the device is using if it hasn't told
808 * us. If we know the std, check if the device is using any of
809 * the words from the next level up. It happens.
810 */
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000811 if (like_std < std) like_std = std;
Glenn L McGrath07085852003-10-09 07:28:22 +0000812
Rob Landleya3e4f382006-04-29 16:06:31 +0000813 if (((std == 5) || (!std && (like_std < 6))) &&
Glenn L McGrath07085852003-10-09 07:28:22 +0000814 ((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
815 (( val[CMDS_SUPP_1] & CMDS_W83) > 0x00ff)) ||
816 ((( val[CMDS_SUPP_2] & VALID) == VALID_VAL) &&
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000817 ( val[CMDS_SUPP_2] & CMDS_W84) ) )
818 ) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000819 like_std = 6;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000820 } else if (((std == 4) || (!std && (like_std < 5))) &&
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000821 ((((val[INTEGRITY] & SIG) == SIG_VAL) && !chksum) ||
Glenn L McGrath07085852003-10-09 07:28:22 +0000822 (( val[HWRST_RSLT] & VALID) == VALID_VAL) ||
823 ((( val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
824 (( val[CMDS_SUPP_1] & CMDS_W83) > 0x001f)) ) )
825 {
Eric Andersen3443bd72003-07-22 07:30:36 +0000826 like_std = 5;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000827 } else if (((std == 3) || (!std && (like_std < 4))) &&
Glenn L McGrath07085852003-10-09 07:28:22 +0000828 ((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
829 ((( val[CMDS_SUPP_1] & CMDS_W83) > 0x0000) ||
830 (( val[CMDS_SUPP_0] & CMDS_W82) > 0x000f))) ||
831 (( val[CAPAB_1] & VALID) == VALID_VAL) ||
832 (( val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) ||
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000833 (( val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) )
834 ) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000835 like_std = 4;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000836 } else if (((std == 2) || (!std && (like_std < 3)))
837 && ((val[CMDS_SUPP_1] & VALID) == VALID_VAL)
838 ) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000839 like_std = 3;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000840 } else if (((std == 1) || (!std && (like_std < 2))) &&
Glenn L McGrath07085852003-10-09 07:28:22 +0000841 ((val[CAPAB_0] & (IORDY_SUP | IORDY_OFF)) ||
842 (val[WHATS_VALID] & OK_W64_70)) )
843 {
Eric Andersen3443bd72003-07-22 07:30:36 +0000844 like_std = 2;
845 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000846
Rob Landleya3e4f382006-04-29 16:06:31 +0000847 if (!std)
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000848 printf("\n\tLikely used: %u\n", like_std);
Rob Landleya3e4f382006-04-29 16:06:31 +0000849 else if (like_std > std)
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000850 printf("& some of %u\n", like_std);
Glenn L McGrath07085852003-10-09 07:28:22 +0000851 else
Denis Vlasenko4daad902007-09-27 10:20:47 +0000852 bb_putchar('\n');
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000853 } else {
Eric Andersen3443bd72003-07-22 07:30:36 +0000854 /* TBD: do CDROM stuff more thoroughly. For now... */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000855 kk = 0;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000856 if (val[CDR_MINOR] == 9) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000857 kk = 1;
858 printf("\n\tUsed: ATAPI for CD-ROMs, SFF-8020i, r2.5");
859 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000860 if (val[CDR_MAJOR] && (val[CDR_MAJOR] !=NOVAL_1)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000861 kk = 1;
862 printf("\n\tSupported: CD-ROM ATAPI");
863 jj = val[CDR_MAJOR] >> 1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000864 for (ii = 1; ii < 15; ii++) {
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000865 if (jj & 0x0001) printf("-%u ", ii);
Eric Andersen3443bd72003-07-22 07:30:36 +0000866 jj >>= 1;
867 }
868 }
Denis Vlasenkofeb7ae72007-10-01 12:05:12 +0000869 puts(kk ? "" : "\n\tLikely used CD-ROM ATAPI-1");
Eric Andersen3443bd72003-07-22 07:30:36 +0000870 /* the cdrom stuff is more like ATA-2 than anything else, so: */
871 like_std = 2;
872 }
873
Rob Landleya3e4f382006-04-29 16:06:31 +0000874 if (min_std == 0xffff)
Glenn L McGrath07085852003-10-09 07:28:22 +0000875 min_std = like_std > 4 ? like_std - 3 : 1;
Eric Andersen3443bd72003-07-22 07:30:36 +0000876
Denys Vlasenkod60752f2015-10-07 22:42:45 +0200877 puts("Configuration:");
Eric Andersen3443bd72003-07-22 07:30:36 +0000878 /* more info from the general configuration word */
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000879 if ((eqpt != CDROM) && (like_std == 1)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000880 jj = val[GEN_CONFIG] >> 1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000881 for (ii = 1; ii < 15; ii++) {
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000882 if (jj & 0x0001)
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000883 printf("\t%s\n", nth_string(ata1_cfg_str, ii));
Eric Andersen3443bd72003-07-22 07:30:36 +0000884 jj >>=1;
885 }
886 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000887 if (dev == ATAPI_DEV) {
Rob Landleyadde7982006-05-16 15:32:30 +0000888 if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_3MS_VAL)
889 strng = "3ms";
890 else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_INTR_VAL)
891 strng = "<=10ms with INTRQ";
892 else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_50US_VAL)
893 strng ="50us";
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000894 else
Denis Vlasenko91303402007-10-30 19:36:54 +0000895 strng = "unknown";
Rob Landleyadde7982006-05-16 15:32:30 +0000896 printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */
897
898 if ((val[GEN_CONFIG] & PKT_SIZE_SUPPORTED) == PKT_SIZE_12_VAL)
899 strng = "12 bytes";
900 else if ((val[GEN_CONFIG] & PKT_SIZE_SUPPORTED) == PKT_SIZE_16_VAL)
901 strng = "16 bytes";
902 else
Denis Vlasenko91303402007-10-30 19:36:54 +0000903 strng = "unknown";
Rob Landleyadde7982006-05-16 15:32:30 +0000904 puts(strng);
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000905 } else {
Glenn L McGrath07085852003-10-09 07:28:22 +0000906 /* addressing...CHS? See section 6.2 of ATA specs 4 or 5 */
Eric Andersen3443bd72003-07-22 07:30:36 +0000907 ll = (uint32_t)val[LBA_SECTS_MSB] << 16 | val[LBA_SECTS_LSB];
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200908 mm = 0;
909 bbbig = 0;
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000910 if ((ll > 0x00FBFC10) && (!val[LCYLS]))
Denys Vlasenkod60752f2015-10-07 22:42:45 +0200911 puts("\tCHS addressing not supported");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000912 else {
Eric Andersen3443bd72003-07-22 07:30:36 +0000913 jj = val[WHATS_VALID] & OK_W54_58;
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200914 printf("\tLogical\t\tmax\tcurrent\n"
915 "\tcylinders\t%u\t%u\n"
916 "\theads\t\t%u\t%u\n"
917 "\tsectors/track\t%u\t%u\n"
918 "\t--\n",
919 val[LCYLS],
920 jj ? val[LCYLS_CUR] : 0,
921 val[LHEADS],
922 jj ? val[LHEADS_CUR] : 0,
923 val[LSECTS],
924 jj ? val[LSECTS_CUR] : 0);
Glenn L McGrath07085852003-10-09 07:28:22 +0000925
Rob Landleyadde7982006-05-16 15:32:30 +0000926 if ((min_std == 1) && (val[TRACK_BYTES] || val[SECT_BYTES]))
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200927 printf("\tbytes/track: %u\tbytes/sector: %u\n",
928 val[TRACK_BYTES], val[SECT_BYTES]);
Glenn L McGrath07085852003-10-09 07:28:22 +0000929
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000930 if (jj) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000931 mm = (uint32_t)val[CAPACITY_MSB] << 16 | val[CAPACITY_LSB];
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000932 if (like_std < 3) {
933 /* check Endian of capacity bytes */
Eric Andersen3443bd72003-07-22 07:30:36 +0000934 nn = val[LCYLS_CUR] * val[LHEADS_CUR] * val[LSECTS_CUR];
935 oo = (uint32_t)val[CAPACITY_LSB] << 16 | val[CAPACITY_MSB];
Rob Landleya3e4f382006-04-29 16:06:31 +0000936 if (abs(mm - nn) > abs(oo - nn))
Eric Andersen3443bd72003-07-22 07:30:36 +0000937 mm = oo;
938 }
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000939 printf("\tCHS current addressable sectors:%11u\n", mm);
Glenn L McGrath07085852003-10-09 07:28:22 +0000940 }
Eric Andersen3443bd72003-07-22 07:30:36 +0000941 }
942 /* LBA addressing */
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000943 printf("\tLBA user addressable sectors:%11u\n", ll);
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000944 if (((val[CMDS_SUPP_1] & VALID) == VALID_VAL)
945 && (val[CMDS_SUPP_1] & SUPPORT_48_BIT)
946 ) {
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000947 bbbig = (uint64_t)val[LBA_64_MSB] << 48 |
948 (uint64_t)val[LBA_48_MSB] << 32 |
949 (uint64_t)val[LBA_MID] << 16 |
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000950 val[LBA_LSB];
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000951 printf("\tLBA48 user addressable sectors:%11"PRIu64"\n", bbbig);
Eric Andersen3443bd72003-07-22 07:30:36 +0000952 }
Glenn L McGrath07085852003-10-09 07:28:22 +0000953
954 if (!bbbig)
Rob Landley2e2d7522006-04-29 15:23:33 +0000955 bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000956 printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11);
957 bbbig = (bbbig << 9) / 1000000;
958 printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig);
Glenn L McGrath07085852003-10-09 07:28:22 +0000959
Rob Landleyadde7982006-05-16 15:32:30 +0000960 if (bbbig > 1000)
Rob Landley81dab2c2006-05-28 01:56:08 +0000961 printf("(%"PRIu64" GB)\n", bbbig/1000);
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000962 else
Denis Vlasenko4daad902007-09-27 10:20:47 +0000963 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +0000964 }
965
966 /* hw support of commands (capabilities) */
Glenn L McGrath07085852003-10-09 07:28:22 +0000967 printf("Capabilities:\n\t");
968
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000969 if (dev == ATAPI_DEV) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200970 if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP))
971 printf("Cmd queuing, ");
972 if (val[CAPAB_0] & OVLP_SUP)
973 printf("Cmd overlap, ");
Eric Andersen3443bd72003-07-22 07:30:36 +0000974 }
Rob Landleyadde7982006-05-16 15:32:30 +0000975 if (val[CAPAB_0] & LBA_SUP) printf("LBA, ");
Glenn L McGrath07085852003-10-09 07:28:22 +0000976
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000977 if (like_std != 1) {
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000978 printf("IORDY%s(can%s be disabled)\n",
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200979 !(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "",
980 (val[CAPAB_0] & IORDY_OFF) ? "" :"not");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000981 } else
Denys Vlasenkod60752f2015-10-07 22:42:45 +0200982 puts("no IORDY");
Glenn L McGrath07085852003-10-09 07:28:22 +0000983
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000984 if ((like_std == 1) && val[BUF_TYPE]) {
Rob Landleyadde7982006-05-16 15:32:30 +0000985 printf("\tBuffer type: %04x: %s%s\n", val[BUF_TYPE],
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200986 (val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector",
987 (val[BUF_TYPE] > 2) ? " with read caching ability" : "");
Eric Andersen3443bd72003-07-22 07:30:36 +0000988 }
Rob Landleyadde7982006-05-16 15:32:30 +0000989
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000990 if ((min_std == 1) && (val[BUFFER__SIZE] && (val[BUFFER__SIZE] != NOVAL_1))) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000991 printf("\tBuffer size: %.1fkB\n", (float)val[BUFFER__SIZE]/2);
Eric Andersen3443bd72003-07-22 07:30:36 +0000992 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000993 if ((min_std < 4) && (val[RW_LONG])) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000994 printf("\tbytes avail on r/w long: %u\n", val[RW_LONG]);
Eric Andersen3443bd72003-07-22 07:30:36 +0000995 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000996 if ((eqpt != CDROM) && (like_std > 3)) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000997 printf("\tQueue depth: %u\n", (val[QUEUE_DEPTH] & DEPTH_BITS) + 1);
Eric Andersen3443bd72003-07-22 07:30:36 +0000998 }
Glenn L McGrath07085852003-10-09 07:28:22 +0000999
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001000 if (dev == ATA_DEV) {
Rob Landleya3e4f382006-04-29 16:06:31 +00001001 if (like_std == 1)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001002 printf("\tCan%s perform double-word IO\n", (!val[DWORD_IO]) ? "not" : "");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001003 else {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001004 printf("\tStandby timer values: spec'd by %s",
1005 (val[CAPAB_0] & STD_STBY) ? "standard" : "vendor");
Rob Landleya3e4f382006-04-29 16:06:31 +00001006 if ((like_std > 3) && ((val[CAPAB_1] & VALID) == VALID_VAL))
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001007 printf(", %s device specific minimum\n",
1008 (val[CAPAB_1] & MIN_STANDBY_TIMER) ? "with" : "no");
Glenn L McGrath07085852003-10-09 07:28:22 +00001009 else
Denis Vlasenko4daad902007-09-27 10:20:47 +00001010 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001011 }
1012 printf("\tR/W multiple sector transfer: ");
Rob Landleya3e4f382006-04-29 16:06:31 +00001013 if ((like_std < 3) && !(val[SECTOR_XFER_MAX] & SECTOR_XFER))
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001014 puts("not supported");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001015 else {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001016 printf("Max = %u\tCurrent = ", val[SECTOR_XFER_MAX] & SECTOR_XFER);
Rob Landleyadde7982006-05-16 15:32:30 +00001017 if (val[SECTOR_XFER_CUR] & MULTIPLE_SETTING_VALID)
1018 printf("%u\n", val[SECTOR_XFER_CUR] & SECTOR_XFER);
1019 else
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001020 puts("?");
Eric Andersen3443bd72003-07-22 07:30:36 +00001021 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001022 if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008)) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001023 /* We print out elsewhere whether the APM feature is enabled or
Denys Vlasenko60cb48c2013-01-14 15:57:44 +01001024 * not. If it's not enabled, let's not repeat the info; just print
1025 * nothing here. */
Glenn L McGrath07085852003-10-09 07:28:22 +00001026 printf("\tAdvancedPM level: ");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001027 if ((val[ADV_PWR] & 0xFF00) == 0x4000) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001028 uint8_t apm_level = val[ADV_PWR] & 0x00FF;
Eric Andersen3443bd72003-07-22 07:30:36 +00001029 printf("%u (0x%x)\n", apm_level, apm_level);
Glenn L McGrath07085852003-10-09 07:28:22 +00001030 }
1031 else
Eric Andersen3443bd72003-07-22 07:30:36 +00001032 printf("unknown setting (0x%04x)\n", val[ADV_PWR]);
Eric Andersen3443bd72003-07-22 07:30:36 +00001033 }
Rob Landleyadde7982006-05-16 15:32:30 +00001034 if (like_std > 5 && val[ACOUSTIC]) {
1035 printf("\tRecommended acoustic management value: %u, current value: %u\n",
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001036 (val[ACOUSTIC] >> 8) & 0x00ff,
1037 val[ACOUSTIC] & 0x00ff);
Eric Andersen3443bd72003-07-22 07:30:36 +00001038 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001039 } else {
Denys Vlasenko6830ade2013-01-15 13:58:01 +01001040 /* ATAPI */
Rob Landleyadde7982006-05-16 15:32:30 +00001041 if (eqpt != CDROM && (val[CAPAB_0] & SWRST_REQ))
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001042 puts("\tATA sw reset required");
Glenn L McGrath07085852003-10-09 07:28:22 +00001043
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001044 if (val[PKT_REL] || val[SVC_NBSY]) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001045 printf("\tOverlap support:");
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001046 if (val[PKT_REL])
1047 printf(" %uus to release bus.", val[PKT_REL]);
1048 if (val[SVC_NBSY])
1049 printf(" %uus to clear BSY after SERVICE cmd.",
1050 val[SVC_NBSY]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001051 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001052 }
1053 }
1054
1055 /* DMA stuff. Check that only one DMA mode is selected. */
1056 printf("\tDMA: ");
Rob Landleya3e4f382006-04-29 16:06:31 +00001057 if (!(val[CAPAB_0] & DMA_SUP))
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001058 puts("not supported");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001059 else {
Rob Landleyadde7982006-05-16 15:32:30 +00001060 if (val[DMA_MODE] && !val[SINGLE_DMA] && !val[MULTI_DMA])
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001061 printf(" sdma%u\n", (val[DMA_MODE] & MODE) >> 8);
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001062 if (val[SINGLE_DMA]) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001063 jj = val[SINGLE_DMA];
1064 kk = val[SINGLE_DMA] >> 8;
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001065 err_dma += mode_loop(jj, kk, 's', &have_mode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001066 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001067 if (val[MULTI_DMA]) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001068 jj = val[MULTI_DMA];
1069 kk = val[MULTI_DMA] >> 8;
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001070 err_dma += mode_loop(jj, kk, 'm', &have_mode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001071 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001072 if ((val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001073 jj = val[ULTRA_DMA];
1074 kk = val[ULTRA_DMA] >> 8;
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001075 err_dma += mode_loop(jj, kk, 'u', &have_mode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001076 }
Rob Landleyadde7982006-05-16 15:32:30 +00001077 if (err_dma || !have_mode) printf("(?)");
Denis Vlasenko4daad902007-09-27 10:20:47 +00001078 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001079
Rob Landleyadde7982006-05-16 15:32:30 +00001080 if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP))
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001081 puts("\t\tInterleaved DMA support");
Eric Andersen3443bd72003-07-22 07:30:36 +00001082
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001083 if ((val[WHATS_VALID] & OK_W64_70)
1084 && (val[DMA_TIME_MIN] || val[DMA_TIME_NORM])
1085 ) {
Rob Landleyadde7982006-05-16 15:32:30 +00001086 printf("\t\tCycle time:");
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001087 if (val[DMA_TIME_MIN]) printf(" min=%uns", val[DMA_TIME_MIN]);
1088 if (val[DMA_TIME_NORM]) printf(" recommended=%uns", val[DMA_TIME_NORM]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001089 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001090 }
1091 }
1092
1093 /* Programmed IO stuff */
1094 printf("\tPIO: ");
Tim Rikerc1ef7bd2006-01-25 00:08:53 +00001095 /* If a drive supports mode n (e.g. 3), it also supports all modes less
Eric Andersen3443bd72003-07-22 07:30:36 +00001096 * than n (e.g. 3, 2, 1 and 0). Print all the modes. */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001097 if ((val[WHATS_VALID] & OK_W64_70) && (val[ADV_PIO_MODES] & PIO_SUP)) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001098 jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007;
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001099 for (ii = 0; ii <= PIO_MODE_MAX; ii++) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001100 if (jj & 0x0001) printf("pio%d ", ii);
Eric Andersen3443bd72003-07-22 07:30:36 +00001101 jj >>=1;
1102 }
Denis Vlasenko4daad902007-09-27 10:20:47 +00001103 bb_putchar('\n');
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001104 } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) {
Rob Landleya3e4f382006-04-29 16:06:31 +00001105 for (ii = 0; ii <= val[PIO_MODE]>>8; ii++)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001106 printf("pio%d ", ii);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001107 bb_putchar('\n');
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001108 } else
Denis Vlasenko91303402007-10-30 19:36:54 +00001109 puts("unknown");
Glenn L McGrath07085852003-10-09 07:28:22 +00001110
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001111 if (val[WHATS_VALID] & OK_W64_70) {
1112 if (val[PIO_NO_FLOW] || val[PIO_FLOW]) {
Rob Landleyadde7982006-05-16 15:32:30 +00001113 printf("\t\tCycle time:");
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001114 if (val[PIO_NO_FLOW])
1115 printf(" no flow control=%uns", val[PIO_NO_FLOW]);
1116 if (val[PIO_FLOW])
1117 printf(" IORDY flow control=%uns", val[PIO_FLOW]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001118 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001119 }
1120 }
1121
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001122 if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001123 puts("Commands/features:\n"
1124 "\tEnabled\tSupported:");
Eric Andersen3443bd72003-07-22 07:30:36 +00001125 jj = val[CMDS_SUPP_0];
1126 kk = val[CMDS_EN_0];
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001127 for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++) {
Denis Vlasenkobfc3d822007-11-04 04:10:17 +00001128 const char *feat_str = nth_string(cmd_feat_str, ii);
Denis Vlasenko91303402007-10-30 19:36:54 +00001129 if ((jj & 0x8000) && (*feat_str != '\0')) {
1130 printf("\t%s\t%s\n", (kk & 0x8000) ? " *" : "", feat_str);
Eric Andersen3443bd72003-07-22 07:30:36 +00001131 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001132 jj <<= 1;
1133 kk <<= 1;
1134 if (ii % 16 == 15) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001135 jj = val[CMDS_SUPP_0+1+(ii/16)];
1136 kk = val[CMDS_EN_0+1+(ii/16)];
1137 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001138 if (ii == 31) {
Rob Landleya3e4f382006-04-29 16:06:31 +00001139 if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL)
Glenn L McGrath07085852003-10-09 07:28:22 +00001140 ii +=16;
Eric Andersen3443bd72003-07-22 07:30:36 +00001141 }
1142 }
1143 }
Rob Landleyadde7982006-05-16 15:32:30 +00001144 /* Removable Media Status Notification feature set */
Denis Vlasenko67b23e62006-10-03 21:00:06 +00001145 if ((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP)
Denis Vlasenkobfc3d822007-11-04 04:10:17 +00001146 printf("\t%s supported\n", nth_string(cmd_feat_str, 27));
Glenn L McGrath07085852003-10-09 07:28:22 +00001147
Eric Andersen3443bd72003-07-22 07:30:36 +00001148 /* security */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001149 if ((eqpt != CDROM) && (like_std > 3)
1150 && (val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME])
1151 ) {
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001152 puts("Security:");
Rob Landleyadde7982006-05-16 15:32:30 +00001153 if (val[PSWD_CODE] && (val[PSWD_CODE] != NOVAL_1))
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001154 printf("\tMaster password revision code = %u\n", val[PSWD_CODE]);
Eric Andersen3443bd72003-07-22 07:30:36 +00001155 jj = val[SECU_STATUS];
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001156 if (jj) {
1157 for (ii = 0; ii < NUM_SECU_STR; ii++) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001158 printf("\t%s\t%s\n",
1159 (!(jj & 0x0001)) ? "not" : "",
1160 nth_string(secu_str, ii));
Eric Andersen3443bd72003-07-22 07:30:36 +00001161 jj >>=1;
1162 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001163 if (val[SECU_STATUS] & SECU_ENABLED) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001164 printf("\tSecurity level %s\n",
1165 (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high");
Eric Andersen3443bd72003-07-22 07:30:36 +00001166 }
1167 }
1168 jj = val[ERASE_TIME] & ERASE_BITS;
1169 kk = val[ENH_ERASE_TIME] & ERASE_BITS;
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001170 if (jj || kk) {
Denis Vlasenko7d60fc12008-06-05 06:51:06 +00001171 bb_putchar('\t');
Rob Landleyade7f952006-05-25 18:53:06 +00001172 if (jj) printf("%umin for %sSECURITY ERASE UNIT. ", jj==ERASE_BITS ? 508 : jj<<1, "");
1173 if (kk) printf("%umin for %sSECURITY ERASE UNIT. ", kk==ERASE_BITS ? 508 : kk<<1, "ENHANCED ");
Denis Vlasenko4daad902007-09-27 10:20:47 +00001174 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001175 }
1176 }
1177
1178 /* reset result */
Rob Landleyadde7982006-05-16 15:32:30 +00001179 jj = val[HWRST_RSLT];
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001180 if ((jj & VALID) == VALID_VAL) {
Denis Vlasenko6bef3d12007-11-06 03:05:54 +00001181 oo = (jj & RST0);
1182 if (!oo)
Rob Landleyadde7982006-05-16 15:32:30 +00001183 jj >>= 8;
Rob Landleya3e4f382006-04-29 16:06:31 +00001184 if ((jj & DEV_DET) == JUMPER_VAL)
Rob Landleyadde7982006-05-16 15:32:30 +00001185 strng = " determined by the jumper";
Rob Landleya3e4f382006-04-29 16:06:31 +00001186 else if ((jj & DEV_DET) == CSEL_VAL)
Rob Landleyadde7982006-05-16 15:32:30 +00001187 strng = " determined by CSEL";
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00001188 else
Rob Landleyadde7982006-05-16 15:32:30 +00001189 strng = "";
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001190 printf("HW reset results:\n"
1191 "\tCBLID- %s Vih\n"
1192 "\tDevice num = %i%s\n",
1193 (val[HWRST_RSLT] & CBLID) ? "above" : "below",
1194 !(oo), strng);
Eric Andersen3443bd72003-07-22 07:30:36 +00001195 }
1196
1197 /* more stuff from std 5 */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001198 if ((like_std > 4) && (eqpt != CDROM)) {
1199 if (val[CFA_PWR_MODE] & VALID_W160) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001200 printf("CFA power mode 1:\n"
1201 "\t%s%s\n",
1202 (val[CFA_PWR_MODE] & PWR_MODE_OFF) ? "disabled" : "enabled",
1203 (val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : "");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001204 if (val[CFA_PWR_MODE] & MAX_AMPS)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001205 printf("\tMaximum current = %uma\n", val[CFA_PWR_MODE] & MAX_AMPS);
Eric Andersen3443bd72003-07-22 07:30:36 +00001206 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001207 if ((val[INTEGRITY] & SIG) == SIG_VAL) {
Rob Landleyadde7982006-05-16 15:32:30 +00001208 printf("Checksum: %scorrect\n", chksum ? "in" : "");
Eric Andersen3443bd72003-07-22 07:30:36 +00001209 }
1210 }
1211
Rob Landleyadde7982006-05-16 15:32:30 +00001212 exit(EXIT_SUCCESS);
Eric Andersen3443bd72003-07-22 07:30:36 +00001213}
1214#endif
1215
Eric Andersen3443bd72003-07-22 07:30:36 +00001216// Historically, if there was no HDIO_OBSOLETE_IDENTITY, then
1217// then the HDIO_GET_IDENTITY only returned 142 bytes.
1218// Otherwise, HDIO_OBSOLETE_IDENTITY returns 142 bytes,
1219// and HDIO_GET_IDENTITY returns 512 bytes. But the latest
1220// 2.5.xx kernels no longer define HDIO_OBSOLETE_IDENTITY
1221// (which they should, but they should just return -EINVAL).
1222//
1223// So.. we must now assume that HDIO_GET_IDENTITY returns 512 bytes.
1224// On a really old system, it will not, and we will be confused.
1225// Too bad, really.
1226
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001227#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
Denis Vlasenko91303402007-10-30 19:36:54 +00001228static const char cfg_str[] ALIGN1 =
Denis Vlasenko6b404432008-01-07 16:13:14 +00001229 """\0" "HardSect""\0" "SoftSect""\0" "NotMFM""\0"
1230 "HdSw>15uSec""\0" "SpinMotCtl""\0" "Fixed""\0" "Removeable""\0"
1231 "DTR<=5Mbs""\0" "DTR>5Mbs""\0" "DTR>10Mbs""\0" "RotSpdTol>.5%""\0"
1232 "dStbOff""\0" "TrkOff""\0" "FmtGapReq""\0" "nonMagnetic"
Denis Vlasenko91303402007-10-30 19:36:54 +00001233;
Eric Andersen3443bd72003-07-22 07:30:36 +00001234
Denis Vlasenko91303402007-10-30 19:36:54 +00001235static const char BuffType[] ALIGN1 =
1236 "unknown""\0" "1Sect""\0" "DualPort""\0" "DualPortCache"
1237;
Eric Andersen3443bd72003-07-22 07:30:36 +00001238
Denys Vlasenkoa7bb3c12009-10-08 12:28:08 +02001239static NOINLINE void dump_identity(const struct hd_driveid *id)
Eric Andersen3443bd72003-07-22 07:30:36 +00001240{
1241 int i;
Denis Vlasenko284d0fa2008-02-16 13:18:17 +00001242 const unsigned short *id_regs = (const void*) id;
Rob Landley0a7c8ef2006-02-22 17:01:00 +00001243
Glenn L McGrath07085852003-10-09 07:28:22 +00001244 printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n Config={",
1245 id->model, id->fw_rev, id->serial_no);
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001246 for (i = 0; i <= 15; i++) {
Rob Landleyade7f952006-05-25 18:53:06 +00001247 if (id->config & (1<<i))
Denis Vlasenkobfc3d822007-11-04 04:10:17 +00001248 printf(" %s", nth_string(cfg_str, i));
Rob Landleyadde7982006-05-16 15:32:30 +00001249 }
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001250 printf(" }\n RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n"
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001251 " BuffType=(%u) %s, BuffSize=%ukB, MaxMultSect=%u",
1252 id->cyls, id->heads, id->sectors, id->track_bytes,
1253 id->sector_bytes, id->ecc_bytes,
1254 id->buf_type,
1255 nth_string(BuffType, (id->buf_type > 3) ? 0 : id->buf_type),
1256 id->buf_size/2, id->max_multsect);
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001257 if (id->max_multsect) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001258 printf(", MultSect=");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001259 if (!(id->multsect_valid & 1))
Eric Andersen3443bd72003-07-22 07:30:36 +00001260 printf("?%u?", id->multsect);
1261 else if (id->multsect)
1262 printf("%u", id->multsect);
1263 else
1264 printf("off");
1265 }
Denis Vlasenko4daad902007-09-27 10:20:47 +00001266 bb_putchar('\n');
Rob Landleyade7f952006-05-25 18:53:06 +00001267
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001268 if (!(id->field_valid & 1))
Rob Landleyade7f952006-05-25 18:53:06 +00001269 printf(" (maybe):");
1270
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001271 printf(" CurCHS=%u/%u/%u, CurSects=%lu, LBA=%s", id->cur_cyls, id->cur_heads,
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001272 id->cur_sectors,
1273 (BB_BIG_ENDIAN) ?
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001274 (unsigned long)(id->cur_capacity0 << 16) | id->cur_capacity1 :
1275 (unsigned long)(id->cur_capacity1 << 16) | id->cur_capacity0,
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001276 ((id->capability&2) == 0) ? "no" : "yes");
Rob Landleyade7f952006-05-25 18:53:06 +00001277
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001278 if (id->capability & 2)
Rob Landleyade7f952006-05-25 18:53:06 +00001279 printf(", LBAsects=%u", id->lba_capacity);
1280
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001281 printf("\n IORDY=%s",
1282 (id->capability & 8)
1283 ? ((id->capability & 4) ? "on/off" : "yes")
1284 : "no");
Rob Landleyade7f952006-05-25 18:53:06 +00001285
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001286 if (((id->capability & 8) || (id->field_valid & 2)) && (id->field_valid & 2))
Rob Landleyade7f952006-05-25 18:53:06 +00001287 printf(", tPIO={min:%u,w/IORDY:%u}", id->eide_pio, id->eide_pio_iordy);
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00001288
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001289 if ((id->capability & 1) && (id->field_valid & 2))
Rob Landleyade7f952006-05-25 18:53:06 +00001290 printf(", tDMA={min:%u,rec:%u}", id->eide_dma_min, id->eide_dma_time);
1291
1292 printf("\n PIO modes: ");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001293 if (id->tPIO <= 5) {
Rob Landleyade7f952006-05-25 18:53:06 +00001294 printf("pio0 ");
1295 if (id->tPIO >= 1) printf("pio1 ");
1296 if (id->tPIO >= 2) printf("pio2 ");
Eric Andersen3443bd72003-07-22 07:30:36 +00001297 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001298 if (id->field_valid & 2) {
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001299 static const masks_labels_t pio_modes = {
1300 .masks = { 1, 2, ~3 },
1301 .labels = "pio3 \0""pio4 \0""pio? \0",
1302 };
1303 print_flags(&pio_modes, id->eide_pio_modes);
Rob Landleyade7f952006-05-25 18:53:06 +00001304 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001305 if (id->capability & 1) {
1306 if (id->dma_1word | id->dma_mword) {
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001307 static const int dma_wmode_masks[] = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 };
Rob Landleyade7f952006-05-25 18:53:06 +00001308 printf("\n DMA modes: ");
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001309 print_flags_separated(dma_wmode_masks,
1310 "*\0""sdma0 \0""*\0""sdma1 \0""*\0""sdma2 \0""*\0""sdma? \0",
1311 id->dma_1word, NULL);
1312 print_flags_separated(dma_wmode_masks,
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001313 "*\0""mdma0 \0""*\0""mdma1 \0""*\0""mdma2 \0""*\0""mdma? \0",
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001314 id->dma_mword, NULL);
Eric Andersen3443bd72003-07-22 07:30:36 +00001315 }
1316 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001317 if (((id->capability & 8) || (id->field_valid & 2)) && id->field_valid & 4) {
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001318 static const masks_labels_t ultra_modes1 = {
1319 .masks = { 0x100, 0x001, 0x200, 0x002, 0x400, 0x004 },
1320 .labels = "*\0""udma0 \0""*\0""udma1 \0""*\0""udma2 \0",
1321 };
Denis Vlasenko7049ff82008-06-25 09:53:17 +00001322
Rob Landleyade7f952006-05-25 18:53:06 +00001323 printf("\n UDMA modes: ");
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001324 print_flags(&ultra_modes1, id->dma_ultra);
Eric Andersen3443bd72003-07-22 07:30:36 +00001325#ifdef __NEW_HD_DRIVE_ID
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001326 if (id->hw_config & 0x2000) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001327#else /* !__NEW_HD_DRIVE_ID */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001328 if (id->word93 & 0x2000) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001329#endif /* __NEW_HD_DRIVE_ID */
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001330 static const masks_labels_t ultra_modes2 = {
1331 .masks = { 0x0800, 0x0008, 0x1000, 0x0010,
1332 0x2000, 0x0020, 0x4000, 0x0040,
1333 0x8000, 0x0080 },
1334 .labels = "*\0""udma3 \0""*\0""udma4 \0"
1335 "*\0""udma5 \0""*\0""udma6 \0"
1336 "*\0""udma7 \0"
1337 };
1338 print_flags(&ultra_modes2, id->dma_ultra);
Eric Andersen3443bd72003-07-22 07:30:36 +00001339 }
1340 }
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001341 printf("\n AdvancedPM=%s", (!(id_regs[83] & 8)) ? "no" : "yes");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001342 if (id_regs[83] & 8) {
1343 if (!(id_regs[86] & 8))
Glenn L McGrath07085852003-10-09 07:28:22 +00001344 printf(": disabled (255)");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001345 else if ((id_regs[91] & 0xFF00) != 0x4000)
Glenn L McGrath07085852003-10-09 07:28:22 +00001346 printf(": unknown setting");
1347 else
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001348 printf(": mode=0x%02X (%u)", id_regs[91] & 0xFF, id_regs[91] & 0xFF);
Glenn L McGrath07085852003-10-09 07:28:22 +00001349 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001350 if (id_regs[82] & 0x20)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001351 printf(" WriteCache=%s", (id_regs[85] & 0x20) ? "enabled" : "disabled");
Glenn L McGrath07085852003-10-09 07:28:22 +00001352#ifdef __NEW_HD_DRIVE_ID
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001353 if ((id->minor_rev_num && id->minor_rev_num <= 31)
1354 || (id->major_rev_num && id->minor_rev_num <= 31)
1355 ) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001356 printf("\n Drive conforms to: %s: ",
1357 (id->minor_rev_num <= 31) ? nth_string(minor_str, id->minor_rev_num) : "unknown");
1358 if (id->major_rev_num != 0x0000 /* NOVAL_0 */
1359 && id->major_rev_num != 0xFFFF /* NOVAL_1 */
1360 ) {
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001361 for (i = 0; i <= 15; i++) {
Rob Landleyadde7982006-05-16 15:32:30 +00001362 if (id->major_rev_num & (1<<i))
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001363 printf(" ATA/ATAPI-%u", i);
Rob Landleyadde7982006-05-16 15:32:30 +00001364 }
Glenn L McGrath07085852003-10-09 07:28:22 +00001365 }
1366 }
Eric Andersen3443bd72003-07-22 07:30:36 +00001367#endif /* __NEW_HD_DRIVE_ID */
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001368 puts("\n\n * current active mode\n");
Eric Andersen3443bd72003-07-22 07:30:36 +00001369}
1370#endif
1371
Denis Vlasenko892536f2007-09-27 10:23:34 +00001372static void flush_buffer_cache(/*int fd*/ void)
Eric Andersen3443bd72003-07-22 07:30:36 +00001373{
Rob Landleya3e4f382006-04-29 16:06:31 +00001374 fsync(fd); /* flush buffers */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001375 ioctl_or_warn(fd, BLKFLSBUF, NULL); /* do it again, big time */
Eric Andersen3443bd72003-07-22 07:30:36 +00001376#ifdef HDIO_DRIVE_CMD
Glenn L McGrath07085852003-10-09 07:28:22 +00001377 sleep(1);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001378 if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) { /* await completion */
1379 if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */
1380 bb_perror_msg("HDIO_DRIVE_CMD");
1381 else
1382 bb_perror_msg("ioctl %#x failed", HDIO_DRIVE_CMD);
1383 }
Eric Andersen3443bd72003-07-22 07:30:36 +00001384#endif
1385}
1386
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001387static void seek_to_zero(/*int fd*/ void)
Eric Andersen3443bd72003-07-22 07:30:36 +00001388{
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001389 xlseek(fd, (off_t) 0, SEEK_SET);
Eric Andersen3443bd72003-07-22 07:30:36 +00001390}
1391
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001392static void read_big_block(/*int fd,*/ char *buf)
Eric Andersen3443bd72003-07-22 07:30:36 +00001393{
Rob Landleyadde7982006-05-16 15:32:30 +00001394 int i;
1395
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001396 xread(fd, buf, TIMING_BUF_BYTES);
Eric Andersen3443bd72003-07-22 07:30:36 +00001397 /* access all sectors of buf to ensure the read fully completed */
1398 for (i = 0; i < TIMING_BUF_BYTES; i += 512)
1399 buf[i] &= 1;
Eric Andersen3443bd72003-07-22 07:30:36 +00001400}
1401
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001402static unsigned dev_size_mb(/*int fd*/ void)
Rob Landleyadde7982006-05-16 15:32:30 +00001403{
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001404 union {
1405 unsigned long long blksize64;
1406 unsigned blksize32;
1407 } u;
Rob Landleyadde7982006-05-16 15:32:30 +00001408
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001409 if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // bytes
1410 u.blksize64 /= (1024 * 1024);
1411 } else {
1412 xioctl(fd, BLKGETSIZE, &u.blksize32); // sectors
1413 u.blksize64 = u.blksize32 / (2 * 1024);
Rob Landleyadde7982006-05-16 15:32:30 +00001414 }
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001415 if (u.blksize64 > UINT_MAX)
1416 return UINT_MAX;
1417 return u.blksize64;
Rob Landleyadde7982006-05-16 15:32:30 +00001418}
Eric Andersen50af12d2003-08-06 08:47:59 +00001419
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001420static void print_timing(unsigned m, unsigned elapsed_us)
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001421{
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001422 unsigned sec = elapsed_us / 1000000;
1423 unsigned hs = (elapsed_us % 1000000) / 10000;
1424
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001425 printf("%5u MB in %u.%02u seconds = %u kB/s\n",
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001426 m, sec, hs,
Denis Vlasenko0afdfdf2007-09-28 13:41:41 +00001427 /* "| 1" prevents div-by-0 */
1428 (unsigned) ((unsigned long long)m * (1024 * 1000000) / (elapsed_us | 1))
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001429 // ~= (m * 1024) / (elapsed_us / 1000000)
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001430 // = kb / elapsed_sec
1431 );
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001432}
1433
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001434static void do_time(int cache /*,int fd*/)
1435/* cache=1: time cache: repeatedly read N MB at offset 0
1436 * cache=0: time device: linear read, starting at offset 0
1437 */
Eric Andersen3443bd72003-07-22 07:30:36 +00001438{
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001439 unsigned max_iterations, iterations;
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001440 unsigned start; /* doesn't need to be long long */
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001441 unsigned elapsed, elapsed2;
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001442 unsigned total_MB;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001443 char *buf = xmalloc(TIMING_BUF_BYTES);
Rob Landley4ae2f512006-05-19 17:24:26 +00001444
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001445 if (mlock(buf, TIMING_BUF_BYTES))
1446 bb_perror_msg_and_die("mlock");
Rob Landleyadde7982006-05-16 15:32:30 +00001447
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001448 /* Clear out the device request queues & give them time to complete.
1449 * NB: *small* delay. User is expected to have a clue and to not run
1450 * heavy io in parallel with measurements. */
Rob Landleyadde7982006-05-16 15:32:30 +00001451 sync();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001452 sleep(1);
1453 if (cache) { /* Time cache */
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001454 seek_to_zero();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001455 read_big_block(buf);
1456 printf("Timing buffer-cache reads: ");
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001457 } else { /* Time device */
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001458 printf("Timing buffered disk reads:");
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001459 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +01001460 fflush_all();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001461
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001462 /* Now do the timing */
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001463 iterations = 0;
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001464 /* Max time to run (small for cache, avoids getting
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001465 * huge total_MB which can overlow unsigned type) */
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001466 elapsed2 = 510000; /* cache */
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001467 max_iterations = UINT_MAX;
1468 if (!cache) {
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001469 elapsed2 = 3000000; /* not cache */
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001470 /* Don't want to read past the end! */
1471 max_iterations = dev_size_mb() / TIMING_BUF_MB;
1472 }
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001473 start = monotonic_us();
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001474 do {
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001475 if (cache)
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001476 seek_to_zero();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001477 read_big_block(buf);
1478 elapsed = (unsigned)monotonic_us() - start;
1479 ++iterations;
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001480 } while (elapsed < elapsed2 && iterations < max_iterations);
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001481 total_MB = iterations * TIMING_BUF_MB;
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001482 //printf(" elapsed:%u iterations:%u ", elapsed, iterations);
1483 if (cache) {
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001484 /* Cache: remove lseek() and monotonic_us() overheads
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001485 * from elapsed */
1486 start = monotonic_us();
Rob Landleyadde7982006-05-16 15:32:30 +00001487 do {
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001488 seek_to_zero();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001489 elapsed2 = (unsigned)monotonic_us() - start;
Rob Landleyadde7982006-05-16 15:32:30 +00001490 } while (--iterations);
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001491 //printf(" elapsed2:%u ", elapsed2);
Rob Landleyadde7982006-05-16 15:32:30 +00001492 elapsed -= elapsed2;
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001493 total_MB *= 2; // BUFCACHE_FACTOR (why?)
Denis Vlasenko892536f2007-09-27 10:23:34 +00001494 flush_buffer_cache();
Glenn L McGrath07085852003-10-09 07:28:22 +00001495 }
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001496 print_timing(total_MB, elapsed);
Rob Landley4ae2f512006-05-19 17:24:26 +00001497 munlock(buf, TIMING_BUF_BYTES);
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001498 free(buf);
Eric Andersen3443bd72003-07-22 07:30:36 +00001499}
1500
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001501#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001502static void bus_state_value(unsigned value)
Eric Andersen3443bd72003-07-22 07:30:36 +00001503{
Rob Landleyadde7982006-05-16 15:32:30 +00001504 if (value == BUSSTATE_ON)
1505 on_off(1);
1506 else if (value == BUSSTATE_OFF)
1507 on_off(0);
1508 else if (value == BUSSTATE_TRISTATE)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001509 puts(" (tristate)");
Rob Landleyadde7982006-05-16 15:32:30 +00001510 else
Denys Vlasenko327f5502013-11-29 16:45:45 +01001511 printf(" (unknown: %u)\n", value);
Eric Andersen3443bd72003-07-22 07:30:36 +00001512}
1513#endif
1514
1515#ifdef HDIO_DRIVE_CMD
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001516static void interpret_standby(uint8_t standby)
Eric Andersen3443bd72003-07-22 07:30:36 +00001517{
Rob Landley403777f2006-08-03 20:22:37 +00001518 printf(" (");
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001519 if (standby == 0) {
Rob Landleyadde7982006-05-16 15:32:30 +00001520 printf("off");
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001521 } else if (standby <= 240 || standby == 252 || standby == 255) {
1522 /* standby is in 5 sec units */
Denys Vlasenko2b132e52009-05-20 23:21:42 +02001523 unsigned t = standby * 5;
1524 printf("%u minutes %u seconds", t / 60, t % 60);
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001525 } else if (standby <= 251) {
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001526 unsigned t = (standby - 240); /* t is in 30 min units */;
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001527 printf("%u.%c hours", t / 2, (t & 1) ? '5' : '0');
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001528 }
1529 if (standby == 253)
1530 printf("vendor-specific");
1531 if (standby == 254)
1532 printf("reserved");
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001533 puts(")");
Eric Andersen3443bd72003-07-22 07:30:36 +00001534}
1535
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001536static const uint8_t xfermode_val[] ALIGN1 = {
1537 8, 9, 10, 11, 12, 13, 14, 15,
1538 16, 17, 18, 19, 20, 21, 22, 23,
1539 32, 33, 34, 35, 36, 37, 38, 39,
1540 64, 65, 66, 67, 68, 69, 70, 71
1541};
1542/* NB: we save size by _not_ storing terninating NUL! */
1543static const char xfermode_name[][5] ALIGN1 = {
1544 "pio0", "pio1", "pio2", "pio3", "pio4", "pio5", "pio6", "pio7",
1545 "sdma0","sdma1","sdma2","sdma3","sdma4","sdma5","sdma6","sdma7",
1546 "mdma0","mdma1","mdma2","mdma3","mdma4","mdma5","mdma6","mdma7",
1547 "udma0","udma1","udma2","udma3","udma4","udma5","udma6","udma7"
Eric Andersen3443bd72003-07-22 07:30:36 +00001548};
1549
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001550static int translate_xfermode(const char *name)
Eric Andersen3443bd72003-07-22 07:30:36 +00001551{
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00001552 int val;
1553 unsigned i;
Eric Andersen3443bd72003-07-22 07:30:36 +00001554
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001555 for (i = 0; i < ARRAY_SIZE(xfermode_val); i++) {
1556 if (!strncmp(name, xfermode_name[i], 5))
1557 if (strlen(name) <= 5)
1558 return xfermode_val[i];
Glenn L McGrath07085852003-10-09 07:28:22 +00001559 }
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001560 /* Negative numbers are invalid and are caught later */
1561 val = bb_strtoi(name, NULL, 10);
1562 if (!errno)
Glenn L McGrath07085852003-10-09 07:28:22 +00001563 return val;
Glenn L McGrath07085852003-10-09 07:28:22 +00001564 return -1;
Eric Andersen3443bd72003-07-22 07:30:36 +00001565}
1566
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001567static void interpret_xfermode(unsigned xfermode)
Eric Andersen3443bd72003-07-22 07:30:36 +00001568{
1569 printf(" (");
Rob Landleyadde7982006-05-16 15:32:30 +00001570 if (xfermode == 0)
1571 printf("default PIO mode");
1572 else if (xfermode == 1)
1573 printf("default PIO mode, disable IORDY");
1574 else if (xfermode >= 8 && xfermode <= 15)
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001575 printf("PIO flow control mode%u", xfermode - 8);
Rob Landleyadde7982006-05-16 15:32:30 +00001576 else if (xfermode >= 16 && xfermode <= 23)
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001577 printf("singleword DMA mode%u", xfermode - 16);
Rob Landleyadde7982006-05-16 15:32:30 +00001578 else if (xfermode >= 32 && xfermode <= 39)
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001579 printf("multiword DMA mode%u", xfermode - 32);
Rob Landleyadde7982006-05-16 15:32:30 +00001580 else if (xfermode >= 64 && xfermode <= 71)
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001581 printf("UltraDMA mode%u", xfermode - 64);
Rob Landleyadde7982006-05-16 15:32:30 +00001582 else
Denis Vlasenko91303402007-10-30 19:36:54 +00001583 printf("unknown");
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001584 puts(")");
Eric Andersen3443bd72003-07-22 07:30:36 +00001585}
1586#endif /* HDIO_DRIVE_CMD */
1587
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001588static void print_flag(int flag, const char *s, unsigned long value)
Rob Landleyadde7982006-05-16 15:32:30 +00001589{
Denis Vlasenko67b23e62006-10-03 21:00:06 +00001590 if (flag)
Denys Vlasenko327f5502013-11-29 16:45:45 +01001591 printf(" setting %s to %lu\n", s, value);
Rob Landleyadde7982006-05-16 15:32:30 +00001592}
1593
Rob Landleya3e4f382006-04-29 16:06:31 +00001594static void process_dev(char *devname)
Eric Andersen3443bd72003-07-22 07:30:36 +00001595{
Denis Vlasenko892536f2007-09-27 10:23:34 +00001596 /*int fd;*/
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001597 long parm, multcount;
Eric Andersen3443bd72003-07-22 07:30:36 +00001598#ifndef HDIO_DRIVE_CMD
1599 int force_operation = 0;
1600#endif
Rob Landley39cf6452006-05-05 16:52:28 +00001601 /* Please restore args[n] to these values after each ioctl
1602 except for args[2] */
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001603 unsigned char args[4] = { WIN_SETFEATURES, 0, 0, 0 };
Rob Landleyadde7982006-05-16 15:32:30 +00001604 const char *fmt = " %s\t= %2ld";
Rob Landleye5b281f2006-04-29 15:49:18 +00001605
Bernhard Reutner-Fischera4830872009-10-26 23:27:08 +01001606 /*fd = xopen_nonblocking(devname);*/
1607 xmove_fd(xopen_nonblocking(devname), fd);
Rob Landleyade7f952006-05-25 18:53:06 +00001608 printf("\n%s:\n", devname);
Eric Andersen3443bd72003-07-22 07:30:36 +00001609
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001610 if (getset_readahead == IS_SET) {
1611 print_flag(getset_readahead, "fs readahead", Xreadahead);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001612 ioctl_or_warn(fd, BLKRASET, (int *)Xreadahead);
Eric Andersen3443bd72003-07-22 07:30:36 +00001613 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001614#if ENABLE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
1615 if (unregister_hwif) {
Rob Landley20deab02006-05-07 23:34:15 +00001616 printf(" attempting to unregister hwif#%lu\n", hwif);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001617 ioctl_or_warn(fd, HDIO_UNREGISTER_HWIF, (int *)(unsigned long)hwif);
Eric Andersen3443bd72003-07-22 07:30:36 +00001618 }
1619#endif
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001620#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001621 if (scan_hwif == IS_SET) {
Rob Landley20deab02006-05-07 23:34:15 +00001622 printf(" attempting to scan hwif (0x%lx, 0x%lx, %lu)\n", hwif_data, hwif_ctrl, hwif_irq);
Eric Andersen3443bd72003-07-22 07:30:36 +00001623 args[0] = hwif_data;
1624 args[1] = hwif_ctrl;
1625 args[2] = hwif_irq;
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001626 ioctl_or_warn(fd, HDIO_SCAN_HWIF, args);
Rob Landley39cf6452006-05-05 16:52:28 +00001627 args[0] = WIN_SETFEATURES;
1628 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001629 }
1630#endif
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001631 if (set_piomode) {
1632 if (noisy_piomode) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001633 printf(" attempting to ");
Eric Andersen3443bd72003-07-22 07:30:36 +00001634 if (piomode == 255)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001635 puts("auto-tune PIO mode");
Eric Andersen3443bd72003-07-22 07:30:36 +00001636 else if (piomode < 100)
Glenn L McGrath07085852003-10-09 07:28:22 +00001637 printf("set PIO mode to %d\n", piomode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001638 else if (piomode < 200)
Glenn L McGrath07085852003-10-09 07:28:22 +00001639 printf("set MDMA mode to %d\n", (piomode-100));
Eric Andersen3443bd72003-07-22 07:30:36 +00001640 else
Glenn L McGrath07085852003-10-09 07:28:22 +00001641 printf("set UDMA mode to %d\n", (piomode-200));
Eric Andersen3443bd72003-07-22 07:30:36 +00001642 }
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001643 ioctl_or_warn(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001644 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001645 if (getset_io32bit == IS_SET) {
1646 print_flag(getset_io32bit, "32-bit IO_support flag", io32bit);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001647 ioctl_or_warn(fd, HDIO_SET_32BIT, (int *)io32bit);
Eric Andersen3443bd72003-07-22 07:30:36 +00001648 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001649 if (getset_mult == IS_SET) {
1650 print_flag(getset_mult, "multcount", mult);
Rob Landleyade7f952006-05-25 18:53:06 +00001651#ifdef HDIO_DRIVE_CMD
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001652 ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult);
Rob Landleyade7f952006-05-25 18:53:06 +00001653#else
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001654 force_operation |= (!ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult));
Eric Andersen3443bd72003-07-22 07:30:36 +00001655#endif
1656 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001657 if (getset_readonly == IS_SET) {
1658 print_flag_on_off(getset_readonly, "readonly", readonly);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001659 ioctl_or_warn(fd, BLKROSET, &readonly);
Eric Andersen3443bd72003-07-22 07:30:36 +00001660 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001661 if (getset_unmask == IS_SET) {
1662 print_flag_on_off(getset_unmask, "unmaskirq", unmask);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001663 ioctl_or_warn(fd, HDIO_SET_UNMASKINTR, (int *)unmask);
Eric Andersen3443bd72003-07-22 07:30:36 +00001664 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001665#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001666 if (getset_dma == IS_SET) {
1667 print_flag_on_off(getset_dma, "using_dma", dma);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001668 ioctl_or_warn(fd, HDIO_SET_DMA, (int *)dma);
Eric Andersen3443bd72003-07-22 07:30:36 +00001669 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001670#endif /* FEATURE_HDPARM_HDIO_GETSET_DMA */
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001671#ifdef HDIO_SET_QDMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001672 if (getset_dma_q == IS_SET) {
1673 print_flag_on_off(getset_dma_q, "DMA queue_depth", dma_q);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001674 ioctl_or_warn(fd, HDIO_SET_QDMA, (int *)dma_q);
Eric Andersen3443bd72003-07-22 07:30:36 +00001675 }
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001676#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001677 if (getset_nowerr == IS_SET) {
1678 print_flag_on_off(getset_nowerr, "nowerr", nowerr);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001679 ioctl_or_warn(fd, HDIO_SET_NOWERR, (int *)nowerr);
Eric Andersen3443bd72003-07-22 07:30:36 +00001680 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001681 if (getset_keep == IS_SET) {
1682 print_flag_on_off(getset_keep, "keep_settings", keep);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001683 ioctl_or_warn(fd, HDIO_SET_KEEPSETTINGS, (int *)keep);
Eric Andersen3443bd72003-07-22 07:30:36 +00001684 }
1685#ifdef HDIO_DRIVE_CMD
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001686 if (getset_doorlock == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001687 args[0] = doorlock ? WIN_DOORLOCK : WIN_DOORUNLOCK;
Rob Landley39cf6452006-05-05 16:52:28 +00001688 args[2] = 0;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001689 print_flag_on_off(getset_doorlock, "drive doorlock", doorlock);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001690 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001691 args[0] = WIN_SETFEATURES;
Eric Andersen3443bd72003-07-22 07:30:36 +00001692 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001693 if (getset_dkeep == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001694 /* lock/unlock the drive's "feature" settings */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001695 print_flag_on_off(getset_dkeep, "drive keep features", dkeep);
Eric Andersen3443bd72003-07-22 07:30:36 +00001696 args[2] = dkeep ? 0x66 : 0xcc;
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001697 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001698 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001699 if (getset_defects == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001700 args[2] = defects ? 0x04 : 0x84;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001701 print_flag(getset_defects, "drive defect-mgmt", defects);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001702 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001703 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001704 if (getset_prefetch == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001705 args[1] = prefetch;
Rob Landleye5b281f2006-04-29 15:49:18 +00001706 args[2] = 0xab;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001707 print_flag(getset_prefetch, "drive prefetch", prefetch);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001708 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001709 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001710 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001711 if (set_xfermode) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001712 args[1] = xfermode_requested;
Rob Landleye5b281f2006-04-29 15:49:18 +00001713 args[2] = 3;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001714 print_flag(1, "xfermode", xfermode_requested);
1715 interpret_xfermode(xfermode_requested);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001716 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001717 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001718 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001719 if (getset_lookahead == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001720 args[2] = lookahead ? 0xaa : 0x55;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001721 print_flag_on_off(getset_lookahead, "drive read-lookahead", lookahead);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001722 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001723 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001724 if (getset_apmmode == IS_SET) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001725 /* feature register */
1726 args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */;
Rob Landleyadde7982006-05-16 15:32:30 +00001727 args[1] = apmmode; /* sector count register 1-255 */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001728 printf(" setting APM level to %s 0x%02lX (%ld)\n",
1729 (apmmode == 255) ? "disabled" : "",
1730 apmmode, apmmode);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001731 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001732 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001733 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001734 if (getset_wcache == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001735#ifdef DO_FLUSHCACHE
1736#ifndef WIN_FLUSHCACHE
1737#define WIN_FLUSHCACHE 0xe7
1738#endif
Eric Andersen3443bd72003-07-22 07:30:36 +00001739#endif /* DO_FLUSHCACHE */
Eric Andersen3443bd72003-07-22 07:30:36 +00001740 args[2] = wcache ? 0x02 : 0x82;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001741 print_flag_on_off(getset_wcache, "drive write-caching", wcache);
Eric Andersen3443bd72003-07-22 07:30:36 +00001742#ifdef DO_FLUSHCACHE
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001743 if (!wcache)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001744 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache);
Eric Andersen3443bd72003-07-22 07:30:36 +00001745#endif /* DO_FLUSHCACHE */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001746 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001747#ifdef DO_FLUSHCACHE
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001748 if (!wcache)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001749 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache);
Eric Andersen3443bd72003-07-22 07:30:36 +00001750#endif /* DO_FLUSHCACHE */
1751 }
Rob Landley39cf6452006-05-05 16:52:28 +00001752
1753 /* In code below, we do not preserve args[0], but the rest
1754 is preserved, including args[2] */
1755 args[2] = 0;
1756
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001757 if (set_standbynow) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001758#ifndef WIN_STANDBYNOW1
1759#define WIN_STANDBYNOW1 0xE0
1760#endif
1761#ifndef WIN_STANDBYNOW2
1762#define WIN_STANDBYNOW2 0x94
1763#endif
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001764 puts(" issuing standby command");
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001765 args[0] = WIN_STANDBYNOW1;
Denis Vlasenko892536f2007-09-27 10:23:34 +00001766 ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2);
Eric Andersen3443bd72003-07-22 07:30:36 +00001767 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001768 if (set_sleepnow) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001769#ifndef WIN_SLEEPNOW1
1770#define WIN_SLEEPNOW1 0xE6
1771#endif
1772#ifndef WIN_SLEEPNOW2
1773#define WIN_SLEEPNOW2 0x99
1774#endif
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001775 puts(" issuing sleep command");
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001776 args[0] = WIN_SLEEPNOW1;
Denis Vlasenko892536f2007-09-27 10:23:34 +00001777 ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2);
Eric Andersen3443bd72003-07-22 07:30:36 +00001778 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001779 if (set_seagate) {
Rob Landleye5b281f2006-04-29 15:49:18 +00001780 args[0] = 0xfb;
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001781 puts(" disabling Seagate auto powersaving mode");
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001782 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001783 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001784 if (getset_standby == IS_SET) {
Rob Landleye5b281f2006-04-29 15:49:18 +00001785 args[0] = WIN_SETIDLE1;
1786 args[1] = standby_requested;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001787 print_flag(1, "standby", standby_requested);
1788 interpret_standby(standby_requested);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001789 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001790 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001791 }
1792#else /* HDIO_DRIVE_CMD */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001793 if (force_operation) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001794 char buf[512];
Denis Vlasenko892536f2007-09-27 10:23:34 +00001795 flush_buffer_cache();
Eric Andersen3443bd72003-07-22 07:30:36 +00001796 if (-1 == read(fd, buf, sizeof(buf)))
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001797 bb_perror_msg("read of 512 bytes failed");
Eric Andersen3443bd72003-07-22 07:30:36 +00001798 }
Denys Vlasenkoe4dcba12010-10-28 18:57:19 +02001799#endif /* HDIO_DRIVE_CMD */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001800 if (getset_mult || get_identity) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001801 multcount = -1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001802 if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001803 /* To be coherent with ioctl_or_warn. */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001804 if (getset_mult && ENABLE_IOCTL_HEX2STR_ERROR)
Eric Andersen06d4ec22004-03-19 10:53:52 +00001805 bb_perror_msg("HDIO_GET_MULTCOUNT");
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001806 else
1807 bb_perror_msg("ioctl %#x failed", HDIO_GET_MULTCOUNT);
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001808 } else if (getset_mult) {
Rob Landleyadde7982006-05-16 15:32:30 +00001809 printf(fmt, "multcount", multcount);
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001810 on_off(multcount != 0);
Eric Andersen3443bd72003-07-22 07:30:36 +00001811 }
1812 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001813 if (getset_io32bit) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001814 if (!ioctl_or_warn(fd, HDIO_GET_32BIT, &parm)) {
Rob Landleyadde7982006-05-16 15:32:30 +00001815 printf(" IO_support\t=%3ld (", parm);
1816 if (parm == 0)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001817 puts("default 16-bit)");
Rob Landleyadde7982006-05-16 15:32:30 +00001818 else if (parm == 2)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001819 puts("16-bit)");
Rob Landleyadde7982006-05-16 15:32:30 +00001820 else if (parm == 1)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001821 puts("32-bit)");
Rob Landleyadde7982006-05-16 15:32:30 +00001822 else if (parm == 3)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001823 puts("32-bit w/sync)");
Rob Landleyadde7982006-05-16 15:32:30 +00001824 else if (parm == 8)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001825 puts("Request-Queue-Bypass)");
Rob Landleyadde7982006-05-16 15:32:30 +00001826 else
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001827 puts("\?\?\?)");
Eric Andersen3443bd72003-07-22 07:30:36 +00001828 }
1829 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001830 if (getset_unmask) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001831 if (!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001832 print_value_on_off("unmaskirq", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001833 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001834#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001835 if (getset_dma) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001836 if (!ioctl_or_warn(fd, HDIO_GET_DMA, &parm)) {
Rob Landleyadde7982006-05-16 15:32:30 +00001837 printf(fmt, "using_dma", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001838 if (parm == 8)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001839 puts(" (DMA-Assisted-PIO)");
Eric Andersen3443bd72003-07-22 07:30:36 +00001840 else
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001841 on_off(parm != 0);
Eric Andersen3443bd72003-07-22 07:30:36 +00001842 }
1843 }
1844#endif
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001845#ifdef HDIO_GET_QDMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001846 if (getset_dma_q) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001847 if (!ioctl_or_warn(fd, HDIO_GET_QDMA, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001848 print_value_on_off("queue_depth", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001849 }
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001850#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001851 if (getset_keep) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001852 if (!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001853 print_value_on_off("keepsettings", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001854 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001855 if (getset_nowerr) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001856 if (!ioctl_or_warn(fd, HDIO_GET_NOWERR, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001857 print_value_on_off("nowerr", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001858 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001859 if (getset_readonly) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001860 if (!ioctl_or_warn(fd, BLKROGET, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001861 print_value_on_off("readonly", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001862 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001863 if (getset_readahead) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001864 if (!ioctl_or_warn(fd, BLKRAGET, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001865 print_value_on_off("readahead", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001866 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001867 if (get_geom) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001868 if (!ioctl_or_warn(fd, BLKGETSIZE, &parm)) {
Rob Landley2584e9b2006-05-03 20:00:00 +00001869 struct hd_geometry g;
1870
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001871 if (!ioctl_or_warn(fd, HDIO_GETGEO, &g))
Rob Landleyadde7982006-05-16 15:32:30 +00001872 printf(" geometry\t= %u/%u/%u, sectors = %ld, start = %ld\n",
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001873 g.cylinders, g.heads, g.sectors, parm, g.start);
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001874 }
Eric Andersen3443bd72003-07-22 07:30:36 +00001875 }
1876#ifdef HDIO_DRIVE_CMD
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001877 if (get_powermode) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001878#ifndef WIN_CHECKPOWERMODE1
1879#define WIN_CHECKPOWERMODE1 0xE5
1880#endif
1881#ifndef WIN_CHECKPOWERMODE2
1882#define WIN_CHECKPOWERMODE2 0x98
1883#endif
Eric Andersen3443bd72003-07-22 07:30:36 +00001884 const char *state;
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001885
Rob Landleye5b281f2006-04-29 15:49:18 +00001886 args[0] = WIN_CHECKPOWERMODE1;
Denis Vlasenko892536f2007-09-27 10:23:34 +00001887 if (ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2)) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001888 if (errno != EIO || args[0] != 0 || args[1] != 0)
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001889 state = "unknown";
Eric Andersen3443bd72003-07-22 07:30:36 +00001890 else
1891 state = "sleeping";
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001892 } else
Glenn L McGrath07085852003-10-09 07:28:22 +00001893 state = (args[2] == 255) ? "active/idle" : "standby";
Rob Landley39cf6452006-05-05 16:52:28 +00001894 args[1] = args[2] = 0;
Glenn L McGrath07085852003-10-09 07:28:22 +00001895
Eric Andersen3443bd72003-07-22 07:30:36 +00001896 printf(" drive state is: %s\n", state);
1897 }
1898#endif
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001899#if ENABLE_FEATURE_HDPARM_HDIO_DRIVE_RESET
1900 if (perform_reset) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001901 ioctl_or_warn(fd, HDIO_DRIVE_RESET, NULL);
Eric Andersen3443bd72003-07-22 07:30:36 +00001902 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001903#endif /* FEATURE_HDPARM_HDIO_DRIVE_RESET */
1904#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
1905 if (perform_tristate) {
Rob Landleye5b281f2006-04-29 15:49:18 +00001906 args[0] = 0;
1907 args[1] = tristate;
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001908 ioctl_or_warn(fd, HDIO_TRISTATE_HWIF, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001909 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001910#endif /* FEATURE_HDPARM_HDIO_TRISTATE_HWIF */
1911#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
1912 if (get_identity) {
Denis Vlasenko7c282a22007-03-28 00:14:54 +00001913 struct hd_driveid id;
Eric Andersen3443bd72003-07-22 07:30:36 +00001914
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001915 if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) {
1916 if (multcount != -1) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001917 id.multsect = multcount;
1918 id.multsect_valid |= 1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001919 } else
Eric Andersen3443bd72003-07-22 07:30:36 +00001920 id.multsect_valid &= ~1;
1921 dump_identity(&id);
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001922 } else if (errno == -ENOMSG)
Denys Vlasenkod60752f2015-10-07 22:42:45 +02001923 puts(" no identification info available");
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001924 else if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */
Denis Vlasenko49a128a2007-07-17 21:42:59 +00001925 bb_perror_msg("HDIO_GET_IDENTITY");
Eric Andersen3443bd72003-07-22 07:30:36 +00001926 else
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001927 bb_perror_msg("ioctl %#x failed", HDIO_GET_IDENTITY);
Eric Andersen3443bd72003-07-22 07:30:36 +00001928 }
Glenn L McGrath07085852003-10-09 07:28:22 +00001929
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001930 if (get_IDentity) {
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001931 unsigned char args1[4+512]; /* = { ... } will eat 0.5k of rodata! */
Glenn L McGrath07085852003-10-09 07:28:22 +00001932
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001933 memset(args1, 0, sizeof(args1));
1934 args1[0] = WIN_IDENTIFY;
1935 args1[3] = 1;
Denis Vlasenko892536f2007-09-27 10:23:34 +00001936 if (!ioctl_alt_or_warn(HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY))
Rob Landley0753f4a2006-06-07 00:27:25 +00001937 identify((void *)(args1 + 4));
Eric Andersen3443bd72003-07-22 07:30:36 +00001938 }
1939#endif
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001940#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001941 if (getset_busstate == IS_SET) {
1942 print_flag(1, "bus state", busstate);
1943 bus_state_value(busstate);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001944 ioctl_or_warn(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate);
Eric Andersen3443bd72003-07-22 07:30:36 +00001945 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001946 if (getset_busstate) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001947 if (!ioctl_or_warn(fd, HDIO_GET_BUSSTATE, &parm)) {
Rob Landleyadde7982006-05-16 15:32:30 +00001948 printf(fmt, "bus state", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001949 bus_state_value(parm);
1950 }
1951 }
1952#endif
Glenn L McGrath07085852003-10-09 07:28:22 +00001953 if (reread_partn)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001954 ioctl_or_warn(fd, BLKRRPART, NULL);
Glenn L McGrath07085852003-10-09 07:28:22 +00001955
Eric Andersen3443bd72003-07-22 07:30:36 +00001956 if (do_ctimings)
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001957 do_time(1 /*,fd*/); /* time cache */
Eric Andersen3443bd72003-07-22 07:30:36 +00001958 if (do_timings)
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001959 do_time(0 /*,fd*/); /* time device */
Eric Andersen3443bd72003-07-22 07:30:36 +00001960 if (do_flush)
Denis Vlasenko892536f2007-09-27 10:23:34 +00001961 flush_buffer_cache();
Rob Landleya3e4f382006-04-29 16:06:31 +00001962 close(fd);
Eric Andersen3443bd72003-07-22 07:30:36 +00001963}
1964
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001965#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
Rob Landleya3e4f382006-04-29 16:06:31 +00001966static int fromhex(unsigned char c)
Eric Andersen3443bd72003-07-22 07:30:36 +00001967{
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +00001968 if (isdigit(c))
Eric Andersen3443bd72003-07-22 07:30:36 +00001969 return (c - '0');
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +00001970 if (c >= 'a' && c <= 'f')
1971 return (c - ('a' - 10));
Eric Andersen3443bd72003-07-22 07:30:36 +00001972 bb_error_msg_and_die("bad char: '%c' 0x%02x", c, c);
1973}
1974
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00001975static void identify_from_stdin(void) NORETURN;
Rob Landley0f0b6452006-05-03 18:28:06 +00001976static void identify_from_stdin(void)
Eric Andersen3443bd72003-07-22 07:30:36 +00001977{
Rob Landley0753f4a2006-06-07 00:27:25 +00001978 uint16_t sbuf[256];
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +00001979 unsigned char buf[1280];
1980 unsigned char *b = (unsigned char *)buf;
1981 int i;
Eric Andersen3443bd72003-07-22 07:30:36 +00001982
Bernhard Reutner-Fischer5e25ddb2008-05-19 09:48:17 +00001983 xread(STDIN_FILENO, buf, 1280);
Rob Landleyade7f952006-05-25 18:53:06 +00001984
Rob Landley0753f4a2006-06-07 00:27:25 +00001985 // Convert the newline-separated hex data into an identify block.
1986
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001987 for (i = 0; i < 256; i++) {
Rob Landley0753f4a2006-06-07 00:27:25 +00001988 int j;
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00001989 for (j = 0; j < 4; j++)
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +00001990 sbuf[i] = (sbuf[i] << 4) + fromhex(*(b++));
Eric Andersen3443bd72003-07-22 07:30:36 +00001991 }
Rob Landley0753f4a2006-06-07 00:27:25 +00001992
1993 // Parse the data.
1994
Rob Landley6389ff12006-05-01 19:28:53 +00001995 identify(sbuf);
Eric Andersen3443bd72003-07-22 07:30:36 +00001996}
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001997#else
1998void identify_from_stdin(void);
Eric Andersen3443bd72003-07-22 07:30:36 +00001999#endif
2000
Rob Landley20deab02006-05-07 23:34:15 +00002001/* busybox specific stuff */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002002static int parse_opts(unsigned long *value, int min, int max)
Eric Andersenb2aa7762004-04-05 13:08:08 +00002003{
Denis Vlasenko6429aab2006-09-23 12:22:11 +00002004 if (optarg) {
Denis Vlasenko13858992006-10-08 12:49:22 +00002005 *value = xatol_range(optarg, min, max);
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002006 return IS_SET;
Denis Vlasenko6429aab2006-09-23 12:22:11 +00002007 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002008 return IS_GET;
2009}
2010static int parse_opts_0_max(unsigned long *value, int max)
2011{
2012 return parse_opts(value, 0, max);
2013}
2014static int parse_opts_0_1(unsigned long *value)
2015{
2016 return parse_opts(value, 0, 1);
2017}
2018static int parse_opts_0_INTMAX(unsigned long *value)
2019{
2020 return parse_opts(value, 0, INT_MAX);
Rob Landley20deab02006-05-07 23:34:15 +00002021}
2022
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00002023static void parse_xfermode(int flag, smallint *get, smallint *set, int *value)
Rob Landley20deab02006-05-07 23:34:15 +00002024{
2025 if (flag) {
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002026 *get = IS_GET;
Rob Landley20deab02006-05-07 23:34:15 +00002027 if (optarg) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00002028 *value = translate_xfermode(optarg);
2029 *set = (*value > -1);
Rob Landley20deab02006-05-07 23:34:15 +00002030 }
2031 }
2032}
2033
Rob Landley06208412006-05-31 22:52:57 +00002034/*------- getopt short options --------*/
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002035static const char hdparm_options[] ALIGN1 =
Denis Vlasenko4daad902007-09-27 10:20:47 +00002036 "gfu::n::p:r::m::c::k::a::B:tT"
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002037 IF_FEATURE_HDPARM_GET_IDENTITY("iI")
2038 IF_FEATURE_HDPARM_HDIO_GETSET_DMA("d::")
Rob Landley20deab02006-05-07 23:34:15 +00002039#ifdef HDIO_DRIVE_CMD
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002040 "S:D:P:X:K:A:L:W:CyYzZ"
Rob Landley20deab02006-05-07 23:34:15 +00002041#endif
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002042 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("U:")
Rob Landley20deab02006-05-07 23:34:15 +00002043#ifdef HDIO_GET_QDMA
2044#ifdef HDIO_SET_QDMA
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002045 "Q:"
Rob Landley20deab02006-05-07 23:34:15 +00002046#else
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002047 "Q"
Rob Landley20deab02006-05-07 23:34:15 +00002048#endif
2049#endif
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002050 IF_FEATURE_HDPARM_HDIO_DRIVE_RESET("w")
2051 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF("x::b:")
2052 IF_FEATURE_HDPARM_HDIO_SCAN_HWIF("R:");
Rob Landley20deab02006-05-07 23:34:15 +00002053/*-------------------------------------*/
2054
2055/* our main() routine: */
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00002056int hdparm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Rob Landley20deab02006-05-07 23:34:15 +00002057int hdparm_main(int argc, char **argv)
2058{
2059 int c;
Rob Landleyade7f952006-05-25 18:53:06 +00002060 int flagcount = 0;
Rob Landley20deab02006-05-07 23:34:15 +00002061
Denys Vlasenko16714242011-09-21 01:59:15 +02002062 INIT_G();
2063
Rob Landley06208412006-05-31 22:52:57 +00002064 while ((c = getopt(argc, argv, hdparm_options)) >= 0) {
Rob Landley20deab02006-05-07 23:34:15 +00002065 flagcount++;
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002066 IF_FEATURE_HDPARM_GET_IDENTITY(get_IDentity |= (c == 'I'));
2067 IF_FEATURE_HDPARM_GET_IDENTITY(get_identity |= (c == 'i'));
Rob Landleyadde7982006-05-16 15:32:30 +00002068 get_geom |= (c == 'g');
2069 do_flush |= (c == 'f');
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002070 if (c == 'u') getset_unmask = parse_opts_0_1(&unmask);
2071 IF_FEATURE_HDPARM_HDIO_GETSET_DMA(
2072 if (c == 'd') getset_dma = parse_opts_0_max(&dma, 9);
2073 )
2074 if (c == 'n') getset_nowerr = parse_opts_0_1(&nowerr);
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00002075 parse_xfermode((c == 'p'), &noisy_piomode, &set_piomode, &piomode);
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002076 if (c == 'r') getset_readonly = parse_opts_0_1(&readonly);
2077 if (c == 'm') getset_mult = parse_opts_0_INTMAX(&mult /*32*/);
2078 if (c == 'c') getset_io32bit = parse_opts_0_INTMAX(&io32bit /*8*/);
2079 if (c == 'k') getset_keep = parse_opts_0_1(&keep);
2080 if (c == 'a') getset_readahead = parse_opts_0_INTMAX(&Xreadahead);
2081 if (c == 'B') getset_apmmode = parse_opts(&apmmode, 1, 255);
Rob Landleyadde7982006-05-16 15:32:30 +00002082 do_flush |= do_timings |= (c == 't');
2083 do_flush |= do_ctimings |= (c == 'T');
Rob Landley20deab02006-05-07 23:34:15 +00002084#ifdef HDIO_DRIVE_CMD
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002085 if (c == 'S') getset_standby = parse_opts_0_max(&standby_requested, 255);
2086 if (c == 'D') getset_defects = parse_opts_0_INTMAX(&defects);
2087 if (c == 'P') getset_prefetch = parse_opts_0_INTMAX(&prefetch);
Rob Landleyade7f952006-05-25 18:53:06 +00002088 parse_xfermode((c == 'X'), &get_xfermode, &set_xfermode, &xfermode_requested);
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002089 if (c == 'K') getset_dkeep = parse_opts_0_1(&prefetch);
2090 if (c == 'A') getset_lookahead = parse_opts_0_1(&lookahead);
2091 if (c == 'L') getset_doorlock = parse_opts_0_1(&doorlock);
2092 if (c == 'W') getset_wcache = parse_opts_0_1(&wcache);
Rob Landleyade7f952006-05-25 18:53:06 +00002093 get_powermode |= (c == 'C');
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002094 set_standbynow |= (c == 'y');
2095 set_sleepnow |= (c == 'Y');
Rob Landleyadde7982006-05-16 15:32:30 +00002096 reread_partn |= (c == 'z');
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002097 set_seagate |= (c == 'Z');
Rob Landley20deab02006-05-07 23:34:15 +00002098#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002099 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') unregister_hwif = parse_opts_0_INTMAX(&hwif));
Rob Landley20deab02006-05-07 23:34:15 +00002100#ifdef HDIO_GET_QDMA
Rob Landley19802562006-05-08 15:35:46 +00002101 if (c == 'Q') {
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002102 getset_dma_q = parse_opts_0_INTMAX(&dma_q);
Rob Landley19802562006-05-08 15:35:46 +00002103 }
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00002104#endif
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002105 IF_FEATURE_HDPARM_HDIO_DRIVE_RESET(perform_reset = (c == 'r'));
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002106 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'x') perform_tristate = parse_opts_0_1(&tristate));
2107 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'b') getset_busstate = parse_opts_0_max(&busstate, 2));
Rob Landley20deab02006-05-07 23:34:15 +00002108#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
2109 if (c == 'R') {
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002110 scan_hwif = parse_opts_0_INTMAX(&hwif_data);
Denys Vlasenko77832482010-08-12 14:14:45 +02002111 hwif_ctrl = xatoi_positive((argv[optind]) ? argv[optind] : "");
2112 hwif_irq = xatoi_positive((argv[optind+1]) ? argv[optind+1] : "");
Rob Landley20deab02006-05-07 23:34:15 +00002113 /* Move past the 2 additional arguments */
2114 argv += 2;
2115 argc -= 2;
2116 }
2117#endif
2118 }
Rob Landleyade7f952006-05-25 18:53:06 +00002119 /* When no flags are given (flagcount = 0), -acdgkmnru is assumed. */
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002120 if (!flagcount) {
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002121 getset_mult = getset_io32bit = getset_unmask = getset_keep = getset_readonly = getset_readahead = get_geom = IS_GET;
2122 IF_FEATURE_HDPARM_HDIO_GETSET_DMA(getset_dma = IS_GET);
Rob Landleyade7f952006-05-25 18:53:06 +00002123 }
Rob Landley20deab02006-05-07 23:34:15 +00002124 argv += optind;
2125
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00002126 if (!*argv) {
Rob Landley6d8ce172006-06-07 21:22:42 +00002127 if (ENABLE_FEATURE_HDPARM_GET_IDENTITY && !isatty(STDIN_FILENO))
2128 identify_from_stdin(); /* EXIT */
Denis Vlasenko4daad902007-09-27 10:20:47 +00002129 bb_show_usage();
Rob Landley20deab02006-05-07 23:34:15 +00002130 }
2131
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00002132 do {
2133 process_dev(*argv++);
2134 } while (*argv);
2135
2136 return EXIT_SUCCESS;
Eric Andersen3443bd72003-07-22 07:30:36 +00002137}