blob: 7608408dd172607b6f3da9ec336d85f34456f983 [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"
18//usage: "Options:"
19//usage: "\n -a Get/set fs readahead"
20//usage: "\n -A Set drive read-lookahead flag (0/1)"
21//usage: "\n -b Get/set bus state (0 == off, 1 == on, 2 == tristate)"
22//usage: "\n -B Set Advanced Power Management setting (1-255)"
23//usage: "\n -c Get/set IDE 32-bit IO setting"
24//usage: "\n -C Check IDE power mode status"
25//usage: IF_FEATURE_HDPARM_HDIO_GETSET_DMA(
26//usage: "\n -d Get/set using_dma flag")
27//usage: "\n -D Enable/disable drive defect-mgmt"
28//usage: "\n -f Flush buffer cache for device on exit"
29//usage: "\n -g Display drive geometry"
30//usage: "\n -h Display terse usage information"
31//usage: IF_FEATURE_HDPARM_GET_IDENTITY(
32//usage: "\n -i Display drive identification")
33//usage: IF_FEATURE_HDPARM_GET_IDENTITY(
34//usage: "\n -I Detailed/current information directly from drive")
35//usage: "\n -k Get/set keep_settings_over_reset flag (0/1)"
36//usage: "\n -K Set drive keep_features_over_reset flag (0/1)"
37//usage: "\n -L Set drive doorlock (0/1) (removable harddisks only)"
38//usage: "\n -m Get/set multiple sector count"
39//usage: "\n -n Get/set ignore-write-errors flag (0/1)"
40//usage: "\n -p Set PIO mode on IDE interface chipset (0,1,2,3,4,...)"
41//usage: "\n -P Set drive prefetch count"
42/* //usage: "\n -q Change next setting quietly" - not supported ib bbox */
43//usage: "\n -Q Get/set DMA tagged-queuing depth (if supported)"
44//usage: "\n -r Get/set readonly flag (DANGEROUS to set)"
45//usage: IF_FEATURE_HDPARM_HDIO_SCAN_HWIF(
46//usage: "\n -R Register an IDE interface (DANGEROUS)")
47//usage: "\n -S Set standby (spindown) timeout"
48//usage: "\n -t Perform device read timings"
49//usage: "\n -T Perform cache read timings"
50//usage: "\n -u Get/set unmaskirq flag (0/1)"
51//usage: IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(
52//usage: "\n -U Unregister an IDE interface (DANGEROUS)")
53//usage: "\n -v Defaults; same as -mcudkrag for IDE drives"
54//usage: "\n -V Display program version and exit immediately"
55//usage: IF_FEATURE_HDPARM_HDIO_DRIVE_RESET(
56//usage: "\n -w Perform device reset (DANGEROUS)")
57//usage: "\n -W Set drive write-caching flag (0/1) (DANGEROUS)"
58//usage: IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(
59//usage: "\n -x Tristate device for hotswap (0/1) (DANGEROUS)")
60//usage: "\n -X Set IDE xfer mode (DANGEROUS)"
61//usage: "\n -y Put IDE drive in standby mode"
62//usage: "\n -Y Put IDE drive to sleep"
63//usage: "\n -Z Disable Seagate auto-powersaving mode"
64//usage: "\n -z Reread partition table"
65
Denys Vlasenko860d2bb2009-07-10 18:37:06 +020066#include "libbb.h"
67/* must be _after_ libbb.h: */
Eric Andersen3443bd72003-07-22 07:30:36 +000068#include <linux/hdreg.h>
Denys Vlasenkoda49f582009-07-08 02:58:38 +020069#include <sys/mount.h>
Denys Vlasenkoaf3fd142009-09-22 23:16:39 +020070#if !defined(BLKGETSIZE64)
71# define BLKGETSIZE64 _IOR(0x12,114,size_t)
72#endif
Eric Andersen3443bd72003-07-22 07:30:36 +000073
Eric Andersen3443bd72003-07-22 07:30:36 +000074/* device types */
75/* ------------ */
76#define NO_DEV 0xffff
77#define ATA_DEV 0x0000
78#define ATAPI_DEV 0x0001
79
80/* word definitions */
81/* ---------------- */
82#define GEN_CONFIG 0 /* general configuration */
83#define LCYLS 1 /* number of logical cylinders */
84#define CONFIG 2 /* specific configuration */
85#define LHEADS 3 /* number of logical heads */
86#define TRACK_BYTES 4 /* number of bytes/track (ATA-1) */
87#define SECT_BYTES 5 /* number of bytes/sector (ATA-1) */
88#define LSECTS 6 /* number of logical sectors/track */
89#define START_SERIAL 10 /* ASCII serial number */
90#define LENGTH_SERIAL 10 /* 10 words (20 bytes or characters) */
91#define BUF_TYPE 20 /* buffer type (ATA-1) */
92#define BUFFER__SIZE 21 /* buffer size (ATA-1) */
93#define RW_LONG 22 /* extra bytes in R/W LONG cmd ( < ATA-4)*/
94#define START_FW_REV 23 /* ASCII firmware revision */
95#define LENGTH_FW_REV 4 /* 4 words (8 bytes or characters) */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000096#define START_MODEL 27 /* ASCII model number */
97#define LENGTH_MODEL 20 /* 20 words (40 bytes or characters) */
Denis Vlasenko4b924f32007-05-30 00:29:55 +000098#define SECTOR_XFER_MAX 47 /* r/w multiple: max sectors xfered */
Eric Andersen3443bd72003-07-22 07:30:36 +000099#define DWORD_IO 48 /* can do double-word IO (ATA-1 only) */
100#define CAPAB_0 49 /* capabilities */
101#define CAPAB_1 50
102#define PIO_MODE 51 /* max PIO mode supported (obsolete)*/
103#define DMA_MODE 52 /* max Singleword DMA mode supported (obs)*/
104#define WHATS_VALID 53 /* what fields are valid */
105#define LCYLS_CUR 54 /* current logical cylinders */
106#define LHEADS_CUR 55 /* current logical heads */
Denis Vlasenko4b924f32007-05-30 00:29:55 +0000107#define LSECTS_CUR 56 /* current logical sectors/track */
Eric Andersen3443bd72003-07-22 07:30:36 +0000108#define CAPACITY_LSB 57 /* current capacity in sectors */
109#define CAPACITY_MSB 58
110#define SECTOR_XFER_CUR 59 /* r/w multiple: current sectors xfered */
111#define LBA_SECTS_LSB 60 /* LBA: total number of user */
112#define LBA_SECTS_MSB 61 /* addressable sectors */
113#define SINGLE_DMA 62 /* singleword DMA modes */
114#define MULTI_DMA 63 /* multiword DMA modes */
115#define ADV_PIO_MODES 64 /* advanced PIO modes supported */
116 /* multiword DMA xfer cycle time: */
117#define DMA_TIME_MIN 65 /* - minimum */
Denis Vlasenko551ffdc2009-04-01 19:48:05 +0000118#define DMA_TIME_NORM 66 /* - manufacturer's recommended */
Eric Andersen3443bd72003-07-22 07:30:36 +0000119 /* minimum PIO xfer cycle time: */
120#define PIO_NO_FLOW 67 /* - without flow control */
121#define PIO_FLOW 68 /* - with IORDY flow control */
122#define PKT_REL 71 /* typical #ns from PKT cmd to bus rel */
123#define SVC_NBSY 72 /* typical #ns from SERVICE cmd to !BSY */
124#define CDR_MAJOR 73 /* CD ROM: major version number */
125#define CDR_MINOR 74 /* CD ROM: minor version number */
126#define QUEUE_DEPTH 75 /* queue depth */
127#define MAJOR 80 /* major version number */
128#define MINOR 81 /* minor version number */
129#define CMDS_SUPP_0 82 /* command/feature set(s) supported */
130#define CMDS_SUPP_1 83
131#define CMDS_SUPP_2 84
132#define CMDS_EN_0 85 /* command/feature set(s) enabled */
133#define CMDS_EN_1 86
134#define CMDS_EN_2 87
135#define ULTRA_DMA 88 /* ultra DMA modes */
136 /* time to complete security erase */
137#define ERASE_TIME 89 /* - ordinary */
138#define ENH_ERASE_TIME 90 /* - enhanced */
139#define ADV_PWR 91 /* current advanced power management level
Glenn L McGrath07085852003-10-09 07:28:22 +0000140 in low byte, 0x40 in high byte. */
Denis Vlasenko551ffdc2009-04-01 19:48:05 +0000141#define PSWD_CODE 92 /* master password revision code */
Eric Andersen3443bd72003-07-22 07:30:36 +0000142#define HWRST_RSLT 93 /* hardware reset result */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000143#define ACOUSTIC 94 /* acoustic mgmt values ( >= ATA-6) */
Eric Andersen3443bd72003-07-22 07:30:36 +0000144#define LBA_LSB 100 /* LBA: maximum. Currently only 48 */
145#define LBA_MID 101 /* bits are used, but addr 103 */
146#define LBA_48_MSB 102 /* has been reserved for LBA in */
147#define LBA_64_MSB 103 /* the future. */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000148#define RM_STAT 127 /* removable media status notification feature set support */
Eric Andersen3443bd72003-07-22 07:30:36 +0000149#define SECU_STATUS 128 /* security status */
150#define CFA_PWR_MODE 160 /* CFA power mode 1 */
151#define START_MEDIA 176 /* media serial number */
152#define LENGTH_MEDIA 20 /* 20 words (40 bytes or characters)*/
153#define START_MANUF 196 /* media manufacturer I.D. */
154#define LENGTH_MANUF 10 /* 10 words (20 bytes or characters) */
155#define INTEGRITY 255 /* integrity word */
156
157/* bit definitions within the words */
158/* -------------------------------- */
159
160/* many words are considered valid if bit 15 is 0 and bit 14 is 1 */
161#define VALID 0xc000
162#define VALID_VAL 0x4000
163/* many words are considered invalid if they are either all-0 or all-1 */
164#define NOVAL_0 0x0000
165#define NOVAL_1 0xffff
166
167/* word 0: gen_config */
Glenn L McGrath07085852003-10-09 07:28:22 +0000168#define NOT_ATA 0x8000
Eric Andersen3443bd72003-07-22 07:30:36 +0000169#define NOT_ATAPI 0x4000 /* (check only if bit 15 == 1) */
170#define MEDIA_REMOVABLE 0x0080
171#define DRIVE_NOT_REMOVABLE 0x0040 /* bit obsoleted in ATA 6 */
172#define INCOMPLETE 0x0004
173#define CFA_SUPPORT_VAL 0x848a /* 848a=CFA feature set support */
174#define DRQ_RESPONSE_TIME 0x0060
175#define DRQ_3MS_VAL 0x0000
176#define DRQ_INTR_VAL 0x0020
177#define DRQ_50US_VAL 0x0040
178#define PKT_SIZE_SUPPORTED 0x0003
179#define PKT_SIZE_12_VAL 0x0000
180#define PKT_SIZE_16_VAL 0x0001
181#define EQPT_TYPE 0x1f00
182#define SHIFT_EQPT 8
183
184#define CDROM 0x0005
185
Eric Andersen3443bd72003-07-22 07:30:36 +0000186/* word 1: number of logical cylinders */
187#define LCYLS_MAX 0x3fff /* maximum allowable value */
188
Eric Andersenaff114c2004-04-14 17:51:38 +0000189/* word 2: specific configuration
Eric Andersen3443bd72003-07-22 07:30:36 +0000190 * (a) require SET FEATURES to spin-up
191 * (b) require spin-up to fully reply to IDENTIFY DEVICE
192 */
193#define STBY_NID_VAL 0x37c8 /* (a) and (b) */
194#define STBY_ID_VAL 0x738c /* (a) and not (b) */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000195#define PWRD_NID_VAL 0x8c73 /* not (a) and (b) */
Eric Andersen3443bd72003-07-22 07:30:36 +0000196#define PWRD_ID_VAL 0xc837 /* not (a) and not (b) */
197
198/* words 47 & 59: sector_xfer_max & sector_xfer_cur */
199#define SECTOR_XFER 0x00ff /* sectors xfered on r/w multiple cmds*/
200#define MULTIPLE_SETTING_VALID 0x0100 /* 1=multiple sector setting is valid */
201
202/* word 49: capabilities 0 */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000203#define STD_STBY 0x2000 /* 1=standard values supported (ATA); 0=vendor specific values */
Eric Andersen3443bd72003-07-22 07:30:36 +0000204#define IORDY_SUP 0x0800 /* 1=support; 0=may be supported */
205#define IORDY_OFF 0x0400 /* 1=may be disabled */
206#define LBA_SUP 0x0200 /* 1=Logical Block Address support */
207#define DMA_SUP 0x0100 /* 1=Direct Memory Access support */
208#define DMA_IL_SUP 0x8000 /* 1=interleaved DMA support (ATAPI) */
209#define CMD_Q_SUP 0x4000 /* 1=command queuing support (ATAPI) */
210#define OVLP_SUP 0x2000 /* 1=overlap operation support (ATAPI) */
211#define SWRST_REQ 0x1000 /* 1=ATA SW reset required (ATAPI, obsolete */
212
213/* word 50: capabilities 1 */
214#define MIN_STANDBY_TIMER 0x0001 /* 1=device specific standby timer value minimum */
215
216/* words 51 & 52: PIO & DMA cycle times */
217#define MODE 0xff00 /* the mode is in the MSBs */
218
219/* word 53: whats_valid */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000220#define OK_W88 0x0004 /* the ultra_dma info is valid */
Eric Andersen3443bd72003-07-22 07:30:36 +0000221#define OK_W64_70 0x0002 /* see above for word descriptions */
222#define OK_W54_58 0x0001 /* current cyl, head, sector, cap. info valid */
223
224/*word 63,88: dma_mode, ultra_dma_mode*/
225#define MODE_MAX 7 /* bit definitions force udma <=7 (when
226 * udma >=8 comes out it'll have to be
227 * defined in a new dma_mode word!) */
228
229/* word 64: PIO transfer modes */
230#define PIO_SUP 0x00ff /* only bits 0 & 1 are used so far, */
231#define PIO_MODE_MAX 8 /* but all 8 bits are defined */
232
233/* word 75: queue_depth */
234#define DEPTH_BITS 0x001f /* bits used for queue depth */
235
236/* words 80-81: version numbers */
237/* NOVAL_0 or NOVAL_1 means device does not report version */
238
239/* word 81: minor version number */
Rob Landley0e6a3e12006-04-28 01:33:30 +0000240#define MINOR_MAX 0x22
Eric Andersen3443bd72003-07-22 07:30:36 +0000241/* words 82-84: cmds/feats supported */
242#define CMDS_W82 0x77ff /* word 82: defined command locations*/
243#define CMDS_W83 0x3fff /* word 83: defined command locations*/
244#define CMDS_W84 0x002f /* word 83: defined command locations*/
Glenn L McGrath07085852003-10-09 07:28:22 +0000245#define SUPPORT_48_BIT 0x0400
Eric Andersen3443bd72003-07-22 07:30:36 +0000246#define NUM_CMD_FEAT_STR 48
247
Eric Andersen3443bd72003-07-22 07:30:36 +0000248/* words 85-87: cmds/feats enabled */
249/* use cmd_feat_str[] to display what commands and features have
Glenn L McGrath07085852003-10-09 07:28:22 +0000250 * been enabled with words 85-87
Eric Andersen3443bd72003-07-22 07:30:36 +0000251 */
252
253/* words 89, 90, SECU ERASE TIME */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000254#define ERASE_BITS 0x00ff
Eric Andersen3443bd72003-07-22 07:30:36 +0000255
256/* word 92: master password revision */
257/* NOVAL_0 or NOVAL_1 means no support for master password revision */
258
259/* word 93: hw reset result */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000260#define CBLID 0x2000 /* CBLID status */
261#define RST0 0x0001 /* 1=reset to device #0 */
262#define DEV_DET 0x0006 /* how device num determined */
263#define JUMPER_VAL 0x0002 /* device num determined by jumper */
264#define CSEL_VAL 0x0004 /* device num determined by CSEL_VAL */
Eric Andersen3443bd72003-07-22 07:30:36 +0000265
266/* word 127: removable media status notification feature set support */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000267#define RM_STAT_BITS 0x0003
268#define RM_STAT_SUP 0x0001
Glenn L McGrath07085852003-10-09 07:28:22 +0000269
Eric Andersen3443bd72003-07-22 07:30:36 +0000270/* word 128: security */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000271#define SECU_ENABLED 0x0002
272#define SECU_LEVEL 0x0010
273#define NUM_SECU_STR 6
Eric Andersen3443bd72003-07-22 07:30:36 +0000274
275/* word 160: CFA power mode */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000276#define VALID_W160 0x8000 /* 1=word valid */
277#define PWR_MODE_REQ 0x2000 /* 1=CFA power mode req'd by some cmds*/
278#define PWR_MODE_OFF 0x1000 /* 1=CFA power moded disabled */
279#define MAX_AMPS 0x0fff /* value = max current in ma */
Eric Andersen3443bd72003-07-22 07:30:36 +0000280
281/* word 255: integrity */
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000282#define SIG 0x00ff /* signature location */
283#define SIG_VAL 0x00a5 /* signature value */
Eric Andersen3443bd72003-07-22 07:30:36 +0000284
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000285#define TIMING_BUF_MB 1
286#define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024)
Glenn L McGrath07085852003-10-09 07:28:22 +0000287
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000288#undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */
Glenn L McGrath07085852003-10-09 07:28:22 +0000289
Denis Vlasenko892536f2007-09-27 10:23:34 +0000290
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200291#define IS_GET 1
292#define IS_SET 2
293
294
Denis Vlasenko892536f2007-09-27 10:23:34 +0000295enum { fd = 3 };
296
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000297
298struct globals {
299 smallint get_identity, get_geom;
300 smallint do_flush;
301 smallint do_ctimings, do_timings;
302 smallint reread_partn;
303 smallint set_piomode, noisy_piomode;
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200304 smallint getset_readahead;
305 smallint getset_readonly;
306 smallint getset_unmask;
307 smallint getset_mult;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000308#ifdef HDIO_GET_QDMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200309 smallint getset_dma_q;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000310#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200311 smallint getset_nowerr;
312 smallint getset_keep;
313 smallint getset_io32bit;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000314 int piomode;
315 unsigned long Xreadahead;
316 unsigned long readonly;
317 unsigned long unmask;
318 unsigned long mult;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000319#ifdef HDIO_SET_QDMA
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000320 unsigned long dma_q;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000321#endif
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000322 unsigned long nowerr;
323 unsigned long keep;
324 unsigned long io32bit;
325#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
326 unsigned long dma;
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200327 smallint getset_dma;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000328#endif
329#ifdef HDIO_DRIVE_CMD
330 smallint set_xfermode, get_xfermode;
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200331 smallint getset_dkeep;
332 smallint getset_standby;
333 smallint getset_lookahead;
334 smallint getset_prefetch;
335 smallint getset_defects;
336 smallint getset_wcache;
337 smallint getset_doorlock;
338 smallint set_seagate;
339 smallint set_standbynow;
340 smallint set_sleepnow;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000341 smallint get_powermode;
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200342 smallint getset_apmmode;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000343 int xfermode_requested;
344 unsigned long dkeep;
Denis Vlasenko3c96d022008-03-20 13:44:50 +0000345 unsigned long standby_requested; /* 0..255 */
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000346 unsigned long lookahead;
347 unsigned long prefetch;
348 unsigned long defects;
349 unsigned long wcache;
350 unsigned long doorlock;
351 unsigned long apmmode;
352#endif
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000353 IF_FEATURE_HDPARM_GET_IDENTITY( smallint get_IDentity;)
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200354 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( smallint getset_busstate;)
Denis Vlasenko5e34ff22009-04-21 11:09:40 +0000355 IF_FEATURE_HDPARM_HDIO_DRIVE_RESET( smallint perform_reset;)
356 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( smallint perform_tristate;)
357 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(smallint unregister_hwif;)
358 IF_FEATURE_HDPARM_HDIO_SCAN_HWIF( smallint scan_hwif;)
359 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( unsigned long busstate;)
360 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( unsigned long tristate;)
361 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(unsigned long hwif;)
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000362#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
363 unsigned long hwif_data;
364 unsigned long hwif_ctrl;
365 unsigned long hwif_irq;
366#endif
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +0000367#ifdef DO_FLUSHCACHE
368 unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };
369#endif
Denys Vlasenko98a4c7c2010-02-04 15:00:15 +0100370} FIX_ALIASING;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000371#define G (*(struct globals*)&bb_common_bufsiz1)
372struct BUG_G_too_big {
373 char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
374};
375#define get_identity (G.get_identity )
376#define get_geom (G.get_geom )
377#define do_flush (G.do_flush )
378#define do_ctimings (G.do_ctimings )
379#define do_timings (G.do_timings )
380#define reread_partn (G.reread_partn )
381#define set_piomode (G.set_piomode )
382#define noisy_piomode (G.noisy_piomode )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200383#define getset_readahead (G.getset_readahead )
384#define getset_readonly (G.getset_readonly )
385#define getset_unmask (G.getset_unmask )
386#define getset_mult (G.getset_mult )
387#define getset_dma_q (G.getset_dma_q )
388#define getset_nowerr (G.getset_nowerr )
389#define getset_keep (G.getset_keep )
390#define getset_io32bit (G.getset_io32bit )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000391#define piomode (G.piomode )
392#define Xreadahead (G.Xreadahead )
393#define readonly (G.readonly )
394#define unmask (G.unmask )
395#define mult (G.mult )
396#define dma_q (G.dma_q )
397#define nowerr (G.nowerr )
398#define keep (G.keep )
399#define io32bit (G.io32bit )
400#define dma (G.dma )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200401#define getset_dma (G.getset_dma )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000402#define set_xfermode (G.set_xfermode )
403#define get_xfermode (G.get_xfermode )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200404#define getset_dkeep (G.getset_dkeep )
405#define getset_standby (G.getset_standby )
406#define getset_lookahead (G.getset_lookahead )
407#define getset_prefetch (G.getset_prefetch )
408#define getset_defects (G.getset_defects )
409#define getset_wcache (G.getset_wcache )
410#define getset_doorlock (G.getset_doorlock )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000411#define set_seagate (G.set_seagate )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000412#define set_standbynow (G.set_standbynow )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000413#define set_sleepnow (G.set_sleepnow )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000414#define get_powermode (G.get_powermode )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200415#define getset_apmmode (G.getset_apmmode )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000416#define xfermode_requested (G.xfermode_requested )
417#define dkeep (G.dkeep )
418#define standby_requested (G.standby_requested )
419#define lookahead (G.lookahead )
420#define prefetch (G.prefetch )
421#define defects (G.defects )
422#define wcache (G.wcache )
423#define doorlock (G.doorlock )
424#define apmmode (G.apmmode )
425#define get_IDentity (G.get_IDentity )
Denys Vlasenkoc7068452009-05-20 16:11:41 +0200426#define getset_busstate (G.getset_busstate )
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +0000427#define perform_reset (G.perform_reset )
428#define perform_tristate (G.perform_tristate )
429#define unregister_hwif (G.unregister_hwif )
430#define scan_hwif (G.scan_hwif )
431#define busstate (G.busstate )
432#define tristate (G.tristate )
433#define hwif (G.hwif )
434#define hwif_data (G.hwif_data )
435#define hwif_ctrl (G.hwif_ctrl )
436#define hwif_irq (G.hwif_irq )
437
438
Glenn L McGrath07085852003-10-09 07:28:22 +0000439/* Busybox messages and functions */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000440#if ENABLE_IOCTL_HEX2STR_ERROR
Denis Vlasenko892536f2007-09-27 10:23:34 +0000441static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt, const char *string)
Rob Landley5f8b5ec2006-04-29 16:03:40 +0000442{
443 if (!ioctl(fd, cmd, args))
444 return 0;
445 args[0] = alt;
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000446 return bb_ioctl_or_warn(fd, cmd, args, string);
Rob Landley5f8b5ec2006-04-29 16:03:40 +0000447}
Denis Vlasenko892536f2007-09-27 10:23:34 +0000448#define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt,#cmd)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000449#else
Denis Vlasenko892536f2007-09-27 10:23:34 +0000450static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000451{
452 if (!ioctl(fd, cmd, args))
453 return 0;
454 args[0] = alt;
455 return bb_ioctl_or_warn(fd, cmd, args);
456}
Denis Vlasenko892536f2007-09-27 10:23:34 +0000457#define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000458#endif
Rob Landley5f8b5ec2006-04-29 16:03:40 +0000459
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000460static void on_off(int value)
461{
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000462 puts(value ? " (on)" : " (off)");
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000463}
Glenn L McGrath07085852003-10-09 07:28:22 +0000464
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000465static void print_flag_on_off(int get_arg, const char *s, unsigned long arg)
Glenn L McGrath07085852003-10-09 07:28:22 +0000466{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +0000467 if (get_arg) {
Rob Landleyadde7982006-05-16 15:32:30 +0000468 printf(" setting %s to %ld", s, arg);
Glenn L McGrath07085852003-10-09 07:28:22 +0000469 on_off(arg);
470 }
471}
472
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000473static void print_value_on_off(const char *str, unsigned long argp)
Glenn L McGrath07085852003-10-09 07:28:22 +0000474{
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +0000475 printf(" %s\t= %2ld", str, argp);
476 on_off(argp != 0);
Glenn L McGrath07085852003-10-09 07:28:22 +0000477}
Eric Andersen416c2422003-12-12 00:08:57 +0000478
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000479#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
Denis Vlasenko4daad902007-09-27 10:20:47 +0000480static void print_ascii(const char *p, int length)
481{
482#if BB_BIG_ENDIAN
483#define LE_ONLY(x)
484 enum { ofs = 0 };
485#else
486#define LE_ONLY(x) x
487 /* every 16bit word is big-endian (i.e. inverted) */
488 /* accessing bytes in 1,0, 3,2, 5,4... sequence */
489 int ofs = 1;
490#endif
491
492 length *= 2;
493 /* find first non-space & print it */
494 while (length && p[ofs] != ' ') {
495 p++;
496 LE_ONLY(ofs = -ofs;)
497 length--;
498 }
499 while (length && p[ofs]) {
500 bb_putchar(p[ofs]);
501 p++;
502 LE_ONLY(ofs = -ofs;)
503 length--;
504 }
505 bb_putchar('\n');
506#undef LE_ONLY
507}
Glenn L McGrath07085852003-10-09 07:28:22 +0000508
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000509static void xprint_ascii(uint16_t *val, int i, const char *string, int n)
Glenn L McGrath07085852003-10-09 07:28:22 +0000510{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +0000511 if (val[i]) {
512 printf("\t%-20s", string);
Denis Vlasenko4daad902007-09-27 10:20:47 +0000513 print_ascii((void*)&val[i], n);
Glenn L McGrath07085852003-10-09 07:28:22 +0000514 }
515}
Glenn L McGrath07085852003-10-09 07:28:22 +0000516
Glenn L McGrath07085852003-10-09 07:28:22 +0000517static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode)
518{
Eric Andersen3443bd72003-07-22 07:30:36 +0000519 uint16_t ii;
520 uint8_t err_dma = 0;
Glenn L McGrath07085852003-10-09 07:28:22 +0000521
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000522 for (ii = 0; ii <= MODE_MAX; ii++) {
523 if (mode_sel & 0x0001) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000524 printf("*%cdma%u ", cc, ii);
Rob Landleya3e4f382006-04-29 16:06:31 +0000525 if (*have_mode)
Glenn L McGrath07085852003-10-09 07:28:22 +0000526 err_dma = 1;
Eric Andersen3443bd72003-07-22 07:30:36 +0000527 *have_mode = 1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000528 } else if (mode_sup & 0x0001)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000529 printf("%cdma%u ", cc, ii);
Glenn L McGrath07085852003-10-09 07:28:22 +0000530
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000531 mode_sup >>= 1;
532 mode_sel >>= 1;
Eric Andersen3443bd72003-07-22 07:30:36 +0000533 }
534 return err_dma;
535}
Glenn L McGrath07085852003-10-09 07:28:22 +0000536
Denis Vlasenko91303402007-10-30 19:36:54 +0000537static const char pkt_str[] ALIGN1 =
538 "Direct-access device" "\0" /* word 0, bits 12-8 = 00 */
539 "Sequential-access device" "\0" /* word 0, bits 12-8 = 01 */
540 "Printer" "\0" /* word 0, bits 12-8 = 02 */
541 "Processor" "\0" /* word 0, bits 12-8 = 03 */
542 "Write-once device" "\0" /* word 0, bits 12-8 = 04 */
543 "CD-ROM" "\0" /* word 0, bits 12-8 = 05 */
544 "Scanner" "\0" /* word 0, bits 12-8 = 06 */
545 "Optical memory" "\0" /* word 0, bits 12-8 = 07 */
546 "Medium changer" "\0" /* word 0, bits 12-8 = 08 */
547 "Communications device" "\0" /* word 0, bits 12-8 = 09 */
548 "ACS-IT8 device" "\0" /* word 0, bits 12-8 = 0a */
549 "ACS-IT8 device" "\0" /* word 0, bits 12-8 = 0b */
550 "Array controller" "\0" /* word 0, bits 12-8 = 0c */
551 "Enclosure services" "\0" /* word 0, bits 12-8 = 0d */
552 "Reduced block command device" "\0" /* word 0, bits 12-8 = 0e */
553 "Optical card reader/writer" "\0" /* word 0, bits 12-8 = 0f */
554;
555
556static const char ata1_cfg_str[] ALIGN1 = /* word 0 in ATA-1 mode */
557 "reserved" "\0" /* bit 0 */
558 "hard sectored" "\0" /* bit 1 */
559 "soft sectored" "\0" /* bit 2 */
560 "not MFM encoded " "\0" /* bit 3 */
561 "head switch time > 15us" "\0" /* bit 4 */
562 "spindle motor control option" "\0" /* bit 5 */
563 "fixed drive" "\0" /* bit 6 */
564 "removable drive" "\0" /* bit 7 */
565 "disk xfer rate <= 5Mbs" "\0" /* bit 8 */
566 "disk xfer rate > 5Mbs, <= 10Mbs" "\0" /* bit 9 */
567 "disk xfer rate > 5Mbs" "\0" /* bit 10 */
568 "rotational speed tol." "\0" /* bit 11 */
569 "data strobe offset option" "\0" /* bit 12 */
570 "track offset option" "\0" /* bit 13 */
571 "format speed tolerance gap reqd" "\0" /* bit 14 */
572 "ATAPI" /* bit 14 */
573;
574
575static const char minor_str[] ALIGN1 =
576 /* word 81 value: */
577 "Unspecified" "\0" /* 0x0000 */
578 "ATA-1 X3T9.2 781D prior to rev.4" "\0" /* 0x0001 */
579 "ATA-1 published, ANSI X3.221-1994" "\0" /* 0x0002 */
580 "ATA-1 X3T9.2 781D rev.4" "\0" /* 0x0003 */
581 "ATA-2 published, ANSI X3.279-1996" "\0" /* 0x0004 */
582 "ATA-2 X3T10 948D prior to rev.2k" "\0" /* 0x0005 */
583 "ATA-3 X3T10 2008D rev.1" "\0" /* 0x0006 */
584 "ATA-2 X3T10 948D rev.2k" "\0" /* 0x0007 */
585 "ATA-3 X3T10 2008D rev.0" "\0" /* 0x0008 */
586 "ATA-2 X3T10 948D rev.3" "\0" /* 0x0009 */
587 "ATA-3 published, ANSI X3.298-199x" "\0" /* 0x000a */
588 "ATA-3 X3T10 2008D rev.6" "\0" /* 0x000b */
589 "ATA-3 X3T13 2008D rev.7 and 7a" "\0" /* 0x000c */
590 "ATA/ATAPI-4 X3T13 1153D rev.6" "\0" /* 0x000d */
591 "ATA/ATAPI-4 T13 1153D rev.13" "\0" /* 0x000e */
592 "ATA/ATAPI-4 X3T13 1153D rev.7" "\0" /* 0x000f */
593 "ATA/ATAPI-4 T13 1153D rev.18" "\0" /* 0x0010 */
594 "ATA/ATAPI-4 T13 1153D rev.15" "\0" /* 0x0011 */
595 "ATA/ATAPI-4 published, ANSI INCITS 317-1998" "\0" /* 0x0012 */
596 "ATA/ATAPI-5 T13 1321D rev.3" "\0" /* 0x0013 */
597 "ATA/ATAPI-4 T13 1153D rev.14" "\0" /* 0x0014 */
598 "ATA/ATAPI-5 T13 1321D rev.1" "\0" /* 0x0015 */
599 "ATA/ATAPI-5 published, ANSI INCITS 340-2000" "\0" /* 0x0016 */
600 "ATA/ATAPI-4 T13 1153D rev.17" "\0" /* 0x0017 */
601 "ATA/ATAPI-6 T13 1410D rev.0" "\0" /* 0x0018 */
602 "ATA/ATAPI-6 T13 1410D rev.3a" "\0" /* 0x0019 */
603 "ATA/ATAPI-7 T13 1532D rev.1" "\0" /* 0x001a */
604 "ATA/ATAPI-6 T13 1410D rev.2" "\0" /* 0x001b */
605 "ATA/ATAPI-6 T13 1410D rev.1" "\0" /* 0x001c */
606 "ATA/ATAPI-7 published, ANSI INCITS 397-2005" "\0" /* 0x001d */
607 "ATA/ATAPI-7 T13 1532D rev.0" "\0" /* 0x001e */
608 "reserved" "\0" /* 0x001f */
609 "reserved" "\0" /* 0x0020 */
610 "ATA/ATAPI-7 T13 1532D rev.4a" "\0" /* 0x0021 */
611 "ATA/ATAPI-6 published, ANSI INCITS 361-2002" "\0" /* 0x0022 */
612 "reserved" /* 0x0023-0xfffe */
613;
614static const char actual_ver[MINOR_MAX + 2] ALIGN1 = {
615 /* word 81 value: */
616 0, /* 0x0000 WARNING: actual_ver[] array */
617 1, /* 0x0001 WARNING: corresponds */
618 1, /* 0x0002 WARNING: *exactly* */
619 1, /* 0x0003 WARNING: to the ATA/ */
620 2, /* 0x0004 WARNING: ATAPI version */
621 2, /* 0x0005 WARNING: listed in */
622 3, /* 0x0006 WARNING: the */
623 2, /* 0x0007 WARNING: minor_str */
624 3, /* 0x0008 WARNING: array */
625 2, /* 0x0009 WARNING: above. */
626 3, /* 0x000a WARNING: */
627 3, /* 0x000b WARNING: If you change */
628 3, /* 0x000c WARNING: that one, */
629 4, /* 0x000d WARNING: change this one */
630 4, /* 0x000e WARNING: too!!! */
631 4, /* 0x000f */
632 4, /* 0x0010 */
633 4, /* 0x0011 */
634 4, /* 0x0012 */
635 5, /* 0x0013 */
636 4, /* 0x0014 */
637 5, /* 0x0015 */
638 5, /* 0x0016 */
639 4, /* 0x0017 */
640 6, /* 0x0018 */
641 6, /* 0x0019 */
642 7, /* 0x001a */
643 6, /* 0x001b */
644 6, /* 0x001c */
645 7, /* 0x001d */
646 7, /* 0x001e */
647 0, /* 0x001f */
648 0, /* 0x0020 */
649 7, /* 0x0021 */
650 6, /* 0x0022 */
651 0 /* 0x0023-0xfffe */
652};
653
654static const char cmd_feat_str[] ALIGN1 =
655 "" "\0" /* word 82 bit 15: obsolete */
656 "NOP cmd" "\0" /* word 82 bit 14 */
657 "READ BUFFER cmd" "\0" /* word 82 bit 13 */
658 "WRITE BUFFER cmd" "\0" /* word 82 bit 12 */
659 "" "\0" /* word 82 bit 11: obsolete */
660 "Host Protected Area feature set" "\0" /* word 82 bit 10 */
661 "DEVICE RESET cmd" "\0" /* word 82 bit 9 */
662 "SERVICE interrupt" "\0" /* word 82 bit 8 */
663 "Release interrupt" "\0" /* word 82 bit 7 */
664 "Look-ahead" "\0" /* word 82 bit 6 */
665 "Write cache" "\0" /* word 82 bit 5 */
666 "PACKET command feature set" "\0" /* word 82 bit 4 */
667 "Power Management feature set" "\0" /* word 82 bit 3 */
668 "Removable Media feature set" "\0" /* word 82 bit 2 */
669 "Security Mode feature set" "\0" /* word 82 bit 1 */
670 "SMART feature set" "\0" /* word 82 bit 0 */
671 /* -------------- */
672 "" "\0" /* word 83 bit 15: !valid bit */
673 "" "\0" /* word 83 bit 14: valid bit */
674 "FLUSH CACHE EXT cmd" "\0" /* word 83 bit 13 */
675 "Mandatory FLUSH CACHE cmd " "\0" /* word 83 bit 12 */
676 "Device Configuration Overlay feature set " "\0"
677 "48-bit Address feature set " "\0" /* word 83 bit 10 */
678 "" "\0"
679 "SET MAX security extension" "\0" /* word 83 bit 8 */
680 "Address Offset Reserved Area Boot" "\0" /* word 83 bit 7 */
681 "SET FEATURES subcommand required to spinup after power up" "\0"
682 "Power-Up In Standby feature set" "\0" /* word 83 bit 5 */
683 "Removable Media Status Notification feature set" "\0"
684 "Adv. Power Management feature set" "\0" /* word 83 bit 3 */
685 "CFA feature set" "\0" /* word 83 bit 2 */
686 "READ/WRITE DMA QUEUED" "\0" /* word 83 bit 1 */
687 "DOWNLOAD MICROCODE cmd" "\0" /* word 83 bit 0 */
688 /* -------------- */
689 "" "\0" /* word 84 bit 15: !valid bit */
690 "" "\0" /* word 84 bit 14: valid bit */
691 "" "\0" /* word 84 bit 13: reserved */
692 "" "\0" /* word 84 bit 12: reserved */
693 "" "\0" /* word 84 bit 11: reserved */
694 "" "\0" /* word 84 bit 10: reserved */
695 "" "\0" /* word 84 bit 9: reserved */
696 "" "\0" /* word 84 bit 8: reserved */
697 "" "\0" /* word 84 bit 7: reserved */
698 "" "\0" /* word 84 bit 6: reserved */
699 "General Purpose Logging feature set" "\0" /* word 84 bit 5 */
700 "" "\0" /* word 84 bit 4: reserved */
701 "Media Card Pass Through Command feature set " "\0"
702 "Media serial number " "\0" /* word 84 bit 2 */
703 "SMART self-test " "\0" /* word 84 bit 1 */
704 "SMART error logging " /* word 84 bit 0 */
705;
706
707static const char secu_str[] ALIGN1 =
708 "supported" "\0" /* word 128, bit 0 */
709 "enabled" "\0" /* word 128, bit 1 */
710 "locked" "\0" /* word 128, bit 2 */
711 "frozen" "\0" /* word 128, bit 3 */
712 "expired: security count" "\0" /* word 128, bit 4 */
713 "supported: enhanced erase" /* word 128, bit 5 */
714;
715
716// Parse 512 byte disk identification block and print much crap.
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000717static void identify(uint16_t *val) NORETURN;
Denis Vlasenko4daad902007-09-27 10:20:47 +0000718static void identify(uint16_t *val)
Eric Andersen3443bd72003-07-22 07:30:36 +0000719{
Denis Vlasenko4daad902007-09-27 10:20:47 +0000720 uint16_t ii, jj, kk;
Eric Andersen3443bd72003-07-22 07:30:36 +0000721 uint16_t like_std = 1, std = 0, min_std = 0xffff;
722 uint16_t dev = NO_DEV, eqpt = NO_DEV;
723 uint8_t have_mode = 0, err_dma = 0;
724 uint8_t chksum = 0;
725 uint32_t ll, mm, nn, oo;
Rob Landley2e2d7522006-04-29 15:23:33 +0000726 uint64_t bbbig; /* (:) */
Rob Landleyadde7982006-05-16 15:32:30 +0000727 const char *strng;
Denis Vlasenko4daad902007-09-27 10:20:47 +0000728#if BB_BIG_ENDIAN
729 uint16_t buf[256];
Eric Andersen3443bd72003-07-22 07:30:36 +0000730
Denis Vlasenko4daad902007-09-27 10:20:47 +0000731 // Adjust for endianness
732 swab(val, buf, sizeof(buf));
733 val = buf;
734#endif
Denys Vlasenkob22bbff2009-07-04 16:50:43 +0200735 /* check if we recognize the device type */
Denis Vlasenko4daad902007-09-27 10:20:47 +0000736 bb_putchar('\n');
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000737 if (!(val[GEN_CONFIG] & NOT_ATA)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000738 dev = ATA_DEV;
739 printf("ATA device, with ");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000740 } else if (val[GEN_CONFIG]==CFA_SUPPORT_VAL) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000741 dev = ATA_DEV;
742 like_std = 4;
743 printf("CompactFlash ATA device, with ");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000744 } else if (!(val[GEN_CONFIG] & NOT_ATAPI)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000745 dev = ATAPI_DEV;
746 eqpt = (val[GEN_CONFIG] & EQPT_TYPE) >> SHIFT_EQPT;
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000747 printf("ATAPI %s, with ", eqpt <= 0xf ? nth_string(pkt_str, eqpt) : "unknown");
Eric Andersen3443bd72003-07-22 07:30:36 +0000748 like_std = 3;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000749 } else
Denis Vlasenko91303402007-10-30 19:36:54 +0000750 /* "Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n" */
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +0000751 bb_error_msg_and_die("unknown device type");
Eric Andersen3443bd72003-07-22 07:30:36 +0000752
Rob Landleyadde7982006-05-16 15:32:30 +0000753 printf("%sremovable media\n", !(val[GEN_CONFIG] & MEDIA_REMOVABLE) ? "non-" : "");
Eric Andersen3443bd72003-07-22 07:30:36 +0000754 /* Info from the specific configuration word says whether or not the
755 * ID command completed correctly. It is only defined, however in
Glenn L McGrath07085852003-10-09 07:28:22 +0000756 * ATA/ATAPI-5 & 6; it is reserved (value theoretically 0) in prior
Eric Andersen3443bd72003-07-22 07:30:36 +0000757 * standards. Since the values allowed for this word are extremely
758 * specific, it should be safe to check it now, even though we don't
759 * know yet what standard this device is using.
760 */
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000761 if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL)
762 || (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL)
763 ) {
Glenn L McGrath07085852003-10-09 07:28:22 +0000764 like_std = 5;
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000765 if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL))
Rob Landleyadde7982006-05-16 15:32:30 +0000766 printf("powers-up in standby; SET FEATURES subcmd spins-up.\n");
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000767 if (((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==PWRD_NID_VAL)) && (val[GEN_CONFIG] & INCOMPLETE))
Rob Landleyadde7982006-05-16 15:32:30 +0000768 printf("\n\tWARNING: ID response incomplete.\n\tFollowing data may be incorrect.\n\n");
Eric Andersen3443bd72003-07-22 07:30:36 +0000769 }
770
771 /* output the model and serial numbers and the fw revision */
Glenn L McGrath07085852003-10-09 07:28:22 +0000772 xprint_ascii(val, START_MODEL, "Model Number:", LENGTH_MODEL);
773 xprint_ascii(val, START_SERIAL, "Serial Number:", LENGTH_SERIAL);
774 xprint_ascii(val, START_FW_REV, "Firmware Revision:", LENGTH_FW_REV);
775 xprint_ascii(val, START_MEDIA, "Media Serial Num:", LENGTH_MEDIA);
776 xprint_ascii(val, START_MANUF, "Media Manufacturer:", LENGTH_MANUF);
Eric Andersen3443bd72003-07-22 07:30:36 +0000777
778 /* major & minor standards version number (Note: these words were not
779 * defined until ATA-3 & the CDROM std uses different words.) */
780 printf("Standards:");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000781 if (eqpt != CDROM) {
782 if (val[MINOR] && (val[MINOR] <= MINOR_MAX)) {
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000783 if (like_std < 3) like_std = 3;
Eric Andersen3443bd72003-07-22 07:30:36 +0000784 std = actual_ver[val[MINOR]];
Denys Vlasenkof3ea7922010-07-26 01:06:14 +0200785 if (std)
786 printf("\n\tUsed: %s ", nth_string(minor_str, val[MINOR]));
Eric Andersen3443bd72003-07-22 07:30:36 +0000787 }
788 /* looks like when they up-issue the std, they obsolete one;
Glenn L McGrath07085852003-10-09 07:28:22 +0000789 * thus, only the newest 4 issues need be supported. (That's
Eric Andersen3443bd72003-07-22 07:30:36 +0000790 * what "kk" and "min_std" are all about.) */
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000791 if (val[MAJOR] && (val[MAJOR] != NOVAL_1)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000792 printf("\n\tSupported: ");
793 jj = val[MAJOR] << 1;
794 kk = like_std >4 ? like_std-4: 0;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000795 for (ii = 14; (ii >0)&&(ii>kk); ii--) {
796 if (jj & 0x8000) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000797 printf("%u ", ii);
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000798 if (like_std < ii) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000799 like_std = ii;
800 kk = like_std >4 ? like_std-4: 0;
801 }
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000802 if (min_std > ii) min_std = ii;
Eric Andersen3443bd72003-07-22 07:30:36 +0000803 }
804 jj <<= 1;
805 }
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000806 if (like_std < 3) like_std = 3;
Eric Andersen3443bd72003-07-22 07:30:36 +0000807 }
808 /* Figure out what standard the device is using if it hasn't told
809 * us. If we know the std, check if the device is using any of
810 * the words from the next level up. It happens.
811 */
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000812 if (like_std < std) like_std = std;
Glenn L McGrath07085852003-10-09 07:28:22 +0000813
Rob Landleya3e4f382006-04-29 16:06:31 +0000814 if (((std == 5) || (!std && (like_std < 6))) &&
Glenn L McGrath07085852003-10-09 07:28:22 +0000815 ((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
816 (( val[CMDS_SUPP_1] & CMDS_W83) > 0x00ff)) ||
817 ((( val[CMDS_SUPP_2] & VALID) == VALID_VAL) &&
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000818 ( val[CMDS_SUPP_2] & CMDS_W84) ) )
819 ) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000820 like_std = 6;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000821 } else if (((std == 4) || (!std && (like_std < 5))) &&
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000822 ((((val[INTEGRITY] & SIG) == SIG_VAL) && !chksum) ||
Glenn L McGrath07085852003-10-09 07:28:22 +0000823 (( val[HWRST_RSLT] & VALID) == VALID_VAL) ||
824 ((( val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
825 (( val[CMDS_SUPP_1] & CMDS_W83) > 0x001f)) ) )
826 {
Eric Andersen3443bd72003-07-22 07:30:36 +0000827 like_std = 5;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000828 } else if (((std == 3) || (!std && (like_std < 4))) &&
Glenn L McGrath07085852003-10-09 07:28:22 +0000829 ((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) &&
830 ((( val[CMDS_SUPP_1] & CMDS_W83) > 0x0000) ||
831 (( val[CMDS_SUPP_0] & CMDS_W82) > 0x000f))) ||
832 (( val[CAPAB_1] & VALID) == VALID_VAL) ||
833 (( val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) ||
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000834 (( val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) )
835 ) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000836 like_std = 4;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000837 } else if (((std == 2) || (!std && (like_std < 3)))
838 && ((val[CMDS_SUPP_1] & VALID) == VALID_VAL)
839 ) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000840 like_std = 3;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000841 } else if (((std == 1) || (!std && (like_std < 2))) &&
Glenn L McGrath07085852003-10-09 07:28:22 +0000842 ((val[CAPAB_0] & (IORDY_SUP | IORDY_OFF)) ||
843 (val[WHATS_VALID] & OK_W64_70)) )
844 {
Eric Andersen3443bd72003-07-22 07:30:36 +0000845 like_std = 2;
846 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000847
Rob Landleya3e4f382006-04-29 16:06:31 +0000848 if (!std)
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000849 printf("\n\tLikely used: %u\n", like_std);
Rob Landleya3e4f382006-04-29 16:06:31 +0000850 else if (like_std > std)
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000851 printf("& some of %u\n", like_std);
Glenn L McGrath07085852003-10-09 07:28:22 +0000852 else
Denis Vlasenko4daad902007-09-27 10:20:47 +0000853 bb_putchar('\n');
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000854 } else {
Eric Andersen3443bd72003-07-22 07:30:36 +0000855 /* TBD: do CDROM stuff more thoroughly. For now... */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000856 kk = 0;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000857 if (val[CDR_MINOR] == 9) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000858 kk = 1;
859 printf("\n\tUsed: ATAPI for CD-ROMs, SFF-8020i, r2.5");
860 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000861 if (val[CDR_MAJOR] && (val[CDR_MAJOR] !=NOVAL_1)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000862 kk = 1;
863 printf("\n\tSupported: CD-ROM ATAPI");
864 jj = val[CDR_MAJOR] >> 1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000865 for (ii = 1; ii < 15; ii++) {
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000866 if (jj & 0x0001) printf("-%u ", ii);
Eric Andersen3443bd72003-07-22 07:30:36 +0000867 jj >>= 1;
868 }
869 }
Denis Vlasenkofeb7ae72007-10-01 12:05:12 +0000870 puts(kk ? "" : "\n\tLikely used CD-ROM ATAPI-1");
Eric Andersen3443bd72003-07-22 07:30:36 +0000871 /* the cdrom stuff is more like ATA-2 than anything else, so: */
872 like_std = 2;
873 }
874
Rob Landleya3e4f382006-04-29 16:06:31 +0000875 if (min_std == 0xffff)
Glenn L McGrath07085852003-10-09 07:28:22 +0000876 min_std = like_std > 4 ? like_std - 3 : 1;
Eric Andersen3443bd72003-07-22 07:30:36 +0000877
878 printf("Configuration:\n");
879 /* more info from the general configuration word */
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000880 if ((eqpt != CDROM) && (like_std == 1)) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000881 jj = val[GEN_CONFIG] >> 1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000882 for (ii = 1; ii < 15; ii++) {
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000883 if (jj & 0x0001)
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000884 printf("\t%s\n", nth_string(ata1_cfg_str, ii));
Eric Andersen3443bd72003-07-22 07:30:36 +0000885 jj >>=1;
886 }
887 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000888 if (dev == ATAPI_DEV) {
Rob Landleyadde7982006-05-16 15:32:30 +0000889 if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_3MS_VAL)
890 strng = "3ms";
891 else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_INTR_VAL)
892 strng = "<=10ms with INTRQ";
893 else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_50US_VAL)
894 strng ="50us";
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000895 else
Denis Vlasenko91303402007-10-30 19:36:54 +0000896 strng = "unknown";
Rob Landleyadde7982006-05-16 15:32:30 +0000897 printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */
898
899 if ((val[GEN_CONFIG] & PKT_SIZE_SUPPORTED) == PKT_SIZE_12_VAL)
900 strng = "12 bytes";
901 else if ((val[GEN_CONFIG] & PKT_SIZE_SUPPORTED) == PKT_SIZE_16_VAL)
902 strng = "16 bytes";
903 else
Denis Vlasenko91303402007-10-30 19:36:54 +0000904 strng = "unknown";
Rob Landleyadde7982006-05-16 15:32:30 +0000905 puts(strng);
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000906 } else {
Glenn L McGrath07085852003-10-09 07:28:22 +0000907 /* addressing...CHS? See section 6.2 of ATA specs 4 or 5 */
Eric Andersen3443bd72003-07-22 07:30:36 +0000908 ll = (uint32_t)val[LBA_SECTS_MSB] << 16 | val[LBA_SECTS_LSB];
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200909 mm = 0;
910 bbbig = 0;
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000911 if ((ll > 0x00FBFC10) && (!val[LCYLS]))
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000912 printf("\tCHS addressing not supported\n");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000913 else {
Eric Andersen3443bd72003-07-22 07:30:36 +0000914 jj = val[WHATS_VALID] & OK_W54_58;
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200915 printf("\tLogical\t\tmax\tcurrent\n"
916 "\tcylinders\t%u\t%u\n"
917 "\theads\t\t%u\t%u\n"
918 "\tsectors/track\t%u\t%u\n"
919 "\t--\n",
920 val[LCYLS],
921 jj ? val[LCYLS_CUR] : 0,
922 val[LHEADS],
923 jj ? val[LHEADS_CUR] : 0,
924 val[LSECTS],
925 jj ? val[LSECTS_CUR] : 0);
Glenn L McGrath07085852003-10-09 07:28:22 +0000926
Rob Landleyadde7982006-05-16 15:32:30 +0000927 if ((min_std == 1) && (val[TRACK_BYTES] || val[SECT_BYTES]))
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200928 printf("\tbytes/track: %u\tbytes/sector: %u\n",
929 val[TRACK_BYTES], val[SECT_BYTES]);
Glenn L McGrath07085852003-10-09 07:28:22 +0000930
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000931 if (jj) {
Eric Andersen3443bd72003-07-22 07:30:36 +0000932 mm = (uint32_t)val[CAPACITY_MSB] << 16 | val[CAPACITY_LSB];
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000933 if (like_std < 3) {
934 /* check Endian of capacity bytes */
Eric Andersen3443bd72003-07-22 07:30:36 +0000935 nn = val[LCYLS_CUR] * val[LHEADS_CUR] * val[LSECTS_CUR];
936 oo = (uint32_t)val[CAPACITY_LSB] << 16 | val[CAPACITY_MSB];
Rob Landleya3e4f382006-04-29 16:06:31 +0000937 if (abs(mm - nn) > abs(oo - nn))
Eric Andersen3443bd72003-07-22 07:30:36 +0000938 mm = oo;
939 }
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000940 printf("\tCHS current addressable sectors:%11u\n", mm);
Glenn L McGrath07085852003-10-09 07:28:22 +0000941 }
Eric Andersen3443bd72003-07-22 07:30:36 +0000942 }
943 /* LBA addressing */
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000944 printf("\tLBA user addressable sectors:%11u\n", ll);
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000945 if (((val[CMDS_SUPP_1] & VALID) == VALID_VAL)
946 && (val[CMDS_SUPP_1] & SUPPORT_48_BIT)
947 ) {
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +0000948 bbbig = (uint64_t)val[LBA_64_MSB] << 48 |
949 (uint64_t)val[LBA_48_MSB] << 32 |
950 (uint64_t)val[LBA_MID] << 16 |
Denis Vlasenko6963eb52007-05-22 21:46:11 +0000951 val[LBA_LSB];
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000952 printf("\tLBA48 user addressable sectors:%11"PRIu64"\n", bbbig);
Eric Andersen3443bd72003-07-22 07:30:36 +0000953 }
Glenn L McGrath07085852003-10-09 07:28:22 +0000954
955 if (!bbbig)
Rob Landley2e2d7522006-04-29 15:23:33 +0000956 bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000957 printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11);
958 bbbig = (bbbig << 9) / 1000000;
959 printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig);
Glenn L McGrath07085852003-10-09 07:28:22 +0000960
Rob Landleyadde7982006-05-16 15:32:30 +0000961 if (bbbig > 1000)
Rob Landley81dab2c2006-05-28 01:56:08 +0000962 printf("(%"PRIu64" GB)\n", bbbig/1000);
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000963 else
Denis Vlasenko4daad902007-09-27 10:20:47 +0000964 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +0000965 }
966
967 /* hw support of commands (capabilities) */
Glenn L McGrath07085852003-10-09 07:28:22 +0000968 printf("Capabilities:\n\t");
969
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000970 if (dev == ATAPI_DEV) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200971 if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP))
972 printf("Cmd queuing, ");
973 if (val[CAPAB_0] & OVLP_SUP)
974 printf("Cmd overlap, ");
Eric Andersen3443bd72003-07-22 07:30:36 +0000975 }
Rob Landleyadde7982006-05-16 15:32:30 +0000976 if (val[CAPAB_0] & LBA_SUP) printf("LBA, ");
Glenn L McGrath07085852003-10-09 07:28:22 +0000977
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000978 if (like_std != 1) {
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000979 printf("IORDY%s(can%s be disabled)\n",
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200980 !(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "",
981 (val[CAPAB_0] & IORDY_OFF) ? "" :"not");
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000982 } else
Glenn L McGrath07085852003-10-09 07:28:22 +0000983 printf("no IORDY\n");
984
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000985 if ((like_std == 1) && val[BUF_TYPE]) {
Rob Landleyadde7982006-05-16 15:32:30 +0000986 printf("\tBuffer type: %04x: %s%s\n", val[BUF_TYPE],
Denys Vlasenko6d335be2009-05-20 14:48:03 +0200987 (val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector",
988 (val[BUF_TYPE] > 2) ? " with read caching ability" : "");
Eric Andersen3443bd72003-07-22 07:30:36 +0000989 }
Rob Landleyadde7982006-05-16 15:32:30 +0000990
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000991 if ((min_std == 1) && (val[BUFFER__SIZE] && (val[BUFFER__SIZE] != NOVAL_1))) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000992 printf("\tBuffer size: %.1fkB\n", (float)val[BUFFER__SIZE]/2);
Eric Andersen3443bd72003-07-22 07:30:36 +0000993 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000994 if ((min_std < 4) && (val[RW_LONG])) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000995 printf("\tbytes avail on r/w long: %u\n", val[RW_LONG]);
Eric Andersen3443bd72003-07-22 07:30:36 +0000996 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +0000997 if ((eqpt != CDROM) && (like_std > 3)) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +0000998 printf("\tQueue depth: %u\n", (val[QUEUE_DEPTH] & DEPTH_BITS) + 1);
Eric Andersen3443bd72003-07-22 07:30:36 +0000999 }
Glenn L McGrath07085852003-10-09 07:28:22 +00001000
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001001 if (dev == ATA_DEV) {
Rob Landleya3e4f382006-04-29 16:06:31 +00001002 if (like_std == 1)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001003 printf("\tCan%s perform double-word IO\n", (!val[DWORD_IO]) ? "not" : "");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001004 else {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001005 printf("\tStandby timer values: spec'd by %s",
1006 (val[CAPAB_0] & STD_STBY) ? "standard" : "vendor");
Rob Landleya3e4f382006-04-29 16:06:31 +00001007 if ((like_std > 3) && ((val[CAPAB_1] & VALID) == VALID_VAL))
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001008 printf(", %s device specific minimum\n",
1009 (val[CAPAB_1] & MIN_STANDBY_TIMER) ? "with" : "no");
Glenn L McGrath07085852003-10-09 07:28:22 +00001010 else
Denis Vlasenko4daad902007-09-27 10:20:47 +00001011 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001012 }
1013 printf("\tR/W multiple sector transfer: ");
Rob Landleya3e4f382006-04-29 16:06:31 +00001014 if ((like_std < 3) && !(val[SECTOR_XFER_MAX] & SECTOR_XFER))
Eric Andersen3443bd72003-07-22 07:30:36 +00001015 printf("not supported\n");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001016 else {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001017 printf("Max = %u\tCurrent = ", val[SECTOR_XFER_MAX] & SECTOR_XFER);
Rob Landleyadde7982006-05-16 15:32:30 +00001018 if (val[SECTOR_XFER_CUR] & MULTIPLE_SETTING_VALID)
1019 printf("%u\n", val[SECTOR_XFER_CUR] & SECTOR_XFER);
1020 else
1021 printf("?\n");
Eric Andersen3443bd72003-07-22 07:30:36 +00001022 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001023 if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008)) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001024 /* We print out elsewhere whether the APM feature is enabled or
1025 not. If it's not enabled, let's not repeat the info; just print
1026 nothing here. */
Glenn L McGrath07085852003-10-09 07:28:22 +00001027 printf("\tAdvancedPM level: ");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001028 if ((val[ADV_PWR] & 0xFF00) == 0x4000) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001029 uint8_t apm_level = val[ADV_PWR] & 0x00FF;
Eric Andersen3443bd72003-07-22 07:30:36 +00001030 printf("%u (0x%x)\n", apm_level, apm_level);
Glenn L McGrath07085852003-10-09 07:28:22 +00001031 }
1032 else
Eric Andersen3443bd72003-07-22 07:30:36 +00001033 printf("unknown setting (0x%04x)\n", val[ADV_PWR]);
Eric Andersen3443bd72003-07-22 07:30:36 +00001034 }
Rob Landleyadde7982006-05-16 15:32:30 +00001035 if (like_std > 5 && val[ACOUSTIC]) {
1036 printf("\tRecommended acoustic management value: %u, current value: %u\n",
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001037 (val[ACOUSTIC] >> 8) & 0x00ff,
1038 val[ACOUSTIC] & 0x00ff);
Eric Andersen3443bd72003-07-22 07:30:36 +00001039 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001040 } else {
Glenn L McGrath07085852003-10-09 07:28:22 +00001041 /* ATAPI */
Rob Landleyadde7982006-05-16 15:32:30 +00001042 if (eqpt != CDROM && (val[CAPAB_0] & SWRST_REQ))
1043 printf("\tATA sw reset required\n");
Glenn L McGrath07085852003-10-09 07:28:22 +00001044
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001045 if (val[PKT_REL] || val[SVC_NBSY]) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001046 printf("\tOverlap support:");
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001047 if (val[PKT_REL])
1048 printf(" %uus to release bus.", val[PKT_REL]);
1049 if (val[SVC_NBSY])
1050 printf(" %uus to clear BSY after SERVICE cmd.",
1051 val[SVC_NBSY]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001052 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001053 }
1054 }
1055
1056 /* DMA stuff. Check that only one DMA mode is selected. */
1057 printf("\tDMA: ");
Rob Landleya3e4f382006-04-29 16:06:31 +00001058 if (!(val[CAPAB_0] & DMA_SUP))
Eric Andersen3443bd72003-07-22 07:30:36 +00001059 printf("not supported\n");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001060 else {
Rob Landleyadde7982006-05-16 15:32:30 +00001061 if (val[DMA_MODE] && !val[SINGLE_DMA] && !val[MULTI_DMA])
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001062 printf(" sdma%u\n", (val[DMA_MODE] & MODE) >> 8);
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001063 if (val[SINGLE_DMA]) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001064 jj = val[SINGLE_DMA];
1065 kk = val[SINGLE_DMA] >> 8;
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001066 err_dma += mode_loop(jj, kk, 's', &have_mode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001067 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001068 if (val[MULTI_DMA]) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001069 jj = val[MULTI_DMA];
1070 kk = val[MULTI_DMA] >> 8;
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001071 err_dma += mode_loop(jj, kk, 'm', &have_mode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001072 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001073 if ((val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001074 jj = val[ULTRA_DMA];
1075 kk = val[ULTRA_DMA] >> 8;
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001076 err_dma += mode_loop(jj, kk, 'u', &have_mode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001077 }
Rob Landleyadde7982006-05-16 15:32:30 +00001078 if (err_dma || !have_mode) printf("(?)");
Denis Vlasenko4daad902007-09-27 10:20:47 +00001079 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001080
Rob Landleyadde7982006-05-16 15:32:30 +00001081 if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP))
1082 printf("\t\tInterleaved DMA support\n");
Eric Andersen3443bd72003-07-22 07:30:36 +00001083
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001084 if ((val[WHATS_VALID] & OK_W64_70)
1085 && (val[DMA_TIME_MIN] || val[DMA_TIME_NORM])
1086 ) {
Rob Landleyadde7982006-05-16 15:32:30 +00001087 printf("\t\tCycle time:");
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001088 if (val[DMA_TIME_MIN]) printf(" min=%uns", val[DMA_TIME_MIN]);
1089 if (val[DMA_TIME_NORM]) printf(" recommended=%uns", val[DMA_TIME_NORM]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001090 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001091 }
1092 }
1093
1094 /* Programmed IO stuff */
1095 printf("\tPIO: ");
Tim Rikerc1ef7bd2006-01-25 00:08:53 +00001096 /* If a drive supports mode n (e.g. 3), it also supports all modes less
Eric Andersen3443bd72003-07-22 07:30:36 +00001097 * than n (e.g. 3, 2, 1 and 0). Print all the modes. */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001098 if ((val[WHATS_VALID] & OK_W64_70) && (val[ADV_PIO_MODES] & PIO_SUP)) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001099 jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007;
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001100 for (ii = 0; ii <= PIO_MODE_MAX; ii++) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001101 if (jj & 0x0001) printf("pio%d ", ii);
Eric Andersen3443bd72003-07-22 07:30:36 +00001102 jj >>=1;
1103 }
Denis Vlasenko4daad902007-09-27 10:20:47 +00001104 bb_putchar('\n');
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001105 } else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) {
Rob Landleya3e4f382006-04-29 16:06:31 +00001106 for (ii = 0; ii <= val[PIO_MODE]>>8; ii++)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001107 printf("pio%d ", ii);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001108 bb_putchar('\n');
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001109 } else
Denis Vlasenko91303402007-10-30 19:36:54 +00001110 puts("unknown");
Glenn L McGrath07085852003-10-09 07:28:22 +00001111
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001112 if (val[WHATS_VALID] & OK_W64_70) {
1113 if (val[PIO_NO_FLOW] || val[PIO_FLOW]) {
Rob Landleyadde7982006-05-16 15:32:30 +00001114 printf("\t\tCycle time:");
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001115 if (val[PIO_NO_FLOW])
1116 printf(" no flow control=%uns", val[PIO_NO_FLOW]);
1117 if (val[PIO_FLOW])
1118 printf(" IORDY flow control=%uns", val[PIO_FLOW]);
Denis Vlasenko4daad902007-09-27 10:20:47 +00001119 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001120 }
1121 }
1122
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001123 if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001124 printf("Commands/features:\n"
1125 "\tEnabled\tSupported:\n");
Eric Andersen3443bd72003-07-22 07:30:36 +00001126 jj = val[CMDS_SUPP_0];
1127 kk = val[CMDS_EN_0];
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001128 for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++) {
Denis Vlasenkobfc3d822007-11-04 04:10:17 +00001129 const char *feat_str = nth_string(cmd_feat_str, ii);
Denis Vlasenko91303402007-10-30 19:36:54 +00001130 if ((jj & 0x8000) && (*feat_str != '\0')) {
1131 printf("\t%s\t%s\n", (kk & 0x8000) ? " *" : "", feat_str);
Eric Andersen3443bd72003-07-22 07:30:36 +00001132 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001133 jj <<= 1;
1134 kk <<= 1;
1135 if (ii % 16 == 15) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001136 jj = val[CMDS_SUPP_0+1+(ii/16)];
1137 kk = val[CMDS_EN_0+1+(ii/16)];
1138 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001139 if (ii == 31) {
Rob Landleya3e4f382006-04-29 16:06:31 +00001140 if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL)
Glenn L McGrath07085852003-10-09 07:28:22 +00001141 ii +=16;
Eric Andersen3443bd72003-07-22 07:30:36 +00001142 }
1143 }
1144 }
Rob Landleyadde7982006-05-16 15:32:30 +00001145 /* Removable Media Status Notification feature set */
Denis Vlasenko67b23e62006-10-03 21:00:06 +00001146 if ((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP)
Denis Vlasenkobfc3d822007-11-04 04:10:17 +00001147 printf("\t%s supported\n", nth_string(cmd_feat_str, 27));
Glenn L McGrath07085852003-10-09 07:28:22 +00001148
Eric Andersen3443bd72003-07-22 07:30:36 +00001149 /* security */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001150 if ((eqpt != CDROM) && (like_std > 3)
1151 && (val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME])
1152 ) {
Rob Landleyade7f952006-05-25 18:53:06 +00001153 printf("Security:\n");
Rob Landleyadde7982006-05-16 15:32:30 +00001154 if (val[PSWD_CODE] && (val[PSWD_CODE] != NOVAL_1))
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001155 printf("\tMaster password revision code = %u\n", val[PSWD_CODE]);
Eric Andersen3443bd72003-07-22 07:30:36 +00001156 jj = val[SECU_STATUS];
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001157 if (jj) {
1158 for (ii = 0; ii < NUM_SECU_STR; ii++) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001159 printf("\t%s\t%s\n",
1160 (!(jj & 0x0001)) ? "not" : "",
1161 nth_string(secu_str, ii));
Eric Andersen3443bd72003-07-22 07:30:36 +00001162 jj >>=1;
1163 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001164 if (val[SECU_STATUS] & SECU_ENABLED) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001165 printf("\tSecurity level %s\n",
1166 (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high");
Eric Andersen3443bd72003-07-22 07:30:36 +00001167 }
1168 }
1169 jj = val[ERASE_TIME] & ERASE_BITS;
1170 kk = val[ENH_ERASE_TIME] & ERASE_BITS;
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001171 if (jj || kk) {
Denis Vlasenko7d60fc12008-06-05 06:51:06 +00001172 bb_putchar('\t');
Rob Landleyade7f952006-05-25 18:53:06 +00001173 if (jj) printf("%umin for %sSECURITY ERASE UNIT. ", jj==ERASE_BITS ? 508 : jj<<1, "");
1174 if (kk) printf("%umin for %sSECURITY ERASE UNIT. ", kk==ERASE_BITS ? 508 : kk<<1, "ENHANCED ");
Denis Vlasenko4daad902007-09-27 10:20:47 +00001175 bb_putchar('\n');
Eric Andersen3443bd72003-07-22 07:30:36 +00001176 }
1177 }
1178
1179 /* reset result */
Rob Landleyadde7982006-05-16 15:32:30 +00001180 jj = val[HWRST_RSLT];
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001181 if ((jj & VALID) == VALID_VAL) {
Denis Vlasenko6bef3d12007-11-06 03:05:54 +00001182 oo = (jj & RST0);
1183 if (!oo)
Rob Landleyadde7982006-05-16 15:32:30 +00001184 jj >>= 8;
Rob Landleya3e4f382006-04-29 16:06:31 +00001185 if ((jj & DEV_DET) == JUMPER_VAL)
Rob Landleyadde7982006-05-16 15:32:30 +00001186 strng = " determined by the jumper";
Rob Landleya3e4f382006-04-29 16:06:31 +00001187 else if ((jj & DEV_DET) == CSEL_VAL)
Rob Landleyadde7982006-05-16 15:32:30 +00001188 strng = " determined by CSEL";
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00001189 else
Rob Landleyadde7982006-05-16 15:32:30 +00001190 strng = "";
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001191 printf("HW reset results:\n"
1192 "\tCBLID- %s Vih\n"
1193 "\tDevice num = %i%s\n",
1194 (val[HWRST_RSLT] & CBLID) ? "above" : "below",
1195 !(oo), strng);
Eric Andersen3443bd72003-07-22 07:30:36 +00001196 }
1197
1198 /* more stuff from std 5 */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001199 if ((like_std > 4) && (eqpt != CDROM)) {
1200 if (val[CFA_PWR_MODE] & VALID_W160) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001201 printf("CFA power mode 1:\n"
1202 "\t%s%s\n",
1203 (val[CFA_PWR_MODE] & PWR_MODE_OFF) ? "disabled" : "enabled",
1204 (val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : "");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001205 if (val[CFA_PWR_MODE] & MAX_AMPS)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001206 printf("\tMaximum current = %uma\n", val[CFA_PWR_MODE] & MAX_AMPS);
Eric Andersen3443bd72003-07-22 07:30:36 +00001207 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001208 if ((val[INTEGRITY] & SIG) == SIG_VAL) {
Rob Landleyadde7982006-05-16 15:32:30 +00001209 printf("Checksum: %scorrect\n", chksum ? "in" : "");
Eric Andersen3443bd72003-07-22 07:30:36 +00001210 }
1211 }
1212
Rob Landleyadde7982006-05-16 15:32:30 +00001213 exit(EXIT_SUCCESS);
Eric Andersen3443bd72003-07-22 07:30:36 +00001214}
1215#endif
1216
Eric Andersen3443bd72003-07-22 07:30:36 +00001217// Historically, if there was no HDIO_OBSOLETE_IDENTITY, then
1218// then the HDIO_GET_IDENTITY only returned 142 bytes.
1219// Otherwise, HDIO_OBSOLETE_IDENTITY returns 142 bytes,
1220// and HDIO_GET_IDENTITY returns 512 bytes. But the latest
1221// 2.5.xx kernels no longer define HDIO_OBSOLETE_IDENTITY
1222// (which they should, but they should just return -EINVAL).
1223//
1224// So.. we must now assume that HDIO_GET_IDENTITY returns 512 bytes.
1225// On a really old system, it will not, and we will be confused.
1226// Too bad, really.
1227
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001228#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
Denis Vlasenko91303402007-10-30 19:36:54 +00001229static const char cfg_str[] ALIGN1 =
Denis Vlasenko6b404432008-01-07 16:13:14 +00001230 """\0" "HardSect""\0" "SoftSect""\0" "NotMFM""\0"
1231 "HdSw>15uSec""\0" "SpinMotCtl""\0" "Fixed""\0" "Removeable""\0"
1232 "DTR<=5Mbs""\0" "DTR>5Mbs""\0" "DTR>10Mbs""\0" "RotSpdTol>.5%""\0"
1233 "dStbOff""\0" "TrkOff""\0" "FmtGapReq""\0" "nonMagnetic"
Denis Vlasenko91303402007-10-30 19:36:54 +00001234;
Eric Andersen3443bd72003-07-22 07:30:36 +00001235
Denis Vlasenko91303402007-10-30 19:36:54 +00001236static const char BuffType[] ALIGN1 =
1237 "unknown""\0" "1Sect""\0" "DualPort""\0" "DualPortCache"
1238;
Eric Andersen3443bd72003-07-22 07:30:36 +00001239
Denys Vlasenkoa7bb3c12009-10-08 12:28:08 +02001240static NOINLINE void dump_identity(const struct hd_driveid *id)
Eric Andersen3443bd72003-07-22 07:30:36 +00001241{
1242 int i;
Denis Vlasenko284d0fa2008-02-16 13:18:17 +00001243 const unsigned short *id_regs = (const void*) id;
Rob Landley0a7c8ef2006-02-22 17:01:00 +00001244
Glenn L McGrath07085852003-10-09 07:28:22 +00001245 printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n Config={",
1246 id->model, id->fw_rev, id->serial_no);
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001247 for (i = 0; i <= 15; i++) {
Rob Landleyade7f952006-05-25 18:53:06 +00001248 if (id->config & (1<<i))
Denis Vlasenkobfc3d822007-11-04 04:10:17 +00001249 printf(" %s", nth_string(cfg_str, i));
Rob Landleyadde7982006-05-16 15:32:30 +00001250 }
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001251 printf(" }\n RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n"
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001252 " BuffType=(%u) %s, BuffSize=%ukB, MaxMultSect=%u",
1253 id->cyls, id->heads, id->sectors, id->track_bytes,
1254 id->sector_bytes, id->ecc_bytes,
1255 id->buf_type,
1256 nth_string(BuffType, (id->buf_type > 3) ? 0 : id->buf_type),
1257 id->buf_size/2, id->max_multsect);
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001258 if (id->max_multsect) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001259 printf(", MultSect=");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001260 if (!(id->multsect_valid & 1))
Eric Andersen3443bd72003-07-22 07:30:36 +00001261 printf("?%u?", id->multsect);
1262 else if (id->multsect)
1263 printf("%u", id->multsect);
1264 else
1265 printf("off");
1266 }
Denis Vlasenko4daad902007-09-27 10:20:47 +00001267 bb_putchar('\n');
Rob Landleyade7f952006-05-25 18:53:06 +00001268
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001269 if (!(id->field_valid & 1))
Rob Landleyade7f952006-05-25 18:53:06 +00001270 printf(" (maybe):");
1271
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001272 printf(" CurCHS=%u/%u/%u, CurSects=%lu, LBA=%s", id->cur_cyls, id->cur_heads,
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001273 id->cur_sectors,
1274 (BB_BIG_ENDIAN) ?
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001275 (unsigned long)(id->cur_capacity0 << 16) | id->cur_capacity1 :
1276 (unsigned long)(id->cur_capacity1 << 16) | id->cur_capacity0,
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001277 ((id->capability&2) == 0) ? "no" : "yes");
Rob Landleyade7f952006-05-25 18:53:06 +00001278
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001279 if (id->capability & 2)
Rob Landleyade7f952006-05-25 18:53:06 +00001280 printf(", LBAsects=%u", id->lba_capacity);
1281
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001282 printf("\n IORDY=%s",
1283 (id->capability & 8)
1284 ? ((id->capability & 4) ? "on/off" : "yes")
1285 : "no");
Rob Landleyade7f952006-05-25 18:53:06 +00001286
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001287 if (((id->capability & 8) || (id->field_valid & 2)) && (id->field_valid & 2))
Rob Landleyade7f952006-05-25 18:53:06 +00001288 printf(", tPIO={min:%u,w/IORDY:%u}", id->eide_pio, id->eide_pio_iordy);
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00001289
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001290 if ((id->capability & 1) && (id->field_valid & 2))
Rob Landleyade7f952006-05-25 18:53:06 +00001291 printf(", tDMA={min:%u,rec:%u}", id->eide_dma_min, id->eide_dma_time);
1292
1293 printf("\n PIO modes: ");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001294 if (id->tPIO <= 5) {
Rob Landleyade7f952006-05-25 18:53:06 +00001295 printf("pio0 ");
1296 if (id->tPIO >= 1) printf("pio1 ");
1297 if (id->tPIO >= 2) printf("pio2 ");
Eric Andersen3443bd72003-07-22 07:30:36 +00001298 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001299 if (id->field_valid & 2) {
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001300 static const masks_labels_t pio_modes = {
1301 .masks = { 1, 2, ~3 },
1302 .labels = "pio3 \0""pio4 \0""pio? \0",
1303 };
1304 print_flags(&pio_modes, id->eide_pio_modes);
Rob Landleyade7f952006-05-25 18:53:06 +00001305 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001306 if (id->capability & 1) {
1307 if (id->dma_1word | id->dma_mword) {
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001308 static const int dma_wmode_masks[] = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 };
Rob Landleyade7f952006-05-25 18:53:06 +00001309 printf("\n DMA modes: ");
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001310 print_flags_separated(dma_wmode_masks,
1311 "*\0""sdma0 \0""*\0""sdma1 \0""*\0""sdma2 \0""*\0""sdma? \0",
1312 id->dma_1word, NULL);
1313 print_flags_separated(dma_wmode_masks,
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001314 "*\0""mdma0 \0""*\0""mdma1 \0""*\0""mdma2 \0""*\0""mdma? \0",
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001315 id->dma_mword, NULL);
Eric Andersen3443bd72003-07-22 07:30:36 +00001316 }
1317 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001318 if (((id->capability & 8) || (id->field_valid & 2)) && id->field_valid & 4) {
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001319 static const masks_labels_t ultra_modes1 = {
1320 .masks = { 0x100, 0x001, 0x200, 0x002, 0x400, 0x004 },
1321 .labels = "*\0""udma0 \0""*\0""udma1 \0""*\0""udma2 \0",
1322 };
Denis Vlasenko7049ff82008-06-25 09:53:17 +00001323
Rob Landleyade7f952006-05-25 18:53:06 +00001324 printf("\n UDMA modes: ");
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001325 print_flags(&ultra_modes1, id->dma_ultra);
Eric Andersen3443bd72003-07-22 07:30:36 +00001326#ifdef __NEW_HD_DRIVE_ID
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001327 if (id->hw_config & 0x2000) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001328#else /* !__NEW_HD_DRIVE_ID */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001329 if (id->word93 & 0x2000) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001330#endif /* __NEW_HD_DRIVE_ID */
Denis Vlasenko53354ac2008-06-07 15:10:29 +00001331 static const masks_labels_t ultra_modes2 = {
1332 .masks = { 0x0800, 0x0008, 0x1000, 0x0010,
1333 0x2000, 0x0020, 0x4000, 0x0040,
1334 0x8000, 0x0080 },
1335 .labels = "*\0""udma3 \0""*\0""udma4 \0"
1336 "*\0""udma5 \0""*\0""udma6 \0"
1337 "*\0""udma7 \0"
1338 };
1339 print_flags(&ultra_modes2, id->dma_ultra);
Eric Andersen3443bd72003-07-22 07:30:36 +00001340 }
1341 }
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001342 printf("\n AdvancedPM=%s", (!(id_regs[83] & 8)) ? "no" : "yes");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001343 if (id_regs[83] & 8) {
1344 if (!(id_regs[86] & 8))
Glenn L McGrath07085852003-10-09 07:28:22 +00001345 printf(": disabled (255)");
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001346 else if ((id_regs[91] & 0xFF00) != 0x4000)
Glenn L McGrath07085852003-10-09 07:28:22 +00001347 printf(": unknown setting");
1348 else
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001349 printf(": mode=0x%02X (%u)", id_regs[91] & 0xFF, id_regs[91] & 0xFF);
Glenn L McGrath07085852003-10-09 07:28:22 +00001350 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001351 if (id_regs[82] & 0x20)
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001352 printf(" WriteCache=%s", (id_regs[85] & 0x20) ? "enabled" : "disabled");
Glenn L McGrath07085852003-10-09 07:28:22 +00001353#ifdef __NEW_HD_DRIVE_ID
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001354 if ((id->minor_rev_num && id->minor_rev_num <= 31)
1355 || (id->major_rev_num && id->minor_rev_num <= 31)
1356 ) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001357 printf("\n Drive conforms to: %s: ",
1358 (id->minor_rev_num <= 31) ? nth_string(minor_str, id->minor_rev_num) : "unknown");
1359 if (id->major_rev_num != 0x0000 /* NOVAL_0 */
1360 && id->major_rev_num != 0xFFFF /* NOVAL_1 */
1361 ) {
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001362 for (i = 0; i <= 15; i++) {
Rob Landleyadde7982006-05-16 15:32:30 +00001363 if (id->major_rev_num & (1<<i))
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001364 printf(" ATA/ATAPI-%u", i);
Rob Landleyadde7982006-05-16 15:32:30 +00001365 }
Glenn L McGrath07085852003-10-09 07:28:22 +00001366 }
1367 }
Eric Andersen3443bd72003-07-22 07:30:36 +00001368#endif /* __NEW_HD_DRIVE_ID */
Rob Landleyade7f952006-05-25 18:53:06 +00001369 printf("\n\n * current active mode\n\n");
Eric Andersen3443bd72003-07-22 07:30:36 +00001370}
1371#endif
1372
Denis Vlasenko892536f2007-09-27 10:23:34 +00001373static void flush_buffer_cache(/*int fd*/ void)
Eric Andersen3443bd72003-07-22 07:30:36 +00001374{
Rob Landleya3e4f382006-04-29 16:06:31 +00001375 fsync(fd); /* flush buffers */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001376 ioctl_or_warn(fd, BLKFLSBUF, NULL); /* do it again, big time */
Eric Andersen3443bd72003-07-22 07:30:36 +00001377#ifdef HDIO_DRIVE_CMD
Glenn L McGrath07085852003-10-09 07:28:22 +00001378 sleep(1);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001379 if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) { /* await completion */
1380 if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */
1381 bb_perror_msg("HDIO_DRIVE_CMD");
1382 else
1383 bb_perror_msg("ioctl %#x failed", HDIO_DRIVE_CMD);
1384 }
Eric Andersen3443bd72003-07-22 07:30:36 +00001385#endif
1386}
1387
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001388static void seek_to_zero(/*int fd*/ void)
Eric Andersen3443bd72003-07-22 07:30:36 +00001389{
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001390 xlseek(fd, (off_t) 0, SEEK_SET);
Eric Andersen3443bd72003-07-22 07:30:36 +00001391}
1392
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001393static void read_big_block(/*int fd,*/ char *buf)
Eric Andersen3443bd72003-07-22 07:30:36 +00001394{
Rob Landleyadde7982006-05-16 15:32:30 +00001395 int i;
1396
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001397 xread(fd, buf, TIMING_BUF_BYTES);
Eric Andersen3443bd72003-07-22 07:30:36 +00001398 /* access all sectors of buf to ensure the read fully completed */
1399 for (i = 0; i < TIMING_BUF_BYTES; i += 512)
1400 buf[i] &= 1;
Eric Andersen3443bd72003-07-22 07:30:36 +00001401}
1402
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001403static unsigned dev_size_mb(/*int fd*/ void)
Rob Landleyadde7982006-05-16 15:32:30 +00001404{
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001405 union {
1406 unsigned long long blksize64;
1407 unsigned blksize32;
1408 } u;
Rob Landleyadde7982006-05-16 15:32:30 +00001409
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001410 if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // bytes
1411 u.blksize64 /= (1024 * 1024);
1412 } else {
1413 xioctl(fd, BLKGETSIZE, &u.blksize32); // sectors
1414 u.blksize64 = u.blksize32 / (2 * 1024);
Rob Landleyadde7982006-05-16 15:32:30 +00001415 }
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001416 if (u.blksize64 > UINT_MAX)
1417 return UINT_MAX;
1418 return u.blksize64;
Rob Landleyadde7982006-05-16 15:32:30 +00001419}
Eric Andersen50af12d2003-08-06 08:47:59 +00001420
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001421static void print_timing(unsigned m, unsigned elapsed_us)
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001422{
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001423 unsigned sec = elapsed_us / 1000000;
1424 unsigned hs = (elapsed_us % 1000000) / 10000;
1425
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001426 printf("%5u MB in %u.%02u seconds = %u kB/s\n",
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001427 m, sec, hs,
Denis Vlasenko0afdfdf2007-09-28 13:41:41 +00001428 /* "| 1" prevents div-by-0 */
1429 (unsigned) ((unsigned long long)m * (1024 * 1000000) / (elapsed_us | 1))
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001430 // ~= (m * 1024) / (elapsed_us / 1000000)
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001431 // = kb / elapsed_sec
1432 );
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001433}
1434
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001435static void do_time(int cache /*,int fd*/)
1436/* cache=1: time cache: repeatedly read N MB at offset 0
1437 * cache=0: time device: linear read, starting at offset 0
1438 */
Eric Andersen3443bd72003-07-22 07:30:36 +00001439{
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001440 unsigned max_iterations, iterations;
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001441 unsigned start; /* doesn't need to be long long */
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001442 unsigned elapsed, elapsed2;
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001443 unsigned total_MB;
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001444 char *buf = xmalloc(TIMING_BUF_BYTES);
Rob Landley4ae2f512006-05-19 17:24:26 +00001445
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001446 if (mlock(buf, TIMING_BUF_BYTES))
1447 bb_perror_msg_and_die("mlock");
Rob Landleyadde7982006-05-16 15:32:30 +00001448
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001449 /* Clear out the device request queues & give them time to complete.
1450 * NB: *small* delay. User is expected to have a clue and to not run
1451 * heavy io in parallel with measurements. */
Rob Landleyadde7982006-05-16 15:32:30 +00001452 sync();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001453 sleep(1);
1454 if (cache) { /* Time cache */
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001455 seek_to_zero();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001456 read_big_block(buf);
1457 printf("Timing buffer-cache reads: ");
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001458 } else { /* Time device */
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001459 printf("Timing buffered disk reads:");
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001460 }
Denys Vlasenko8131eea2009-11-02 14:19:51 +01001461 fflush_all();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001462
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001463 /* Now do the timing */
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001464 iterations = 0;
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001465 /* Max time to run (small for cache, avoids getting
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001466 * huge total_MB which can overlow unsigned type) */
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001467 elapsed2 = 510000; /* cache */
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001468 max_iterations = UINT_MAX;
1469 if (!cache) {
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001470 elapsed2 = 3000000; /* not cache */
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001471 /* Don't want to read past the end! */
1472 max_iterations = dev_size_mb() / TIMING_BUF_MB;
1473 }
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001474 start = monotonic_us();
Denis Vlasenko6963eb52007-05-22 21:46:11 +00001475 do {
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001476 if (cache)
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001477 seek_to_zero();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001478 read_big_block(buf);
1479 elapsed = (unsigned)monotonic_us() - start;
1480 ++iterations;
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001481 } while (elapsed < elapsed2 && iterations < max_iterations);
Denis Vlasenko920c52a2007-09-28 13:38:08 +00001482 total_MB = iterations * TIMING_BUF_MB;
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001483 //printf(" elapsed:%u iterations:%u ", elapsed, iterations);
1484 if (cache) {
Denis Vlasenkoa7bc9ac2007-09-28 11:21:47 +00001485 /* Cache: remove lseek() and monotonic_us() overheads
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001486 * from elapsed */
1487 start = monotonic_us();
Rob Landleyadde7982006-05-16 15:32:30 +00001488 do {
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001489 seek_to_zero();
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001490 elapsed2 = (unsigned)monotonic_us() - start;
Rob Landleyadde7982006-05-16 15:32:30 +00001491 } while (--iterations);
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001492 //printf(" elapsed2:%u ", elapsed2);
Rob Landleyadde7982006-05-16 15:32:30 +00001493 elapsed -= elapsed2;
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001494 total_MB *= 2; // BUFCACHE_FACTOR (why?)
Denis Vlasenko892536f2007-09-27 10:23:34 +00001495 flush_buffer_cache();
Glenn L McGrath07085852003-10-09 07:28:22 +00001496 }
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001497 print_timing(total_MB, elapsed);
Rob Landley4ae2f512006-05-19 17:24:26 +00001498 munlock(buf, TIMING_BUF_BYTES);
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001499 free(buf);
Eric Andersen3443bd72003-07-22 07:30:36 +00001500}
1501
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001502#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001503static void bus_state_value(unsigned value)
Eric Andersen3443bd72003-07-22 07:30:36 +00001504{
Rob Landleyadde7982006-05-16 15:32:30 +00001505 if (value == BUSSTATE_ON)
1506 on_off(1);
1507 else if (value == BUSSTATE_OFF)
1508 on_off(0);
1509 else if (value == BUSSTATE_TRISTATE)
1510 printf(" (tristate)\n");
1511 else
1512 printf(" (unknown: %d)\n", value);
Eric Andersen3443bd72003-07-22 07:30:36 +00001513}
1514#endif
1515
1516#ifdef HDIO_DRIVE_CMD
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001517static void interpret_standby(uint8_t standby)
Eric Andersen3443bd72003-07-22 07:30:36 +00001518{
Rob Landley403777f2006-08-03 20:22:37 +00001519 printf(" (");
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001520 if (standby == 0) {
Rob Landleyadde7982006-05-16 15:32:30 +00001521 printf("off");
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001522 } else if (standby <= 240 || standby == 252 || standby == 255) {
1523 /* standby is in 5 sec units */
Denys Vlasenko2b132e52009-05-20 23:21:42 +02001524 unsigned t = standby * 5;
1525 printf("%u minutes %u seconds", t / 60, t % 60);
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001526 } else if (standby <= 251) {
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001527 unsigned t = (standby - 240); /* t is in 30 min units */;
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001528 printf("%u.%c hours", t / 2, (t & 1) ? '5' : '0');
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001529 }
1530 if (standby == 253)
1531 printf("vendor-specific");
1532 if (standby == 254)
1533 printf("reserved");
Eric Andersen3443bd72003-07-22 07:30:36 +00001534 printf(")\n");
1535}
1536
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001537static const uint8_t xfermode_val[] ALIGN1 = {
1538 8, 9, 10, 11, 12, 13, 14, 15,
1539 16, 17, 18, 19, 20, 21, 22, 23,
1540 32, 33, 34, 35, 36, 37, 38, 39,
1541 64, 65, 66, 67, 68, 69, 70, 71
1542};
1543/* NB: we save size by _not_ storing terninating NUL! */
1544static const char xfermode_name[][5] ALIGN1 = {
1545 "pio0", "pio1", "pio2", "pio3", "pio4", "pio5", "pio6", "pio7",
1546 "sdma0","sdma1","sdma2","sdma3","sdma4","sdma5","sdma6","sdma7",
1547 "mdma0","mdma1","mdma2","mdma3","mdma4","mdma5","mdma6","mdma7",
1548 "udma0","udma1","udma2","udma3","udma4","udma5","udma6","udma7"
Eric Andersen3443bd72003-07-22 07:30:36 +00001549};
1550
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001551static int translate_xfermode(const char *name)
Eric Andersen3443bd72003-07-22 07:30:36 +00001552{
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00001553 int val;
1554 unsigned i;
Eric Andersen3443bd72003-07-22 07:30:36 +00001555
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001556 for (i = 0; i < ARRAY_SIZE(xfermode_val); i++) {
1557 if (!strncmp(name, xfermode_name[i], 5))
1558 if (strlen(name) <= 5)
1559 return xfermode_val[i];
Glenn L McGrath07085852003-10-09 07:28:22 +00001560 }
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001561 /* Negative numbers are invalid and are caught later */
1562 val = bb_strtoi(name, NULL, 10);
1563 if (!errno)
Glenn L McGrath07085852003-10-09 07:28:22 +00001564 return val;
Glenn L McGrath07085852003-10-09 07:28:22 +00001565 return -1;
Eric Andersen3443bd72003-07-22 07:30:36 +00001566}
1567
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001568static void interpret_xfermode(unsigned xfermode)
Eric Andersen3443bd72003-07-22 07:30:36 +00001569{
1570 printf(" (");
Rob Landleyadde7982006-05-16 15:32:30 +00001571 if (xfermode == 0)
1572 printf("default PIO mode");
1573 else if (xfermode == 1)
1574 printf("default PIO mode, disable IORDY");
1575 else if (xfermode >= 8 && xfermode <= 15)
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001576 printf("PIO flow control mode%u", xfermode - 8);
Rob Landleyadde7982006-05-16 15:32:30 +00001577 else if (xfermode >= 16 && xfermode <= 23)
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001578 printf("singleword DMA mode%u", xfermode - 16);
Rob Landleyadde7982006-05-16 15:32:30 +00001579 else if (xfermode >= 32 && xfermode <= 39)
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001580 printf("multiword DMA mode%u", xfermode - 32);
Rob Landleyadde7982006-05-16 15:32:30 +00001581 else if (xfermode >= 64 && xfermode <= 71)
Denis Vlasenkoa0319ba2007-08-16 10:37:49 +00001582 printf("UltraDMA mode%u", xfermode - 64);
Rob Landleyadde7982006-05-16 15:32:30 +00001583 else
Denis Vlasenko91303402007-10-30 19:36:54 +00001584 printf("unknown");
Eric Andersen3443bd72003-07-22 07:30:36 +00001585 printf(")\n");
1586}
1587#endif /* HDIO_DRIVE_CMD */
1588
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001589static void print_flag(int flag, const char *s, unsigned long value)
Rob Landleyadde7982006-05-16 15:32:30 +00001590{
Denis Vlasenko67b23e62006-10-03 21:00:06 +00001591 if (flag)
Rob Landleyadde7982006-05-16 15:32:30 +00001592 printf(" setting %s to %ld\n", s, value);
1593}
1594
Rob Landleya3e4f382006-04-29 16:06:31 +00001595static void process_dev(char *devname)
Eric Andersen3443bd72003-07-22 07:30:36 +00001596{
Denis Vlasenko892536f2007-09-27 10:23:34 +00001597 /*int fd;*/
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001598 long parm, multcount;
Eric Andersen3443bd72003-07-22 07:30:36 +00001599#ifndef HDIO_DRIVE_CMD
1600 int force_operation = 0;
1601#endif
Rob Landley39cf6452006-05-05 16:52:28 +00001602 /* Please restore args[n] to these values after each ioctl
1603 except for args[2] */
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00001604 unsigned char args[4] = { WIN_SETFEATURES, 0, 0, 0 };
Rob Landleyadde7982006-05-16 15:32:30 +00001605 const char *fmt = " %s\t= %2ld";
Rob Landleye5b281f2006-04-29 15:49:18 +00001606
Bernhard Reutner-Fischera4830872009-10-26 23:27:08 +01001607 /*fd = xopen_nonblocking(devname);*/
1608 xmove_fd(xopen_nonblocking(devname), fd);
Rob Landleyade7f952006-05-25 18:53:06 +00001609 printf("\n%s:\n", devname);
Eric Andersen3443bd72003-07-22 07:30:36 +00001610
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001611 if (getset_readahead == IS_SET) {
1612 print_flag(getset_readahead, "fs readahead", Xreadahead);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001613 ioctl_or_warn(fd, BLKRASET, (int *)Xreadahead);
Eric Andersen3443bd72003-07-22 07:30:36 +00001614 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001615#if ENABLE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF
1616 if (unregister_hwif) {
Rob Landley20deab02006-05-07 23:34:15 +00001617 printf(" attempting to unregister hwif#%lu\n", hwif);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001618 ioctl_or_warn(fd, HDIO_UNREGISTER_HWIF, (int *)(unsigned long)hwif);
Eric Andersen3443bd72003-07-22 07:30:36 +00001619 }
1620#endif
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001621#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001622 if (scan_hwif == IS_SET) {
Rob Landley20deab02006-05-07 23:34:15 +00001623 printf(" attempting to scan hwif (0x%lx, 0x%lx, %lu)\n", hwif_data, hwif_ctrl, hwif_irq);
Eric Andersen3443bd72003-07-22 07:30:36 +00001624 args[0] = hwif_data;
1625 args[1] = hwif_ctrl;
1626 args[2] = hwif_irq;
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001627 ioctl_or_warn(fd, HDIO_SCAN_HWIF, args);
Rob Landley39cf6452006-05-05 16:52:28 +00001628 args[0] = WIN_SETFEATURES;
1629 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001630 }
1631#endif
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001632 if (set_piomode) {
1633 if (noisy_piomode) {
Glenn L McGrath07085852003-10-09 07:28:22 +00001634 printf(" attempting to ");
Eric Andersen3443bd72003-07-22 07:30:36 +00001635 if (piomode == 255)
Glenn L McGrath07085852003-10-09 07:28:22 +00001636 printf("auto-tune PIO mode\n");
Eric Andersen3443bd72003-07-22 07:30:36 +00001637 else if (piomode < 100)
Glenn L McGrath07085852003-10-09 07:28:22 +00001638 printf("set PIO mode to %d\n", piomode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001639 else if (piomode < 200)
Glenn L McGrath07085852003-10-09 07:28:22 +00001640 printf("set MDMA mode to %d\n", (piomode-100));
Eric Andersen3443bd72003-07-22 07:30:36 +00001641 else
Glenn L McGrath07085852003-10-09 07:28:22 +00001642 printf("set UDMA mode to %d\n", (piomode-200));
Eric Andersen3443bd72003-07-22 07:30:36 +00001643 }
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001644 ioctl_or_warn(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode);
Eric Andersen3443bd72003-07-22 07:30:36 +00001645 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001646 if (getset_io32bit == IS_SET) {
1647 print_flag(getset_io32bit, "32-bit IO_support flag", io32bit);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001648 ioctl_or_warn(fd, HDIO_SET_32BIT, (int *)io32bit);
Eric Andersen3443bd72003-07-22 07:30:36 +00001649 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001650 if (getset_mult == IS_SET) {
1651 print_flag(getset_mult, "multcount", mult);
Rob Landleyade7f952006-05-25 18:53:06 +00001652#ifdef HDIO_DRIVE_CMD
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001653 ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult);
Rob Landleyade7f952006-05-25 18:53:06 +00001654#else
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001655 force_operation |= (!ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult));
Eric Andersen3443bd72003-07-22 07:30:36 +00001656#endif
1657 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001658 if (getset_readonly == IS_SET) {
1659 print_flag_on_off(getset_readonly, "readonly", readonly);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001660 ioctl_or_warn(fd, BLKROSET, &readonly);
Eric Andersen3443bd72003-07-22 07:30:36 +00001661 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001662 if (getset_unmask == IS_SET) {
1663 print_flag_on_off(getset_unmask, "unmaskirq", unmask);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001664 ioctl_or_warn(fd, HDIO_SET_UNMASKINTR, (int *)unmask);
Eric Andersen3443bd72003-07-22 07:30:36 +00001665 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001666#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001667 if (getset_dma == IS_SET) {
1668 print_flag_on_off(getset_dma, "using_dma", dma);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001669 ioctl_or_warn(fd, HDIO_SET_DMA, (int *)dma);
Eric Andersen3443bd72003-07-22 07:30:36 +00001670 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001671#endif /* FEATURE_HDPARM_HDIO_GETSET_DMA */
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001672#ifdef HDIO_SET_QDMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001673 if (getset_dma_q == IS_SET) {
1674 print_flag_on_off(getset_dma_q, "DMA queue_depth", dma_q);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001675 ioctl_or_warn(fd, HDIO_SET_QDMA, (int *)dma_q);
Eric Andersen3443bd72003-07-22 07:30:36 +00001676 }
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001677#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001678 if (getset_nowerr == IS_SET) {
1679 print_flag_on_off(getset_nowerr, "nowerr", nowerr);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001680 ioctl_or_warn(fd, HDIO_SET_NOWERR, (int *)nowerr);
Eric Andersen3443bd72003-07-22 07:30:36 +00001681 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001682 if (getset_keep == IS_SET) {
1683 print_flag_on_off(getset_keep, "keep_settings", keep);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001684 ioctl_or_warn(fd, HDIO_SET_KEEPSETTINGS, (int *)keep);
Eric Andersen3443bd72003-07-22 07:30:36 +00001685 }
1686#ifdef HDIO_DRIVE_CMD
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001687 if (getset_doorlock == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001688 args[0] = doorlock ? WIN_DOORLOCK : WIN_DOORUNLOCK;
Rob Landley39cf6452006-05-05 16:52:28 +00001689 args[2] = 0;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001690 print_flag_on_off(getset_doorlock, "drive doorlock", doorlock);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001691 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001692 args[0] = WIN_SETFEATURES;
Eric Andersen3443bd72003-07-22 07:30:36 +00001693 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001694 if (getset_dkeep == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001695 /* lock/unlock the drive's "feature" settings */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001696 print_flag_on_off(getset_dkeep, "drive keep features", dkeep);
Eric Andersen3443bd72003-07-22 07:30:36 +00001697 args[2] = dkeep ? 0x66 : 0xcc;
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001698 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001699 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001700 if (getset_defects == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001701 args[2] = defects ? 0x04 : 0x84;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001702 print_flag(getset_defects, "drive defect-mgmt", defects);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001703 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001704 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001705 if (getset_prefetch == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001706 args[1] = prefetch;
Rob Landleye5b281f2006-04-29 15:49:18 +00001707 args[2] = 0xab;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001708 print_flag(getset_prefetch, "drive prefetch", prefetch);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001709 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001710 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001711 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001712 if (set_xfermode) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001713 args[1] = xfermode_requested;
Rob Landleye5b281f2006-04-29 15:49:18 +00001714 args[2] = 3;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001715 print_flag(1, "xfermode", xfermode_requested);
1716 interpret_xfermode(xfermode_requested);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001717 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001718 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001719 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001720 if (getset_lookahead == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001721 args[2] = lookahead ? 0xaa : 0x55;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001722 print_flag_on_off(getset_lookahead, "drive read-lookahead", lookahead);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001723 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001724 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001725 if (getset_apmmode == IS_SET) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001726 /* feature register */
1727 args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */;
Rob Landleyadde7982006-05-16 15:32:30 +00001728 args[1] = apmmode; /* sector count register 1-255 */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001729 printf(" setting APM level to %s 0x%02lX (%ld)\n",
1730 (apmmode == 255) ? "disabled" : "",
1731 apmmode, apmmode);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001732 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001733 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001734 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001735 if (getset_wcache == IS_SET) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001736#ifdef DO_FLUSHCACHE
1737#ifndef WIN_FLUSHCACHE
1738#define WIN_FLUSHCACHE 0xe7
1739#endif
Eric Andersen3443bd72003-07-22 07:30:36 +00001740#endif /* DO_FLUSHCACHE */
Eric Andersen3443bd72003-07-22 07:30:36 +00001741 args[2] = wcache ? 0x02 : 0x82;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001742 print_flag_on_off(getset_wcache, "drive write-caching", wcache);
Eric Andersen3443bd72003-07-22 07:30:36 +00001743#ifdef DO_FLUSHCACHE
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001744 if (!wcache)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001745 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache);
Eric Andersen3443bd72003-07-22 07:30:36 +00001746#endif /* DO_FLUSHCACHE */
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001747 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001748#ifdef DO_FLUSHCACHE
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001749 if (!wcache)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001750 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache);
Eric Andersen3443bd72003-07-22 07:30:36 +00001751#endif /* DO_FLUSHCACHE */
1752 }
Rob Landley39cf6452006-05-05 16:52:28 +00001753
1754 /* In code below, we do not preserve args[0], but the rest
1755 is preserved, including args[2] */
1756 args[2] = 0;
1757
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001758 if (set_standbynow) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001759#ifndef WIN_STANDBYNOW1
1760#define WIN_STANDBYNOW1 0xE0
1761#endif
1762#ifndef WIN_STANDBYNOW2
1763#define WIN_STANDBYNOW2 0x94
1764#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001765 printf(" issuing standby command\n");
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001766 args[0] = WIN_STANDBYNOW1;
Denis Vlasenko892536f2007-09-27 10:23:34 +00001767 ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2);
Eric Andersen3443bd72003-07-22 07:30:36 +00001768 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001769 if (set_sleepnow) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001770#ifndef WIN_SLEEPNOW1
1771#define WIN_SLEEPNOW1 0xE6
1772#endif
1773#ifndef WIN_SLEEPNOW2
1774#define WIN_SLEEPNOW2 0x99
1775#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001776 printf(" issuing sleep command\n");
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001777 args[0] = WIN_SLEEPNOW1;
Denis Vlasenko892536f2007-09-27 10:23:34 +00001778 ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2);
Eric Andersen3443bd72003-07-22 07:30:36 +00001779 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001780 if (set_seagate) {
Rob Landleye5b281f2006-04-29 15:49:18 +00001781 args[0] = 0xfb;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001782 printf(" disabling Seagate auto powersaving mode\n");
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001783 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001784 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001785 if (getset_standby == IS_SET) {
Rob Landleye5b281f2006-04-29 15:49:18 +00001786 args[0] = WIN_SETIDLE1;
1787 args[1] = standby_requested;
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001788 print_flag(1, "standby", standby_requested);
1789 interpret_standby(standby_requested);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001790 ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args);
Rob Landley39cf6452006-05-05 16:52:28 +00001791 args[1] = 0;
Eric Andersen3443bd72003-07-22 07:30:36 +00001792 }
1793#else /* HDIO_DRIVE_CMD */
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001794 if (force_operation) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001795 char buf[512];
Denis Vlasenko892536f2007-09-27 10:23:34 +00001796 flush_buffer_cache();
Eric Andersen3443bd72003-07-22 07:30:36 +00001797 if (-1 == read(fd, buf, sizeof(buf)))
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001798 bb_perror_msg("read of 512 bytes failed");
Eric Andersen3443bd72003-07-22 07:30:36 +00001799 }
Denys Vlasenkoe4dcba12010-10-28 18:57:19 +02001800#endif /* HDIO_DRIVE_CMD */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001801 if (getset_mult || get_identity) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001802 multcount = -1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001803 if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) {
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001804 /* To be coherent with ioctl_or_warn. */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001805 if (getset_mult && ENABLE_IOCTL_HEX2STR_ERROR)
Eric Andersen06d4ec22004-03-19 10:53:52 +00001806 bb_perror_msg("HDIO_GET_MULTCOUNT");
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001807 else
1808 bb_perror_msg("ioctl %#x failed", HDIO_GET_MULTCOUNT);
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001809 } else if (getset_mult) {
Rob Landleyadde7982006-05-16 15:32:30 +00001810 printf(fmt, "multcount", multcount);
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001811 on_off(multcount != 0);
Eric Andersen3443bd72003-07-22 07:30:36 +00001812 }
1813 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001814 if (getset_io32bit) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001815 if (!ioctl_or_warn(fd, HDIO_GET_32BIT, &parm)) {
Rob Landleyadde7982006-05-16 15:32:30 +00001816 printf(" IO_support\t=%3ld (", parm);
1817 if (parm == 0)
1818 printf("default 16-bit)\n");
1819 else if (parm == 2)
1820 printf("16-bit)\n");
1821 else if (parm == 1)
1822 printf("32-bit)\n");
1823 else if (parm == 3)
1824 printf("32-bit w/sync)\n");
1825 else if (parm == 8)
1826 printf("Request-Queue-Bypass)\n");
1827 else
1828 printf("\?\?\?)\n");
Eric Andersen3443bd72003-07-22 07:30:36 +00001829 }
1830 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001831 if (getset_unmask) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001832 if (!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001833 print_value_on_off("unmaskirq", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001834 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001835#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001836 if (getset_dma) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001837 if (!ioctl_or_warn(fd, HDIO_GET_DMA, &parm)) {
Rob Landleyadde7982006-05-16 15:32:30 +00001838 printf(fmt, "using_dma", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001839 if (parm == 8)
1840 printf(" (DMA-Assisted-PIO)\n");
1841 else
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001842 on_off(parm != 0);
Eric Andersen3443bd72003-07-22 07:30:36 +00001843 }
1844 }
1845#endif
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001846#ifdef HDIO_GET_QDMA
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001847 if (getset_dma_q) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001848 if (!ioctl_or_warn(fd, HDIO_GET_QDMA, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001849 print_value_on_off("queue_depth", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001850 }
Denis Vlasenko3c96d022008-03-20 13:44:50 +00001851#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001852 if (getset_keep) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001853 if (!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001854 print_value_on_off("keepsettings", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001855 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001856 if (getset_nowerr) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001857 if (!ioctl_or_warn(fd, HDIO_GET_NOWERR, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001858 print_value_on_off("nowerr", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001859 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001860 if (getset_readonly) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001861 if (!ioctl_or_warn(fd, BLKROGET, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001862 print_value_on_off("readonly", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001863 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001864 if (getset_readahead) {
Denis Vlasenkod6855d12008-09-27 14:03:25 +00001865 if (!ioctl_or_warn(fd, BLKRAGET, &parm))
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001866 print_value_on_off("readahead", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001867 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001868 if (get_geom) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001869 if (!ioctl_or_warn(fd, BLKGETSIZE, &parm)) {
Rob Landley2584e9b2006-05-03 20:00:00 +00001870 struct hd_geometry g;
1871
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001872 if (!ioctl_or_warn(fd, HDIO_GETGEO, &g))
Rob Landleyadde7982006-05-16 15:32:30 +00001873 printf(" geometry\t= %u/%u/%u, sectors = %ld, start = %ld\n",
Denys Vlasenko6d335be2009-05-20 14:48:03 +02001874 g.cylinders, g.heads, g.sectors, parm, g.start);
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001875 }
Eric Andersen3443bd72003-07-22 07:30:36 +00001876 }
1877#ifdef HDIO_DRIVE_CMD
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001878 if (get_powermode) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001879#ifndef WIN_CHECKPOWERMODE1
1880#define WIN_CHECKPOWERMODE1 0xE5
1881#endif
1882#ifndef WIN_CHECKPOWERMODE2
1883#define WIN_CHECKPOWERMODE2 0x98
1884#endif
Eric Andersen3443bd72003-07-22 07:30:36 +00001885 const char *state;
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001886
Rob Landleye5b281f2006-04-29 15:49:18 +00001887 args[0] = WIN_CHECKPOWERMODE1;
Denis Vlasenko892536f2007-09-27 10:23:34 +00001888 if (ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2)) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001889 if (errno != EIO || args[0] != 0 || args[1] != 0)
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00001890 state = "unknown";
Eric Andersen3443bd72003-07-22 07:30:36 +00001891 else
1892 state = "sleeping";
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001893 } else
Glenn L McGrath07085852003-10-09 07:28:22 +00001894 state = (args[2] == 255) ? "active/idle" : "standby";
Rob Landley39cf6452006-05-05 16:52:28 +00001895 args[1] = args[2] = 0;
Glenn L McGrath07085852003-10-09 07:28:22 +00001896
Eric Andersen3443bd72003-07-22 07:30:36 +00001897 printf(" drive state is: %s\n", state);
1898 }
1899#endif
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001900#if ENABLE_FEATURE_HDPARM_HDIO_DRIVE_RESET
1901 if (perform_reset) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001902 ioctl_or_warn(fd, HDIO_DRIVE_RESET, NULL);
Eric Andersen3443bd72003-07-22 07:30:36 +00001903 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001904#endif /* FEATURE_HDPARM_HDIO_DRIVE_RESET */
1905#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
1906 if (perform_tristate) {
Rob Landleye5b281f2006-04-29 15:49:18 +00001907 args[0] = 0;
1908 args[1] = tristate;
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001909 ioctl_or_warn(fd, HDIO_TRISTATE_HWIF, &args);
Eric Andersen3443bd72003-07-22 07:30:36 +00001910 }
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001911#endif /* FEATURE_HDPARM_HDIO_TRISTATE_HWIF */
1912#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
1913 if (get_identity) {
Denis Vlasenko7c282a22007-03-28 00:14:54 +00001914 struct hd_driveid id;
Eric Andersen3443bd72003-07-22 07:30:36 +00001915
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001916 if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) {
1917 if (multcount != -1) {
Eric Andersen3443bd72003-07-22 07:30:36 +00001918 id.multsect = multcount;
1919 id.multsect_valid |= 1;
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001920 } else
Eric Andersen3443bd72003-07-22 07:30:36 +00001921 id.multsect_valid &= ~1;
1922 dump_identity(&id);
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001923 } else if (errno == -ENOMSG)
Eric Andersen3443bd72003-07-22 07:30:36 +00001924 printf(" no identification info available\n");
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001925 else if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */
Denis Vlasenko49a128a2007-07-17 21:42:59 +00001926 bb_perror_msg("HDIO_GET_IDENTITY");
Eric Andersen3443bd72003-07-22 07:30:36 +00001927 else
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001928 bb_perror_msg("ioctl %#x failed", HDIO_GET_IDENTITY);
Eric Andersen3443bd72003-07-22 07:30:36 +00001929 }
Glenn L McGrath07085852003-10-09 07:28:22 +00001930
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001931 if (get_IDentity) {
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001932 unsigned char args1[4+512]; /* = { ... } will eat 0.5k of rodata! */
Glenn L McGrath07085852003-10-09 07:28:22 +00001933
Rob Landley5f8b5ec2006-04-29 16:03:40 +00001934 memset(args1, 0, sizeof(args1));
1935 args1[0] = WIN_IDENTIFY;
1936 args1[3] = 1;
Denis Vlasenko892536f2007-09-27 10:23:34 +00001937 if (!ioctl_alt_or_warn(HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY))
Rob Landley0753f4a2006-06-07 00:27:25 +00001938 identify((void *)(args1 + 4));
Eric Andersen3443bd72003-07-22 07:30:36 +00001939 }
1940#endif
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001941#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001942 if (getset_busstate == IS_SET) {
1943 print_flag(1, "bus state", busstate);
1944 bus_state_value(busstate);
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001945 ioctl_or_warn(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate);
Eric Andersen3443bd72003-07-22 07:30:36 +00001946 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02001947 if (getset_busstate) {
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001948 if (!ioctl_or_warn(fd, HDIO_GET_BUSSTATE, &parm)) {
Rob Landleyadde7982006-05-16 15:32:30 +00001949 printf(fmt, "bus state", parm);
Eric Andersen3443bd72003-07-22 07:30:36 +00001950 bus_state_value(parm);
1951 }
1952 }
1953#endif
Glenn L McGrath07085852003-10-09 07:28:22 +00001954 if (reread_partn)
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +00001955 ioctl_or_warn(fd, BLKRRPART, NULL);
Glenn L McGrath07085852003-10-09 07:28:22 +00001956
Eric Andersen3443bd72003-07-22 07:30:36 +00001957 if (do_ctimings)
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001958 do_time(1 /*,fd*/); /* time cache */
Eric Andersen3443bd72003-07-22 07:30:36 +00001959 if (do_timings)
Denis Vlasenkoc3122bc2007-09-28 10:28:03 +00001960 do_time(0 /*,fd*/); /* time device */
Eric Andersen3443bd72003-07-22 07:30:36 +00001961 if (do_flush)
Denis Vlasenko892536f2007-09-27 10:23:34 +00001962 flush_buffer_cache();
Rob Landleya3e4f382006-04-29 16:06:31 +00001963 close(fd);
Eric Andersen3443bd72003-07-22 07:30:36 +00001964}
1965
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001966#if ENABLE_FEATURE_HDPARM_GET_IDENTITY
Rob Landleya3e4f382006-04-29 16:06:31 +00001967static int fromhex(unsigned char c)
Eric Andersen3443bd72003-07-22 07:30:36 +00001968{
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +00001969 if (isdigit(c))
Eric Andersen3443bd72003-07-22 07:30:36 +00001970 return (c - '0');
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +00001971 if (c >= 'a' && c <= 'f')
1972 return (c - ('a' - 10));
Eric Andersen3443bd72003-07-22 07:30:36 +00001973 bb_error_msg_and_die("bad char: '%c' 0x%02x", c, c);
1974}
1975
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00001976static void identify_from_stdin(void) NORETURN;
Rob Landley0f0b6452006-05-03 18:28:06 +00001977static void identify_from_stdin(void)
Eric Andersen3443bd72003-07-22 07:30:36 +00001978{
Rob Landley0753f4a2006-06-07 00:27:25 +00001979 uint16_t sbuf[256];
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +00001980 unsigned char buf[1280];
1981 unsigned char *b = (unsigned char *)buf;
1982 int i;
Eric Andersen3443bd72003-07-22 07:30:36 +00001983
Bernhard Reutner-Fischer5e25ddb2008-05-19 09:48:17 +00001984 xread(STDIN_FILENO, buf, 1280);
Rob Landleyade7f952006-05-25 18:53:06 +00001985
Rob Landley0753f4a2006-06-07 00:27:25 +00001986 // Convert the newline-separated hex data into an identify block.
1987
Denis Vlasenko3bf00202007-02-18 13:36:04 +00001988 for (i = 0; i < 256; i++) {
Rob Landley0753f4a2006-06-07 00:27:25 +00001989 int j;
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00001990 for (j = 0; j < 4; j++)
Denis Vlasenko3a34d0c2007-01-12 22:10:34 +00001991 sbuf[i] = (sbuf[i] << 4) + fromhex(*(b++));
Eric Andersen3443bd72003-07-22 07:30:36 +00001992 }
Rob Landley0753f4a2006-06-07 00:27:25 +00001993
1994 // Parse the data.
1995
Rob Landley6389ff12006-05-01 19:28:53 +00001996 identify(sbuf);
Eric Andersen3443bd72003-07-22 07:30:36 +00001997}
Denis Vlasenko0d3c6af2007-09-28 10:25:32 +00001998#else
1999void identify_from_stdin(void);
Eric Andersen3443bd72003-07-22 07:30:36 +00002000#endif
2001
Rob Landley20deab02006-05-07 23:34:15 +00002002/* busybox specific stuff */
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002003static int parse_opts(unsigned long *value, int min, int max)
Eric Andersenb2aa7762004-04-05 13:08:08 +00002004{
Denis Vlasenko6429aab2006-09-23 12:22:11 +00002005 if (optarg) {
Denis Vlasenko13858992006-10-08 12:49:22 +00002006 *value = xatol_range(optarg, min, max);
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002007 return IS_SET;
Denis Vlasenko6429aab2006-09-23 12:22:11 +00002008 }
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002009 return IS_GET;
2010}
2011static int parse_opts_0_max(unsigned long *value, int max)
2012{
2013 return parse_opts(value, 0, max);
2014}
2015static int parse_opts_0_1(unsigned long *value)
2016{
2017 return parse_opts(value, 0, 1);
2018}
2019static int parse_opts_0_INTMAX(unsigned long *value)
2020{
2021 return parse_opts(value, 0, INT_MAX);
Rob Landley20deab02006-05-07 23:34:15 +00002022}
2023
Denis Vlasenko0eec4ab2007-03-28 01:00:45 +00002024static void parse_xfermode(int flag, smallint *get, smallint *set, int *value)
Rob Landley20deab02006-05-07 23:34:15 +00002025{
2026 if (flag) {
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002027 *get = IS_GET;
Rob Landley20deab02006-05-07 23:34:15 +00002028 if (optarg) {
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00002029 *value = translate_xfermode(optarg);
2030 *set = (*value > -1);
Rob Landley20deab02006-05-07 23:34:15 +00002031 }
2032 }
2033}
2034
Rob Landley06208412006-05-31 22:52:57 +00002035/*------- getopt short options --------*/
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00002036static const char hdparm_options[] ALIGN1 =
Denis Vlasenko4daad902007-09-27 10:20:47 +00002037 "gfu::n::p:r::m::c::k::a::B:tT"
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002038 IF_FEATURE_HDPARM_GET_IDENTITY("iI")
2039 IF_FEATURE_HDPARM_HDIO_GETSET_DMA("d::")
Rob Landley20deab02006-05-07 23:34:15 +00002040#ifdef HDIO_DRIVE_CMD
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002041 "S:D:P:X:K:A:L:W:CyYzZ"
Rob Landley20deab02006-05-07 23:34:15 +00002042#endif
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002043 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF("U:")
Rob Landley20deab02006-05-07 23:34:15 +00002044#ifdef HDIO_GET_QDMA
2045#ifdef HDIO_SET_QDMA
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002046 "Q:"
Rob Landley20deab02006-05-07 23:34:15 +00002047#else
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002048 "Q"
Rob Landley20deab02006-05-07 23:34:15 +00002049#endif
2050#endif
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002051 IF_FEATURE_HDPARM_HDIO_DRIVE_RESET("w")
2052 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF("x::b:")
2053 IF_FEATURE_HDPARM_HDIO_SCAN_HWIF("R:");
Rob Landley20deab02006-05-07 23:34:15 +00002054/*-------------------------------------*/
2055
2056/* our main() routine: */
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00002057int hdparm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Rob Landley20deab02006-05-07 23:34:15 +00002058int hdparm_main(int argc, char **argv)
2059{
2060 int c;
Rob Landleyade7f952006-05-25 18:53:06 +00002061 int flagcount = 0;
Rob Landley20deab02006-05-07 23:34:15 +00002062
Rob Landley06208412006-05-31 22:52:57 +00002063 while ((c = getopt(argc, argv, hdparm_options)) >= 0) {
Rob Landley20deab02006-05-07 23:34:15 +00002064 flagcount++;
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002065 IF_FEATURE_HDPARM_GET_IDENTITY(get_IDentity |= (c == 'I'));
2066 IF_FEATURE_HDPARM_GET_IDENTITY(get_identity |= (c == 'i'));
Rob Landleyadde7982006-05-16 15:32:30 +00002067 get_geom |= (c == 'g');
2068 do_flush |= (c == 'f');
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002069 if (c == 'u') getset_unmask = parse_opts_0_1(&unmask);
2070 IF_FEATURE_HDPARM_HDIO_GETSET_DMA(
2071 if (c == 'd') getset_dma = parse_opts_0_max(&dma, 9);
2072 )
2073 if (c == 'n') getset_nowerr = parse_opts_0_1(&nowerr);
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00002074 parse_xfermode((c == 'p'), &noisy_piomode, &set_piomode, &piomode);
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002075 if (c == 'r') getset_readonly = parse_opts_0_1(&readonly);
2076 if (c == 'm') getset_mult = parse_opts_0_INTMAX(&mult /*32*/);
2077 if (c == 'c') getset_io32bit = parse_opts_0_INTMAX(&io32bit /*8*/);
2078 if (c == 'k') getset_keep = parse_opts_0_1(&keep);
2079 if (c == 'a') getset_readahead = parse_opts_0_INTMAX(&Xreadahead);
2080 if (c == 'B') getset_apmmode = parse_opts(&apmmode, 1, 255);
Rob Landleyadde7982006-05-16 15:32:30 +00002081 do_flush |= do_timings |= (c == 't');
2082 do_flush |= do_ctimings |= (c == 'T');
Rob Landley20deab02006-05-07 23:34:15 +00002083#ifdef HDIO_DRIVE_CMD
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002084 if (c == 'S') getset_standby = parse_opts_0_max(&standby_requested, 255);
2085 if (c == 'D') getset_defects = parse_opts_0_INTMAX(&defects);
2086 if (c == 'P') getset_prefetch = parse_opts_0_INTMAX(&prefetch);
Rob Landleyade7f952006-05-25 18:53:06 +00002087 parse_xfermode((c == 'X'), &get_xfermode, &set_xfermode, &xfermode_requested);
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002088 if (c == 'K') getset_dkeep = parse_opts_0_1(&prefetch);
2089 if (c == 'A') getset_lookahead = parse_opts_0_1(&lookahead);
2090 if (c == 'L') getset_doorlock = parse_opts_0_1(&doorlock);
2091 if (c == 'W') getset_wcache = parse_opts_0_1(&wcache);
Rob Landleyade7f952006-05-25 18:53:06 +00002092 get_powermode |= (c == 'C');
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002093 set_standbynow |= (c == 'y');
2094 set_sleepnow |= (c == 'Y');
Rob Landleyadde7982006-05-16 15:32:30 +00002095 reread_partn |= (c == 'z');
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002096 set_seagate |= (c == 'Z');
Rob Landley20deab02006-05-07 23:34:15 +00002097#endif
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002098 IF_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(if (c == 'U') unregister_hwif = parse_opts_0_INTMAX(&hwif));
Rob Landley20deab02006-05-07 23:34:15 +00002099#ifdef HDIO_GET_QDMA
Rob Landley19802562006-05-08 15:35:46 +00002100 if (c == 'Q') {
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002101 getset_dma_q = parse_opts_0_INTMAX(&dma_q);
Rob Landley19802562006-05-08 15:35:46 +00002102 }
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00002103#endif
Denis Vlasenko5e34ff22009-04-21 11:09:40 +00002104 IF_FEATURE_HDPARM_HDIO_DRIVE_RESET(perform_reset = (c == 'r'));
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002105 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'x') perform_tristate = parse_opts_0_1(&tristate));
2106 IF_FEATURE_HDPARM_HDIO_TRISTATE_HWIF(if (c == 'b') getset_busstate = parse_opts_0_max(&busstate, 2));
Rob Landley20deab02006-05-07 23:34:15 +00002107#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF
2108 if (c == 'R') {
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002109 scan_hwif = parse_opts_0_INTMAX(&hwif_data);
Denys Vlasenko77832482010-08-12 14:14:45 +02002110 hwif_ctrl = xatoi_positive((argv[optind]) ? argv[optind] : "");
2111 hwif_irq = xatoi_positive((argv[optind+1]) ? argv[optind+1] : "");
Rob Landley20deab02006-05-07 23:34:15 +00002112 /* Move past the 2 additional arguments */
2113 argv += 2;
2114 argc -= 2;
2115 }
2116#endif
2117 }
Rob Landleyade7f952006-05-25 18:53:06 +00002118 /* When no flags are given (flagcount = 0), -acdgkmnru is assumed. */
Denis Vlasenko67b23e62006-10-03 21:00:06 +00002119 if (!flagcount) {
Denys Vlasenkoc7068452009-05-20 16:11:41 +02002120 getset_mult = getset_io32bit = getset_unmask = getset_keep = getset_readonly = getset_readahead = get_geom = IS_GET;
2121 IF_FEATURE_HDPARM_HDIO_GETSET_DMA(getset_dma = IS_GET);
Rob Landleyade7f952006-05-25 18:53:06 +00002122 }
Rob Landley20deab02006-05-07 23:34:15 +00002123 argv += optind;
2124
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00002125 if (!*argv) {
Rob Landley6d8ce172006-06-07 21:22:42 +00002126 if (ENABLE_FEATURE_HDPARM_GET_IDENTITY && !isatty(STDIN_FILENO))
2127 identify_from_stdin(); /* EXIT */
Denis Vlasenko4daad902007-09-27 10:20:47 +00002128 bb_show_usage();
Rob Landley20deab02006-05-07 23:34:15 +00002129 }
2130
Denis Vlasenkof1ba7492007-03-28 00:14:01 +00002131 do {
2132 process_dev(*argv++);
2133 } while (*argv);
2134
2135 return EXIT_SUCCESS;
Eric Andersen3443bd72003-07-22 07:30:36 +00002136}