source: MondoRescue/branches/3.2/mindi-busybox/miscutils/hdparm.c@ 3232

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