12 |
* - by Mark Lord (C) 1994-2002 -- freely distributable |
* - by Mark Lord (C) 1994-2002 -- freely distributable |
13 |
*/ |
*/ |
14 |
|
|
15 |
#include "busybox.h" |
#include "libbb.h" |
16 |
#include <linux/hdreg.h> |
#include <linux/hdreg.h> |
17 |
|
|
18 |
/* device types */ |
/* device types */ |
39 |
#define LENGTH_FW_REV 4 /* 4 words (8 bytes or characters) */ |
#define LENGTH_FW_REV 4 /* 4 words (8 bytes or characters) */ |
40 |
#define START_MODEL 27 /* ASCII model number */ |
#define START_MODEL 27 /* ASCII model number */ |
41 |
#define LENGTH_MODEL 20 /* 20 words (40 bytes or characters) */ |
#define LENGTH_MODEL 20 /* 20 words (40 bytes or characters) */ |
42 |
#define SECTOR_XFER_MAX 47 /* r/w multiple: max sectors xfered */ |
#define SECTOR_XFER_MAX 47 /* r/w multiple: max sectors xfered */ |
43 |
#define DWORD_IO 48 /* can do double-word IO (ATA-1 only) */ |
#define DWORD_IO 48 /* can do double-word IO (ATA-1 only) */ |
44 |
#define CAPAB_0 49 /* capabilities */ |
#define CAPAB_0 49 /* capabilities */ |
45 |
#define CAPAB_1 50 |
#define CAPAB_1 50 |
48 |
#define WHATS_VALID 53 /* what fields are valid */ |
#define WHATS_VALID 53 /* what fields are valid */ |
49 |
#define LCYLS_CUR 54 /* current logical cylinders */ |
#define LCYLS_CUR 54 /* current logical cylinders */ |
50 |
#define LHEADS_CUR 55 /* current logical heads */ |
#define LHEADS_CUR 55 /* current logical heads */ |
51 |
#define LSECTS_CUR 56 /* current logical sectors/track */ |
#define LSECTS_CUR 56 /* current logical sectors/track */ |
52 |
#define CAPACITY_LSB 57 /* current capacity in sectors */ |
#define CAPACITY_LSB 57 /* current capacity in sectors */ |
53 |
#define CAPACITY_MSB 58 |
#define CAPACITY_MSB 58 |
54 |
#define SECTOR_XFER_CUR 59 /* r/w multiple: current sectors xfered */ |
#define SECTOR_XFER_CUR 59 /* r/w multiple: current sectors xfered */ |
127 |
|
|
128 |
#define CDROM 0x0005 |
#define CDROM 0x0005 |
129 |
|
|
|
#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY |
|
|
static const char * const pkt_str[] = { |
|
|
"Direct-access device", /* word 0, bits 12-8 = 00 */ |
|
|
"Sequential-access device", /* word 0, bits 12-8 = 01 */ |
|
|
"Printer", /* word 0, bits 12-8 = 02 */ |
|
|
"Processor", /* word 0, bits 12-8 = 03 */ |
|
|
"Write-once device", /* word 0, bits 12-8 = 04 */ |
|
|
"CD-ROM", /* word 0, bits 12-8 = 05 */ |
|
|
"Scanner", /* word 0, bits 12-8 = 06 */ |
|
|
"Optical memory", /* word 0, bits 12-8 = 07 */ |
|
|
"Medium changer", /* word 0, bits 12-8 = 08 */ |
|
|
"Communications device", /* word 0, bits 12-8 = 09 */ |
|
|
"ACS-IT8 device", /* word 0, bits 12-8 = 0a */ |
|
|
"ACS-IT8 device", /* word 0, bits 12-8 = 0b */ |
|
|
"Array controller", /* word 0, bits 12-8 = 0c */ |
|
|
"Enclosure services", /* word 0, bits 12-8 = 0d */ |
|
|
"Reduced block command device", /* word 0, bits 12-8 = 0e */ |
|
|
"Optical card reader/writer", /* word 0, bits 12-8 = 0f */ |
|
|
"", /* word 0, bits 12-8 = 10 */ |
|
|
"", /* word 0, bits 12-8 = 11 */ |
|
|
"", /* word 0, bits 12-8 = 12 */ |
|
|
"", /* word 0, bits 12-8 = 13 */ |
|
|
"", /* word 0, bits 12-8 = 14 */ |
|
|
"", /* word 0, bits 12-8 = 15 */ |
|
|
"", /* word 0, bits 12-8 = 16 */ |
|
|
"", /* word 0, bits 12-8 = 17 */ |
|
|
"", /* word 0, bits 12-8 = 18 */ |
|
|
"", /* word 0, bits 12-8 = 19 */ |
|
|
"", /* word 0, bits 12-8 = 1a */ |
|
|
"", /* word 0, bits 12-8 = 1b */ |
|
|
"", /* word 0, bits 12-8 = 1c */ |
|
|
"", /* word 0, bits 12-8 = 1d */ |
|
|
"", /* word 0, bits 12-8 = 1e */ |
|
|
"Unknown", /* word 0, bits 12-8 = 1f */ |
|
|
}; |
|
|
|
|
|
static const char * const ata1_cfg_str[] = { /* word 0 in ATA-1 mode */ |
|
|
"Reserved", /* bit 0 */ |
|
|
"hard sectored", /* bit 1 */ |
|
|
"soft sectored", /* bit 2 */ |
|
|
"not MFM encoded ", /* bit 3 */ |
|
|
"head switch time > 15us", /* bit 4 */ |
|
|
"spindle motor control option", /* bit 5 */ |
|
|
"fixed drive", /* bit 6 */ |
|
|
"removable drive", /* bit 7 */ |
|
|
"disk xfer rate <= 5Mbs", /* bit 8 */ |
|
|
"disk xfer rate > 5Mbs, <= 10Mbs", /* bit 9 */ |
|
|
"disk xfer rate > 5Mbs", /* bit 10 */ |
|
|
"rotational speed tol.", /* bit 11 */ |
|
|
"data strobe offset option", /* bit 12 */ |
|
|
"track offset option", /* bit 13 */ |
|
|
"format speed tolerance gap reqd", /* bit 14 */ |
|
|
"ATAPI" /* bit 14 */ |
|
|
}; |
|
|
#endif |
|
|
|
|
130 |
/* word 1: number of logical cylinders */ |
/* word 1: number of logical cylinders */ |
131 |
#define LCYLS_MAX 0x3fff /* maximum allowable value */ |
#define LCYLS_MAX 0x3fff /* maximum allowable value */ |
132 |
|
|
144 |
#define MULTIPLE_SETTING_VALID 0x0100 /* 1=multiple sector setting is valid */ |
#define MULTIPLE_SETTING_VALID 0x0100 /* 1=multiple sector setting is valid */ |
145 |
|
|
146 |
/* word 49: capabilities 0 */ |
/* word 49: capabilities 0 */ |
147 |
#define STD_STBY 0x2000 /* 1=standard values supported (ATA); |
#define STD_STBY 0x2000 /* 1=standard values supported (ATA); 0=vendor specific values */ |
|
0=vendor specific values */ |
|
148 |
#define IORDY_SUP 0x0800 /* 1=support; 0=may be supported */ |
#define IORDY_SUP 0x0800 /* 1=support; 0=may be supported */ |
149 |
#define IORDY_OFF 0x0400 /* 1=may be disabled */ |
#define IORDY_OFF 0x0400 /* 1=may be disabled */ |
150 |
#define LBA_SUP 0x0200 /* 1=Logical Block Address support */ |
#define LBA_SUP 0x0200 /* 1=Logical Block Address support */ |
182 |
|
|
183 |
/* word 81: minor version number */ |
/* word 81: minor version number */ |
184 |
#define MINOR_MAX 0x22 |
#define MINOR_MAX 0x22 |
|
#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY |
|
|
static const char *minor_str[MINOR_MAX+2] = { /* word 81 value: */ |
|
|
"Unspecified", /* 0x0000 */ |
|
|
"ATA-1 X3T9.2 781D prior to rev.4", /* 0x0001 */ |
|
|
"ATA-1 published, ANSI X3.221-1994", /* 0x0002 */ |
|
|
"ATA-1 X3T9.2 781D rev.4", /* 0x0003 */ |
|
|
"ATA-2 published, ANSI X3.279-1996", /* 0x0004 */ |
|
|
"ATA-2 X3T10 948D prior to rev.2k", /* 0x0005 */ |
|
|
"ATA-3 X3T10 2008D rev.1", /* 0x0006 */ |
|
|
"ATA-2 X3T10 948D rev.2k", /* 0x0007 */ |
|
|
"ATA-3 X3T10 2008D rev.0", /* 0x0008 */ |
|
|
"ATA-2 X3T10 948D rev.3", /* 0x0009 */ |
|
|
"ATA-3 published, ANSI X3.298-199x", /* 0x000a */ |
|
|
"ATA-3 X3T10 2008D rev.6", /* 0x000b */ |
|
|
"ATA-3 X3T13 2008D rev.7 and 7a", /* 0x000c */ |
|
|
"ATA/ATAPI-4 X3T13 1153D rev.6", /* 0x000d */ |
|
|
"ATA/ATAPI-4 T13 1153D rev.13", /* 0x000e */ |
|
|
"ATA/ATAPI-4 X3T13 1153D rev.7", /* 0x000f */ |
|
|
"ATA/ATAPI-4 T13 1153D rev.18", /* 0x0010 */ |
|
|
"ATA/ATAPI-4 T13 1153D rev.15", /* 0x0011 */ |
|
|
"ATA/ATAPI-4 published, ANSI INCITS 317-1998", /* 0x0012 */ |
|
|
"ATA/ATAPI-5 T13 1321D rev.3", |
|
|
"ATA/ATAPI-4 T13 1153D rev.14", /* 0x0014 */ |
|
|
"ATA/ATAPI-5 T13 1321D rev.1", /* 0x0015 */ |
|
|
"ATA/ATAPI-5 published, ANSI INCITS 340-2000", /* 0x0016 */ |
|
|
"ATA/ATAPI-4 T13 1153D rev.17", /* 0x0017 */ |
|
|
"ATA/ATAPI-6 T13 1410D rev.0", /* 0x0018 */ |
|
|
"ATA/ATAPI-6 T13 1410D rev.3a", /* 0x0019 */ |
|
|
"ATA/ATAPI-7 T13 1532D rev.1", /* 0x001a */ |
|
|
"ATA/ATAPI-6 T13 1410D rev.2", /* 0x001b */ |
|
|
"ATA/ATAPI-6 T13 1410D rev.1", /* 0x001c */ |
|
|
"ATA/ATAPI-7 published, ANSI INCITS 397-2005", /* 0x001d */ |
|
|
"ATA/ATAPI-7 T13 1532D rev.0", /* 0x001e */ |
|
|
"Reserved" /* 0x001f */ |
|
|
"Reserved" /* 0x0020 */ |
|
|
"ATA/ATAPI-7 T13 1532D rev.4a", /* 0x0021 */ |
|
|
"ATA/ATAPI-6 published, ANSI INCITS 361-2002", /* 0x0022 */ |
|
|
"Reserved" /* 0x0023-0xfffe*/ |
|
|
}; |
|
|
#endif |
|
|
static const char actual_ver[MINOR_MAX+2] = { |
|
|
/* word 81 value: */ |
|
|
0, /* 0x0000 WARNING: */ |
|
|
1, /* 0x0001 WARNING: */ |
|
|
1, /* 0x0002 WARNING: */ |
|
|
1, /* 0x0003 WARNING: */ |
|
|
2, /* 0x0004 WARNING: This array */ |
|
|
2, /* 0x0005 WARNING: corresponds */ |
|
|
3, /* 0x0006 WARNING: *exactly* */ |
|
|
2, /* 0x0007 WARNING: to the ATA/ */ |
|
|
3, /* 0x0008 WARNING: ATAPI version */ |
|
|
2, /* 0x0009 WARNING: listed in */ |
|
|
3, /* 0x000a WARNING: the */ |
|
|
3, /* 0x000b WARNING: minor_str */ |
|
|
3, /* 0x000c WARNING: array */ |
|
|
4, /* 0x000d WARNING: above. */ |
|
|
4, /* 0x000e WARNING: */ |
|
|
4, /* 0x000f WARNING: if you change */ |
|
|
4, /* 0x0010 WARNING: that one, */ |
|
|
4, /* 0x0011 WARNING: change this one */ |
|
|
4, /* 0x0012 WARNING: too!!! */ |
|
|
5, /* 0x0013 WARNING: */ |
|
|
4, /* 0x0014 WARNING: */ |
|
|
5, /* 0x0015 WARNING: */ |
|
|
5, /* 0x0016 WARNING: */ |
|
|
4, /* 0x0017 WARNING: */ |
|
|
6, /* 0x0018 WARNING: */ |
|
|
6, /* 0x0019 WARNING: */ |
|
|
7, /* 0x001a WARNING: */ |
|
|
6, /* 0x001b WARNING: */ |
|
|
6, /* 0x001c WARNING: */ |
|
|
7, /* 0x001d WARNING: */ |
|
|
7, /* 0x001e WARNING: */ |
|
|
0, /* 0x001f WARNING: */ |
|
|
0, /* 0x0020 WARNING: */ |
|
|
7, /* 0x0021 WARNING: */ |
|
|
6, /* 0x0022 WARNING: */ |
|
|
0 /* 0x0023-0xfffe */ |
|
|
}; |
|
|
|
|
185 |
/* words 82-84: cmds/feats supported */ |
/* words 82-84: cmds/feats supported */ |
186 |
#define CMDS_W82 0x77ff /* word 82: defined command locations*/ |
#define CMDS_W82 0x77ff /* word 82: defined command locations*/ |
187 |
#define CMDS_W83 0x3fff /* word 83: defined command locations*/ |
#define CMDS_W83 0x3fff /* word 83: defined command locations*/ |
189 |
#define SUPPORT_48_BIT 0x0400 |
#define SUPPORT_48_BIT 0x0400 |
190 |
#define NUM_CMD_FEAT_STR 48 |
#define NUM_CMD_FEAT_STR 48 |
191 |
|
|
|
#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY |
|
|
static const char * const cmd_feat_str[] = { |
|
|
"", /* word 82 bit 15: obsolete */ |
|
|
"NOP cmd", /* word 82 bit 14 */ |
|
|
"READ BUFFER cmd", /* word 82 bit 13 */ |
|
|
"WRITE BUFFER cmd", /* word 82 bit 12 */ |
|
|
"", /* word 82 bit 11: obsolete */ |
|
|
"Host Protected Area feature set", /* word 82 bit 10 */ |
|
|
"DEVICE RESET cmd", /* word 82 bit 9 */ |
|
|
"SERVICE interrupt", /* word 82 bit 8 */ |
|
|
"Release interrupt", /* word 82 bit 7 */ |
|
|
"Look-ahead", /* word 82 bit 6 */ |
|
|
"Write cache", /* word 82 bit 5 */ |
|
|
"PACKET command feature set", /* word 82 bit 4 */ |
|
|
"Power Management feature set", /* word 82 bit 3 */ |
|
|
"Removable Media feature set", /* word 82 bit 2 */ |
|
|
"Security Mode feature set", /* word 82 bit 1 */ |
|
|
"SMART feature set", /* word 82 bit 0 */ |
|
|
/* --------------*/ |
|
|
"", /* word 83 bit 15: !valid bit */ |
|
|
"", /* word 83 bit 14: valid bit */ |
|
|
"FLUSH CACHE EXT cmd", /* word 83 bit 13 */ |
|
|
"Mandatory FLUSH CACHE cmd ", /* word 83 bit 12 */ |
|
|
"Device Configuration Overlay feature set ", |
|
|
"48-bit Address feature set ", /* word 83 bit 10 */ |
|
|
"", |
|
|
"SET MAX security extension", /* word 83 bit 8 */ |
|
|
"Address Offset Reserved Area Boot", /* word 83 bit 7 */ |
|
|
"SET FEATURES subcommand required to spinup after power up", |
|
|
"Power-Up In Standby feature set", /* word 83 bit 5 */ |
|
|
"Removable Media Status Notification feature set", |
|
|
"Adv. Power Management feature set",/* word 83 bit 3 */ |
|
|
"CFA feature set", /* word 83 bit 2 */ |
|
|
"READ/WRITE DMA QUEUED", /* word 83 bit 1 */ |
|
|
"DOWNLOAD MICROCODE cmd", /* word 83 bit 0 */ |
|
|
/* --------------*/ |
|
|
"", /* word 84 bit 15: !valid bit */ |
|
|
"", /* word 84 bit 14: valid bit */ |
|
|
"", /* word 84 bit 13: reserved */ |
|
|
"", /* word 84 bit 12: reserved */ |
|
|
"", /* word 84 bit 11: reserved */ |
|
|
"", /* word 84 bit 10: reserved */ |
|
|
"", /* word 84 bit 9: reserved */ |
|
|
"", /* word 84 bit 8: reserved */ |
|
|
"", /* word 84 bit 7: reserved */ |
|
|
"", /* word 84 bit 6: reserved */ |
|
|
"General Purpose Logging feature set", /* word 84 bit 5 */ |
|
|
"", /* word 84 bit 4: reserved */ |
|
|
"Media Card Pass Through Command feature set ", |
|
|
"Media serial number ", /* word 84 bit 2 */ |
|
|
"SMART self-test ", /* word 84 bit 1 */ |
|
|
"SMART error logging " /* word 84 bit 0 */ |
|
|
}; |
|
|
|
|
|
static void identify(uint16_t *id_supplied) ATTRIBUTE_NORETURN; |
|
|
static void identify_from_stdin(void) ATTRIBUTE_NORETURN; |
|
|
#else |
|
|
void identify_from_stdin(void); |
|
|
#endif |
|
|
|
|
|
|
|
192 |
/* words 85-87: cmds/feats enabled */ |
/* words 85-87: cmds/feats enabled */ |
193 |
/* use cmd_feat_str[] to display what commands and features have |
/* use cmd_feat_str[] to display what commands and features have |
194 |
* been enabled with words 85-87 |
* been enabled with words 85-87 |
195 |
*/ |
*/ |
196 |
|
|
197 |
/* words 89, 90, SECU ERASE TIME */ |
/* words 89, 90, SECU ERASE TIME */ |
198 |
#define ERASE_BITS 0x00ff |
#define ERASE_BITS 0x00ff |
199 |
|
|
200 |
/* word 92: master password revision */ |
/* word 92: master password revision */ |
201 |
/* NOVAL_0 or NOVAL_1 means no support for master password revision */ |
/* NOVAL_0 or NOVAL_1 means no support for master password revision */ |
202 |
|
|
203 |
/* word 93: hw reset result */ |
/* word 93: hw reset result */ |
204 |
#define CBLID 0x2000 /* CBLID status */ |
#define CBLID 0x2000 /* CBLID status */ |
205 |
#define RST0 0x0001 /* 1=reset to device #0 */ |
#define RST0 0x0001 /* 1=reset to device #0 */ |
206 |
#define DEV_DET 0x0006 /* how device num determined */ |
#define DEV_DET 0x0006 /* how device num determined */ |
207 |
#define JUMPER_VAL 0x0002 /* device num determined by jumper */ |
#define JUMPER_VAL 0x0002 /* device num determined by jumper */ |
208 |
#define CSEL_VAL 0x0004 /* device num determined by CSEL_VAL */ |
#define CSEL_VAL 0x0004 /* device num determined by CSEL_VAL */ |
209 |
|
|
210 |
/* word 127: removable media status notification feature set support */ |
/* word 127: removable media status notification feature set support */ |
211 |
#define RM_STAT_BITS 0x0003 |
#define RM_STAT_BITS 0x0003 |
212 |
#define RM_STAT_SUP 0x0001 |
#define RM_STAT_SUP 0x0001 |
213 |
|
|
214 |
/* word 128: security */ |
/* word 128: security */ |
215 |
#define SECU_ENABLED 0x0002 |
#define SECU_ENABLED 0x0002 |
216 |
#define SECU_LEVEL 0x0010 |
#define SECU_LEVEL 0x0010 |
217 |
#define NUM_SECU_STR 6 |
#define NUM_SECU_STR 6 |
|
#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY |
|
|
static const char * const secu_str[] = { |
|
|
"supported", /* word 128, bit 0 */ |
|
|
"enabled", /* word 128, bit 1 */ |
|
|
"locked", /* word 128, bit 2 */ |
|
|
"frozen", /* word 128, bit 3 */ |
|
|
"expired: security count", /* word 128, bit 4 */ |
|
|
"supported: enhanced erase" /* word 128, bit 5 */ |
|
|
}; |
|
|
#endif |
|
218 |
|
|
219 |
/* word 160: CFA power mode */ |
/* word 160: CFA power mode */ |
220 |
#define VALID_W160 0x8000 /* 1=word valid */ |
#define VALID_W160 0x8000 /* 1=word valid */ |
221 |
#define PWR_MODE_REQ 0x2000 /* 1=CFA power mode req'd by some cmds*/ |
#define PWR_MODE_REQ 0x2000 /* 1=CFA power mode req'd by some cmds*/ |
222 |
#define PWR_MODE_OFF 0x1000 /* 1=CFA power moded disabled */ |
#define PWR_MODE_OFF 0x1000 /* 1=CFA power moded disabled */ |
223 |
#define MAX_AMPS 0x0fff /* value = max current in ma */ |
#define MAX_AMPS 0x0fff /* value = max current in ma */ |
224 |
|
|
225 |
/* word 255: integrity */ |
/* word 255: integrity */ |
226 |
#define SIG 0x00ff /* signature location */ |
#define SIG 0x00ff /* signature location */ |
227 |
#define SIG_VAL 0x00A5 /* signature value */ |
#define SIG_VAL 0x00a5 /* signature value */ |
228 |
|
|
229 |
|
#define TIMING_BUF_MB 1 |
230 |
|
#define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024) |
231 |
|
|
232 |
|
#undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */ |
233 |
|
|
234 |
|
|
235 |
#define TIMING_MB 64 |
enum { fd = 3 }; |
236 |
#define TIMING_BUF_MB 1 |
|
237 |
#define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024) |
|
238 |
#define TIMING_BUF_COUNT (timing_MB / TIMING_BUF_MB) |
struct globals { |
239 |
#define BUFCACHE_FACTOR 2 |
smallint get_identity, get_geom; |
240 |
|
smallint do_flush; |
241 |
|
smallint do_ctimings, do_timings; |
242 |
|
smallint reread_partn; |
243 |
|
smallint set_piomode, noisy_piomode; |
244 |
|
smallint set_readahead, get_readahead; |
245 |
|
smallint set_readonly, get_readonly; |
246 |
|
smallint set_unmask, get_unmask; |
247 |
|
smallint set_mult, get_mult; |
248 |
|
#ifdef HDIO_GET_QDMA |
249 |
|
smallint get_dma_q; |
250 |
|
#ifdef HDIO_SET_QDMA |
251 |
|
smallint set_dma_q; |
252 |
|
#endif |
253 |
|
#endif |
254 |
|
smallint set_nowerr, get_nowerr; |
255 |
|
smallint set_keep, get_keep; |
256 |
|
smallint set_io32bit, get_io32bit; |
257 |
|
int piomode; |
258 |
|
unsigned long Xreadahead; |
259 |
|
unsigned long readonly; |
260 |
|
unsigned long unmask; |
261 |
|
unsigned long mult; |
262 |
|
#ifdef HDIO_SET_QDMA |
263 |
|
unsigned long dma_q; |
264 |
|
#endif |
265 |
|
unsigned long nowerr; |
266 |
|
unsigned long keep; |
267 |
|
unsigned long io32bit; |
268 |
|
#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA |
269 |
|
unsigned long dma; |
270 |
|
smallint set_dma, get_dma; |
271 |
|
#endif |
272 |
|
#ifdef HDIO_DRIVE_CMD |
273 |
|
smallint set_xfermode, get_xfermode; |
274 |
|
smallint set_dkeep, get_dkeep; |
275 |
|
smallint set_standby, get_standby; |
276 |
|
smallint set_lookahead, get_lookahead; |
277 |
|
smallint set_prefetch, get_prefetch; |
278 |
|
smallint set_defects, get_defects; |
279 |
|
smallint set_wcache, get_wcache; |
280 |
|
smallint set_doorlock, get_doorlock; |
281 |
|
smallint set_seagate, get_seagate; |
282 |
|
smallint set_standbynow, get_standbynow; |
283 |
|
smallint set_sleepnow, get_sleepnow; |
284 |
|
smallint get_powermode; |
285 |
|
smallint set_apmmode, get_apmmode; |
286 |
|
int xfermode_requested; |
287 |
|
unsigned long dkeep; |
288 |
|
unsigned long standby_requested; /* 0..255 */ |
289 |
|
unsigned long lookahead; |
290 |
|
unsigned long prefetch; |
291 |
|
unsigned long defects; |
292 |
|
unsigned long wcache; |
293 |
|
unsigned long doorlock; |
294 |
|
unsigned long apmmode; |
295 |
|
#endif |
296 |
|
USE_FEATURE_HDPARM_GET_IDENTITY( smallint get_IDentity;) |
297 |
|
USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( smallint set_busstate, get_busstate;) |
298 |
|
USE_FEATURE_HDPARM_HDIO_DRIVE_RESET( smallint perform_reset;) |
299 |
|
USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( smallint perform_tristate;) |
300 |
|
USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(smallint unregister_hwif;) |
301 |
|
USE_FEATURE_HDPARM_HDIO_SCAN_HWIF( smallint scan_hwif;) |
302 |
|
USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( unsigned long busstate;) |
303 |
|
USE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF( unsigned long tristate;) |
304 |
|
USE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF(unsigned long hwif;) |
305 |
|
#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF |
306 |
|
unsigned long hwif_data; |
307 |
|
unsigned long hwif_ctrl; |
308 |
|
unsigned long hwif_irq; |
309 |
|
#endif |
310 |
|
#ifdef DO_FLUSHCACHE |
311 |
|
unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 }; |
312 |
|
#endif |
313 |
|
}; |
314 |
|
#define G (*(struct globals*)&bb_common_bufsiz1) |
315 |
|
struct BUG_G_too_big { |
316 |
|
char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; |
317 |
|
}; |
318 |
|
#define get_identity (G.get_identity ) |
319 |
|
#define get_geom (G.get_geom ) |
320 |
|
#define do_flush (G.do_flush ) |
321 |
|
#define do_ctimings (G.do_ctimings ) |
322 |
|
#define do_timings (G.do_timings ) |
323 |
|
#define reread_partn (G.reread_partn ) |
324 |
|
#define set_piomode (G.set_piomode ) |
325 |
|
#define noisy_piomode (G.noisy_piomode ) |
326 |
|
#define set_readahead (G.set_readahead ) |
327 |
|
#define get_readahead (G.get_readahead ) |
328 |
|
#define set_readonly (G.set_readonly ) |
329 |
|
#define get_readonly (G.get_readonly ) |
330 |
|
#define set_unmask (G.set_unmask ) |
331 |
|
#define get_unmask (G.get_unmask ) |
332 |
|
#define set_mult (G.set_mult ) |
333 |
|
#define get_mult (G.get_mult ) |
334 |
|
#define set_dma_q (G.set_dma_q ) |
335 |
|
#define get_dma_q (G.get_dma_q ) |
336 |
|
#define set_nowerr (G.set_nowerr ) |
337 |
|
#define get_nowerr (G.get_nowerr ) |
338 |
|
#define set_keep (G.set_keep ) |
339 |
|
#define get_keep (G.get_keep ) |
340 |
|
#define set_io32bit (G.set_io32bit ) |
341 |
|
#define get_io32bit (G.get_io32bit ) |
342 |
|
#define piomode (G.piomode ) |
343 |
|
#define Xreadahead (G.Xreadahead ) |
344 |
|
#define readonly (G.readonly ) |
345 |
|
#define unmask (G.unmask ) |
346 |
|
#define mult (G.mult ) |
347 |
|
#define dma_q (G.dma_q ) |
348 |
|
#define nowerr (G.nowerr ) |
349 |
|
#define keep (G.keep ) |
350 |
|
#define io32bit (G.io32bit ) |
351 |
|
#define dma (G.dma ) |
352 |
|
#define set_dma (G.set_dma ) |
353 |
|
#define get_dma (G.get_dma ) |
354 |
|
#define set_xfermode (G.set_xfermode ) |
355 |
|
#define get_xfermode (G.get_xfermode ) |
356 |
|
#define set_dkeep (G.set_dkeep ) |
357 |
|
#define get_dkeep (G.get_dkeep ) |
358 |
|
#define set_standby (G.set_standby ) |
359 |
|
#define get_standby (G.get_standby ) |
360 |
|
#define set_lookahead (G.set_lookahead ) |
361 |
|
#define get_lookahead (G.get_lookahead ) |
362 |
|
#define set_prefetch (G.set_prefetch ) |
363 |
|
#define get_prefetch (G.get_prefetch ) |
364 |
|
#define set_defects (G.set_defects ) |
365 |
|
#define get_defects (G.get_defects ) |
366 |
|
#define set_wcache (G.set_wcache ) |
367 |
|
#define get_wcache (G.get_wcache ) |
368 |
|
#define set_doorlock (G.set_doorlock ) |
369 |
|
#define get_doorlock (G.get_doorlock ) |
370 |
|
#define set_seagate (G.set_seagate ) |
371 |
|
#define get_seagate (G.get_seagate ) |
372 |
|
#define set_standbynow (G.set_standbynow ) |
373 |
|
#define get_standbynow (G.get_standbynow ) |
374 |
|
#define set_sleepnow (G.set_sleepnow ) |
375 |
|
#define get_sleepnow (G.get_sleepnow ) |
376 |
|
#define get_powermode (G.get_powermode ) |
377 |
|
#define set_apmmode (G.set_apmmode ) |
378 |
|
#define get_apmmode (G.get_apmmode ) |
379 |
|
#define xfermode_requested (G.xfermode_requested ) |
380 |
|
#define dkeep (G.dkeep ) |
381 |
|
#define standby_requested (G.standby_requested ) |
382 |
|
#define lookahead (G.lookahead ) |
383 |
|
#define prefetch (G.prefetch ) |
384 |
|
#define defects (G.defects ) |
385 |
|
#define wcache (G.wcache ) |
386 |
|
#define doorlock (G.doorlock ) |
387 |
|
#define apmmode (G.apmmode ) |
388 |
|
#define get_IDentity (G.get_IDentity ) |
389 |
|
#define set_busstate (G.set_busstate ) |
390 |
|
#define get_busstate (G.get_busstate ) |
391 |
|
#define perform_reset (G.perform_reset ) |
392 |
|
#define perform_tristate (G.perform_tristate ) |
393 |
|
#define unregister_hwif (G.unregister_hwif ) |
394 |
|
#define scan_hwif (G.scan_hwif ) |
395 |
|
#define busstate (G.busstate ) |
396 |
|
#define tristate (G.tristate ) |
397 |
|
#define hwif (G.hwif ) |
398 |
|
#define hwif_data (G.hwif_data ) |
399 |
|
#define hwif_ctrl (G.hwif_ctrl ) |
400 |
|
#define hwif_irq (G.hwif_irq ) |
401 |
|
|
|
#undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */ |
|
402 |
|
|
403 |
/* Busybox messages and functions */ |
/* Busybox messages and functions */ |
404 |
static int bb_ioctl(int fd, int request, void *argp, const char *string) |
#if ENABLE_IOCTL_HEX2STR_ERROR |
405 |
|
static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt, const char *string) |
406 |
{ |
{ |
407 |
int e = ioctl(fd, request, argp); |
if (!ioctl(fd, cmd, args)) |
408 |
if (e && string) |
return 0; |
409 |
bb_perror_msg(" %s", string); |
args[0] = alt; |
410 |
return e; |
return bb_ioctl_or_warn(fd, cmd, args, string); |
411 |
} |
} |
412 |
|
#define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt,#cmd) |
413 |
static int bb_ioctl_alt(int fd, int cmd, unsigned char *args, int alt, const char *string) |
#else |
414 |
|
static int ioctl_alt_func(/*int fd,*/ int cmd, unsigned char *args, int alt) |
415 |
{ |
{ |
416 |
if (!ioctl(fd, cmd, args)) |
if (!ioctl(fd, cmd, args)) |
417 |
return 0; |
return 0; |
418 |
args[0] = alt; |
args[0] = alt; |
419 |
return bb_ioctl(fd, cmd, args, string); |
return bb_ioctl_or_warn(fd, cmd, args); |
420 |
} |
} |
421 |
|
#define ioctl_alt_or_warn(cmd,args,alt) ioctl_alt_func(cmd,args,alt) |
422 |
|
#endif |
423 |
|
|
424 |
static void on_off(unsigned int value); |
static void on_off(int value) |
|
|
|
|
static void print_flag_on_off(unsigned long get_arg, const char *s, unsigned long arg) |
|
425 |
{ |
{ |
426 |
|
puts(value ? " (on)" : " (off)"); |
427 |
|
} |
428 |
|
|
429 |
if (get_arg) |
static void print_flag_on_off(int get_arg, const char *s, unsigned long arg) |
430 |
{ |
{ |
431 |
|
if (get_arg) { |
432 |
printf(" setting %s to %ld", s, arg); |
printf(" setting %s to %ld", s, arg); |
433 |
on_off(arg); |
on_off(arg); |
434 |
} |
} |
435 |
} |
} |
436 |
|
|
437 |
static void bb_ioctl_on_off(int fd, int request, void *argp, const char *string, |
static void print_value_on_off(const char *str, unsigned long argp) |
|
const char * str) |
|
438 |
{ |
{ |
439 |
if (ioctl(fd, request, &argp) != 0) |
printf(" %s\t= %2ld", str, argp); |
440 |
bb_perror_msg(" %s", string); |
on_off(argp != 0); |
|
else |
|
|
{ |
|
|
printf(" %s\t= %2ld", str, (unsigned long) argp); |
|
|
on_off((unsigned long) argp); |
|
|
} |
|
441 |
} |
} |
442 |
|
|
443 |
#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY |
#if ENABLE_FEATURE_HDPARM_GET_IDENTITY |
444 |
static void print_ascii(uint16_t *p, uint8_t length); |
static void print_ascii(const char *p, int length) |
445 |
|
{ |
446 |
|
#if BB_BIG_ENDIAN |
447 |
|
#define LE_ONLY(x) |
448 |
|
enum { ofs = 0 }; |
449 |
|
#else |
450 |
|
#define LE_ONLY(x) x |
451 |
|
/* every 16bit word is big-endian (i.e. inverted) */ |
452 |
|
/* accessing bytes in 1,0, 3,2, 5,4... sequence */ |
453 |
|
int ofs = 1; |
454 |
|
#endif |
455 |
|
|
456 |
static void xprint_ascii(uint16_t *val ,int i, char * string, int n) |
length *= 2; |
457 |
|
/* find first non-space & print it */ |
458 |
|
while (length && p[ofs] != ' ') { |
459 |
|
p++; |
460 |
|
LE_ONLY(ofs = -ofs;) |
461 |
|
length--; |
462 |
|
} |
463 |
|
while (length && p[ofs]) { |
464 |
|
bb_putchar(p[ofs]); |
465 |
|
p++; |
466 |
|
LE_ONLY(ofs = -ofs;) |
467 |
|
length--; |
468 |
|
} |
469 |
|
bb_putchar('\n'); |
470 |
|
#undef LE_ONLY |
471 |
|
} |
472 |
|
|
473 |
|
static void xprint_ascii(uint16_t *val, int i, const char *string, int n) |
474 |
{ |
{ |
475 |
if (val[i]) |
if (val[i]) { |
476 |
{ |
printf("\t%-20s", string); |
477 |
printf("\t%-20s",string); |
print_ascii((void*)&val[i], n); |
|
print_ascii(&val[i], n); |
|
478 |
} |
} |
479 |
} |
} |
|
#endif |
|
|
/* end of busybox specific stuff */ |
|
480 |
|
|
|
#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY |
|
481 |
static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode) |
static uint8_t mode_loop(uint16_t mode_sup, uint16_t mode_sel, int cc, uint8_t *have_mode) |
482 |
{ |
{ |
483 |
uint16_t ii; |
uint16_t ii; |
484 |
uint8_t err_dma = 0; |
uint8_t err_dma = 0; |
485 |
|
|
486 |
for (ii = 0; ii <= MODE_MAX; ii++) |
for (ii = 0; ii <= MODE_MAX; ii++) { |
487 |
{ |
if (mode_sel & 0x0001) { |
488 |
if (mode_sel & 0x0001) |
printf("*%cdma%u ", cc, ii); |
|
{ |
|
|
printf("*%cdma%u ",cc,ii); |
|
489 |
if (*have_mode) |
if (*have_mode) |
490 |
err_dma = 1; |
err_dma = 1; |
491 |
*have_mode = 1; |
*have_mode = 1; |
492 |
} |
} else if (mode_sup & 0x0001) |
493 |
else if (mode_sup & 0x0001) |
printf("%cdma%u ", cc, ii); |
|
printf("%cdma%u ",cc,ii); |
|
494 |
|
|
495 |
mode_sup >>=1; |
mode_sup >>= 1; |
496 |
mode_sel >>=1; |
mode_sel >>= 1; |
497 |
} |
} |
498 |
return err_dma; |
return err_dma; |
499 |
} |
} |
500 |
|
|
501 |
static void print_ascii(uint16_t *p, uint8_t length) { |
static const char pkt_str[] ALIGN1 = |
502 |
uint8_t ii; |
"Direct-access device" "\0" /* word 0, bits 12-8 = 00 */ |
503 |
char cl; |
"Sequential-access device" "\0" /* word 0, bits 12-8 = 01 */ |
504 |
|
"Printer" "\0" /* word 0, bits 12-8 = 02 */ |
505 |
|
"Processor" "\0" /* word 0, bits 12-8 = 03 */ |
506 |
|
"Write-once device" "\0" /* word 0, bits 12-8 = 04 */ |
507 |
|
"CD-ROM" "\0" /* word 0, bits 12-8 = 05 */ |
508 |
|
"Scanner" "\0" /* word 0, bits 12-8 = 06 */ |
509 |
|
"Optical memory" "\0" /* word 0, bits 12-8 = 07 */ |
510 |
|
"Medium changer" "\0" /* word 0, bits 12-8 = 08 */ |
511 |
|
"Communications device" "\0" /* word 0, bits 12-8 = 09 */ |
512 |
|
"ACS-IT8 device" "\0" /* word 0, bits 12-8 = 0a */ |
513 |
|
"ACS-IT8 device" "\0" /* word 0, bits 12-8 = 0b */ |
514 |
|
"Array controller" "\0" /* word 0, bits 12-8 = 0c */ |
515 |
|
"Enclosure services" "\0" /* word 0, bits 12-8 = 0d */ |
516 |
|
"Reduced block command device" "\0" /* word 0, bits 12-8 = 0e */ |
517 |
|
"Optical card reader/writer" "\0" /* word 0, bits 12-8 = 0f */ |
518 |
|
; |
519 |
|
|
520 |
|
static const char ata1_cfg_str[] ALIGN1 = /* word 0 in ATA-1 mode */ |
521 |
|
"reserved" "\0" /* bit 0 */ |
522 |
|
"hard sectored" "\0" /* bit 1 */ |
523 |
|
"soft sectored" "\0" /* bit 2 */ |
524 |
|
"not MFM encoded " "\0" /* bit 3 */ |
525 |
|
"head switch time > 15us" "\0" /* bit 4 */ |
526 |
|
"spindle motor control option" "\0" /* bit 5 */ |
527 |
|
"fixed drive" "\0" /* bit 6 */ |
528 |
|
"removable drive" "\0" /* bit 7 */ |
529 |
|
"disk xfer rate <= 5Mbs" "\0" /* bit 8 */ |
530 |
|
"disk xfer rate > 5Mbs, <= 10Mbs" "\0" /* bit 9 */ |
531 |
|
"disk xfer rate > 5Mbs" "\0" /* bit 10 */ |
532 |
|
"rotational speed tol." "\0" /* bit 11 */ |
533 |
|
"data strobe offset option" "\0" /* bit 12 */ |
534 |
|
"track offset option" "\0" /* bit 13 */ |
535 |
|
"format speed tolerance gap reqd" "\0" /* bit 14 */ |
536 |
|
"ATAPI" /* bit 14 */ |
537 |
|
; |
538 |
|
|
539 |
|
static const char minor_str[] ALIGN1 = |
540 |
|
/* word 81 value: */ |
541 |
|
"Unspecified" "\0" /* 0x0000 */ |
542 |
|
"ATA-1 X3T9.2 781D prior to rev.4" "\0" /* 0x0001 */ |
543 |
|
"ATA-1 published, ANSI X3.221-1994" "\0" /* 0x0002 */ |
544 |
|
"ATA-1 X3T9.2 781D rev.4" "\0" /* 0x0003 */ |
545 |
|
"ATA-2 published, ANSI X3.279-1996" "\0" /* 0x0004 */ |
546 |
|
"ATA-2 X3T10 948D prior to rev.2k" "\0" /* 0x0005 */ |
547 |
|
"ATA-3 X3T10 2008D rev.1" "\0" /* 0x0006 */ |
548 |
|
"ATA-2 X3T10 948D rev.2k" "\0" /* 0x0007 */ |
549 |
|
"ATA-3 X3T10 2008D rev.0" "\0" /* 0x0008 */ |
550 |
|
"ATA-2 X3T10 948D rev.3" "\0" /* 0x0009 */ |
551 |
|
"ATA-3 published, ANSI X3.298-199x" "\0" /* 0x000a */ |
552 |
|
"ATA-3 X3T10 2008D rev.6" "\0" /* 0x000b */ |
553 |
|
"ATA-3 X3T13 2008D rev.7 and 7a" "\0" /* 0x000c */ |
554 |
|
"ATA/ATAPI-4 X3T13 1153D rev.6" "\0" /* 0x000d */ |
555 |
|
"ATA/ATAPI-4 T13 1153D rev.13" "\0" /* 0x000e */ |
556 |
|
"ATA/ATAPI-4 X3T13 1153D rev.7" "\0" /* 0x000f */ |
557 |
|
"ATA/ATAPI-4 T13 1153D rev.18" "\0" /* 0x0010 */ |
558 |
|
"ATA/ATAPI-4 T13 1153D rev.15" "\0" /* 0x0011 */ |
559 |
|
"ATA/ATAPI-4 published, ANSI INCITS 317-1998" "\0" /* 0x0012 */ |
560 |
|
"ATA/ATAPI-5 T13 1321D rev.3" "\0" /* 0x0013 */ |
561 |
|
"ATA/ATAPI-4 T13 1153D rev.14" "\0" /* 0x0014 */ |
562 |
|
"ATA/ATAPI-5 T13 1321D rev.1" "\0" /* 0x0015 */ |
563 |
|
"ATA/ATAPI-5 published, ANSI INCITS 340-2000" "\0" /* 0x0016 */ |
564 |
|
"ATA/ATAPI-4 T13 1153D rev.17" "\0" /* 0x0017 */ |
565 |
|
"ATA/ATAPI-6 T13 1410D rev.0" "\0" /* 0x0018 */ |
566 |
|
"ATA/ATAPI-6 T13 1410D rev.3a" "\0" /* 0x0019 */ |
567 |
|
"ATA/ATAPI-7 T13 1532D rev.1" "\0" /* 0x001a */ |
568 |
|
"ATA/ATAPI-6 T13 1410D rev.2" "\0" /* 0x001b */ |
569 |
|
"ATA/ATAPI-6 T13 1410D rev.1" "\0" /* 0x001c */ |
570 |
|
"ATA/ATAPI-7 published, ANSI INCITS 397-2005" "\0" /* 0x001d */ |
571 |
|
"ATA/ATAPI-7 T13 1532D rev.0" "\0" /* 0x001e */ |
572 |
|
"reserved" "\0" /* 0x001f */ |
573 |
|
"reserved" "\0" /* 0x0020 */ |
574 |
|
"ATA/ATAPI-7 T13 1532D rev.4a" "\0" /* 0x0021 */ |
575 |
|
"ATA/ATAPI-6 published, ANSI INCITS 361-2002" "\0" /* 0x0022 */ |
576 |
|
"reserved" /* 0x0023-0xfffe */ |
577 |
|
; |
578 |
|
static const char actual_ver[MINOR_MAX + 2] ALIGN1 = { |
579 |
|
/* word 81 value: */ |
580 |
|
0, /* 0x0000 WARNING: actual_ver[] array */ |
581 |
|
1, /* 0x0001 WARNING: corresponds */ |
582 |
|
1, /* 0x0002 WARNING: *exactly* */ |
583 |
|
1, /* 0x0003 WARNING: to the ATA/ */ |
584 |
|
2, /* 0x0004 WARNING: ATAPI version */ |
585 |
|
2, /* 0x0005 WARNING: listed in */ |
586 |
|
3, /* 0x0006 WARNING: the */ |
587 |
|
2, /* 0x0007 WARNING: minor_str */ |
588 |
|
3, /* 0x0008 WARNING: array */ |
589 |
|
2, /* 0x0009 WARNING: above. */ |
590 |
|
3, /* 0x000a WARNING: */ |
591 |
|
3, /* 0x000b WARNING: If you change */ |
592 |
|
3, /* 0x000c WARNING: that one, */ |
593 |
|
4, /* 0x000d WARNING: change this one */ |
594 |
|
4, /* 0x000e WARNING: too!!! */ |
595 |
|
4, /* 0x000f */ |
596 |
|
4, /* 0x0010 */ |
597 |
|
4, /* 0x0011 */ |
598 |
|
4, /* 0x0012 */ |
599 |
|
5, /* 0x0013 */ |
600 |
|
4, /* 0x0014 */ |
601 |
|
5, /* 0x0015 */ |
602 |
|
5, /* 0x0016 */ |
603 |
|
4, /* 0x0017 */ |
604 |
|
6, /* 0x0018 */ |
605 |
|
6, /* 0x0019 */ |
606 |
|
7, /* 0x001a */ |
607 |
|
6, /* 0x001b */ |
608 |
|
6, /* 0x001c */ |
609 |
|
7, /* 0x001d */ |
610 |
|
7, /* 0x001e */ |
611 |
|
0, /* 0x001f */ |
612 |
|
0, /* 0x0020 */ |
613 |
|
7, /* 0x0021 */ |
614 |
|
6, /* 0x0022 */ |
615 |
|
0 /* 0x0023-0xfffe */ |
616 |
|
}; |
617 |
|
|
618 |
/* find first non-space & print it */ |
static const char cmd_feat_str[] ALIGN1 = |
619 |
for (ii = 0; ii< length; ii++) |
"" "\0" /* word 82 bit 15: obsolete */ |
620 |
{ |
"NOP cmd" "\0" /* word 82 bit 14 */ |
621 |
if (((char) 0x00ff&((*p)>>8)) != ' ') |
"READ BUFFER cmd" "\0" /* word 82 bit 13 */ |
622 |
break; |
"WRITE BUFFER cmd" "\0" /* word 82 bit 12 */ |
623 |
if ((cl = (char) 0x00ff&(*p)) != ' ') |
"" "\0" /* word 82 bit 11: obsolete */ |
624 |
{ |
"Host Protected Area feature set" "\0" /* word 82 bit 10 */ |
625 |
if (cl != '\0') printf("%c",cl); |
"DEVICE RESET cmd" "\0" /* word 82 bit 9 */ |
626 |
p++; |
"SERVICE interrupt" "\0" /* word 82 bit 8 */ |
627 |
ii++; |
"Release interrupt" "\0" /* word 82 bit 7 */ |
628 |
break; |
"Look-ahead" "\0" /* word 82 bit 6 */ |
629 |
} |
"Write cache" "\0" /* word 82 bit 5 */ |
630 |
p++; |
"PACKET command feature set" "\0" /* word 82 bit 4 */ |
631 |
} |
"Power Management feature set" "\0" /* word 82 bit 3 */ |
632 |
/* print the rest */ |
"Removable Media feature set" "\0" /* word 82 bit 2 */ |
633 |
for (; ii< length; ii++) |
"Security Mode feature set" "\0" /* word 82 bit 1 */ |
634 |
{ |
"SMART feature set" "\0" /* word 82 bit 0 */ |
635 |
if (!(*p)) |
/* -------------- */ |
636 |
break; /* some older devices have NULLs */ |
"" "\0" /* word 83 bit 15: !valid bit */ |
637 |
printf("%c%c",(char)0x00ff&((*p)>>8),(char)(*p)&0x00ff); |
"" "\0" /* word 83 bit 14: valid bit */ |
638 |
p++; |
"FLUSH CACHE EXT cmd" "\0" /* word 83 bit 13 */ |
639 |
} |
"Mandatory FLUSH CACHE cmd " "\0" /* word 83 bit 12 */ |
640 |
puts(""); |
"Device Configuration Overlay feature set " "\0" |
641 |
} |
"48-bit Address feature set " "\0" /* word 83 bit 10 */ |
642 |
|
"" "\0" |
643 |
|
"SET MAX security extension" "\0" /* word 83 bit 8 */ |
644 |
|
"Address Offset Reserved Area Boot" "\0" /* word 83 bit 7 */ |
645 |
|
"SET FEATURES subcommand required to spinup after power up" "\0" |
646 |
|
"Power-Up In Standby feature set" "\0" /* word 83 bit 5 */ |
647 |
|
"Removable Media Status Notification feature set" "\0" |
648 |
|
"Adv. Power Management feature set" "\0" /* word 83 bit 3 */ |
649 |
|
"CFA feature set" "\0" /* word 83 bit 2 */ |
650 |
|
"READ/WRITE DMA QUEUED" "\0" /* word 83 bit 1 */ |
651 |
|
"DOWNLOAD MICROCODE cmd" "\0" /* word 83 bit 0 */ |
652 |
|
/* -------------- */ |
653 |
|
"" "\0" /* word 84 bit 15: !valid bit */ |
654 |
|
"" "\0" /* word 84 bit 14: valid bit */ |
655 |
|
"" "\0" /* word 84 bit 13: reserved */ |
656 |
|
"" "\0" /* word 84 bit 12: reserved */ |
657 |
|
"" "\0" /* word 84 bit 11: reserved */ |
658 |
|
"" "\0" /* word 84 bit 10: reserved */ |
659 |
|
"" "\0" /* word 84 bit 9: reserved */ |
660 |
|
"" "\0" /* word 84 bit 8: reserved */ |
661 |
|
"" "\0" /* word 84 bit 7: reserved */ |
662 |
|
"" "\0" /* word 84 bit 6: reserved */ |
663 |
|
"General Purpose Logging feature set" "\0" /* word 84 bit 5 */ |
664 |
|
"" "\0" /* word 84 bit 4: reserved */ |
665 |
|
"Media Card Pass Through Command feature set " "\0" |
666 |
|
"Media serial number " "\0" /* word 84 bit 2 */ |
667 |
|
"SMART self-test " "\0" /* word 84 bit 1 */ |
668 |
|
"SMART error logging " /* word 84 bit 0 */ |
669 |
|
; |
670 |
|
|
671 |
|
static const char secu_str[] ALIGN1 = |
672 |
|
"supported" "\0" /* word 128, bit 0 */ |
673 |
|
"enabled" "\0" /* word 128, bit 1 */ |
674 |
|
"locked" "\0" /* word 128, bit 2 */ |
675 |
|
"frozen" "\0" /* word 128, bit 3 */ |
676 |
|
"expired: security count" "\0" /* word 128, bit 4 */ |
677 |
|
"supported: enhanced erase" /* word 128, bit 5 */ |
678 |
|
; |
679 |
|
|
680 |
// Parse 512 byte disk identification block and print much crap. |
// Parse 512 byte disk identification block and print much crap. |
681 |
|
static void identify(uint16_t *val) NORETURN; |
682 |
static void identify(uint16_t *id_supplied) |
static void identify(uint16_t *val) |
683 |
{ |
{ |
684 |
uint16_t buf[256]; |
uint16_t ii, jj, kk; |
|
uint16_t *val, ii, jj, kk; |
|
685 |
uint16_t like_std = 1, std = 0, min_std = 0xffff; |
uint16_t like_std = 1, std = 0, min_std = 0xffff; |
686 |
uint16_t dev = NO_DEV, eqpt = NO_DEV; |
uint16_t dev = NO_DEV, eqpt = NO_DEV; |
687 |
uint8_t have_mode = 0, err_dma = 0; |
uint8_t have_mode = 0, err_dma = 0; |
689 |
uint32_t ll, mm, nn, oo; |
uint32_t ll, mm, nn, oo; |
690 |
uint64_t bbbig; /* (:) */ |
uint64_t bbbig; /* (:) */ |
691 |
const char *strng; |
const char *strng; |
692 |
|
#if BB_BIG_ENDIAN |
693 |
|
uint16_t buf[256]; |
694 |
|
|
695 |
// Adjust for endianness if necessary. |
// Adjust for endianness |
696 |
|
swab(val, buf, sizeof(buf)); |
697 |
if (BB_BIG_ENDIAN) { |
val = buf; |
698 |
swab(id_supplied, buf, sizeof(buf)); |
#endif |
|
val = buf; |
|
|
} else val = id_supplied; |
|
|
|
|
|
chksum &= 0xff; |
|
|
|
|
699 |
/* check if we recognise the device type */ |
/* check if we recognise the device type */ |
700 |
puts(""); |
bb_putchar('\n'); |
701 |
if (!(val[GEN_CONFIG] & NOT_ATA)) |
if (!(val[GEN_CONFIG] & NOT_ATA)) { |
|
{ |
|
702 |
dev = ATA_DEV; |
dev = ATA_DEV; |
703 |
printf("ATA device, with "); |
printf("ATA device, with "); |
704 |
} |
} else if (val[GEN_CONFIG]==CFA_SUPPORT_VAL) { |
|
else if (val[GEN_CONFIG]==CFA_SUPPORT_VAL) |
|
|
{ |
|
705 |
dev = ATA_DEV; |
dev = ATA_DEV; |
706 |
like_std = 4; |
like_std = 4; |
707 |
printf("CompactFlash ATA device, with "); |
printf("CompactFlash ATA device, with "); |
708 |
} |
} else if (!(val[GEN_CONFIG] & NOT_ATAPI)) { |
|
else if (!(val[GEN_CONFIG] & NOT_ATAPI)) |
|
|
{ |
|
709 |
dev = ATAPI_DEV; |
dev = ATAPI_DEV; |
710 |
eqpt = (val[GEN_CONFIG] & EQPT_TYPE) >> SHIFT_EQPT; |
eqpt = (val[GEN_CONFIG] & EQPT_TYPE) >> SHIFT_EQPT; |
711 |
printf("ATAPI %s, with ", pkt_str[eqpt]); |
printf("ATAPI %s, with ", eqpt <= 0xf ? nth_string(pkt_str, eqpt) : "unknown"); |
712 |
like_std = 3; |
like_std = 3; |
713 |
} |
} else |
714 |
else |
/* "Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n" */ |
|
/*"Unknown device type:\n\tbits 15&14 of general configuration word 0 both set to 1.\n"*/ |
|
715 |
bb_error_msg_and_die("unknown device type"); |
bb_error_msg_and_die("unknown device type"); |
716 |
|
|
717 |
printf("%sremovable media\n", !(val[GEN_CONFIG] & MEDIA_REMOVABLE) ? "non-" : ""); |
printf("%sremovable media\n", !(val[GEN_CONFIG] & MEDIA_REMOVABLE) ? "non-" : ""); |
722 |
* specific, it should be safe to check it now, even though we don't |
* specific, it should be safe to check it now, even though we don't |
723 |
* know yet what standard this device is using. |
* know yet what standard this device is using. |
724 |
*/ |
*/ |
725 |
if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL) || |
if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL) |
726 |
(val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL) ) |
|| (val[CONFIG]==PWRD_NID_VAL) || (val[CONFIG]==PWRD_ID_VAL) |
727 |
{ |
) { |
728 |
like_std = 5; |
like_std = 5; |
729 |
if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL)) |
if ((val[CONFIG]==STBY_NID_VAL) || (val[CONFIG]==STBY_ID_VAL)) |
730 |
printf("powers-up in standby; SET FEATURES subcmd spins-up.\n"); |
printf("powers-up in standby; SET FEATURES subcmd spins-up.\n"); |
742 |
/* major & minor standards version number (Note: these words were not |
/* major & minor standards version number (Note: these words were not |
743 |
* defined until ATA-3 & the CDROM std uses different words.) */ |
* defined until ATA-3 & the CDROM std uses different words.) */ |
744 |
printf("Standards:"); |
printf("Standards:"); |
745 |
if (eqpt != CDROM) |
if (eqpt != CDROM) { |
746 |
{ |
if (val[MINOR] && (val[MINOR] <= MINOR_MAX)) { |
|
if (val[MINOR] && (val[MINOR] <= MINOR_MAX)) |
|
|
{ |
|
747 |
if (like_std < 3) like_std = 3; |
if (like_std < 3) like_std = 3; |
748 |
std = actual_ver[val[MINOR]]; |
std = actual_ver[val[MINOR]]; |
749 |
if (std) printf("\n\tUsed: %s ",minor_str[val[MINOR]]); |
if (std) printf("\n\tUsed: %s ", nth_string(minor_str, val[MINOR])); |
750 |
|
|
751 |
} |
} |
752 |
/* looks like when they up-issue the std, they obsolete one; |
/* looks like when they up-issue the std, they obsolete one; |
753 |
* thus, only the newest 4 issues need be supported. (That's |
* thus, only the newest 4 issues need be supported. (That's |
754 |
* what "kk" and "min_std" are all about.) */ |
* what "kk" and "min_std" are all about.) */ |
755 |
if (val[MAJOR] && (val[MAJOR] !=NOVAL_1)) |
if (val[MAJOR] && (val[MAJOR] != NOVAL_1)) { |
|
{ |
|
756 |
printf("\n\tSupported: "); |
printf("\n\tSupported: "); |
757 |
jj = val[MAJOR] << 1; |
jj = val[MAJOR] << 1; |
758 |
kk = like_std >4 ? like_std-4: 0; |
kk = like_std >4 ? like_std-4: 0; |
759 |
for (ii = 14; (ii >0)&&(ii>kk); ii--) |
for (ii = 14; (ii >0)&&(ii>kk); ii--) { |
760 |
{ |
if (jj & 0x8000) { |
|
if (jj & 0x8000) |
|
|
{ |
|
761 |
printf("%u ", ii); |
printf("%u ", ii); |
762 |
if (like_std < ii) |
if (like_std < ii) { |
|
{ |
|
763 |
like_std = ii; |
like_std = ii; |
764 |
kk = like_std >4 ? like_std-4: 0; |
kk = like_std >4 ? like_std-4: 0; |
765 |
} |
} |
779 |
((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) && |
((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) && |
780 |
(( val[CMDS_SUPP_1] & CMDS_W83) > 0x00ff)) || |
(( val[CMDS_SUPP_1] & CMDS_W83) > 0x00ff)) || |
781 |
((( val[CMDS_SUPP_2] & VALID) == VALID_VAL) && |
((( val[CMDS_SUPP_2] & VALID) == VALID_VAL) && |
782 |
( val[CMDS_SUPP_2] & CMDS_W84) ) ) ) |
( val[CMDS_SUPP_2] & CMDS_W84) ) ) |
783 |
{ |
) { |
784 |
like_std = 6; |
like_std = 6; |
785 |
} |
} else if (((std == 4) || (!std && (like_std < 5))) && |
|
else if (((std == 4) || (!std && (like_std < 5))) && |
|
786 |
((((val[INTEGRITY] & SIG) == SIG_VAL) && !chksum) || |
((((val[INTEGRITY] & SIG) == SIG_VAL) && !chksum) || |
787 |
(( val[HWRST_RSLT] & VALID) == VALID_VAL) || |
(( val[HWRST_RSLT] & VALID) == VALID_VAL) || |
788 |
((( val[CMDS_SUPP_1] & VALID) == VALID_VAL) && |
((( val[CMDS_SUPP_1] & VALID) == VALID_VAL) && |
789 |
(( val[CMDS_SUPP_1] & CMDS_W83) > 0x001f)) ) ) |
(( val[CMDS_SUPP_1] & CMDS_W83) > 0x001f)) ) ) |
790 |
{ |
{ |
791 |
like_std = 5; |
like_std = 5; |
792 |
} |
} else if (((std == 3) || (!std && (like_std < 4))) && |
|
else if (((std == 3) || (!std && (like_std < 4))) && |
|
793 |
((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) && |
((((val[CMDS_SUPP_1] & VALID) == VALID_VAL) && |
794 |
((( val[CMDS_SUPP_1] & CMDS_W83) > 0x0000) || |
((( val[CMDS_SUPP_1] & CMDS_W83) > 0x0000) || |
795 |
(( val[CMDS_SUPP_0] & CMDS_W82) > 0x000f))) || |
(( val[CMDS_SUPP_0] & CMDS_W82) > 0x000f))) || |
796 |
(( val[CAPAB_1] & VALID) == VALID_VAL) || |
(( val[CAPAB_1] & VALID) == VALID_VAL) || |
797 |
(( val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) || |
(( val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) || |
798 |
(( val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) ) ) |
(( val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) ) |
799 |
{ |
) { |
800 |
like_std = 4; |
like_std = 4; |
801 |
} |
} else if (((std == 2) || (!std && (like_std < 3))) |
802 |
else if (((std == 2) || (!std && (like_std < 3))) && |
&& ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) |
803 |
((val[CMDS_SUPP_1] & VALID) == VALID_VAL) ) |
) { |
|
{ |
|
804 |
like_std = 3; |
like_std = 3; |
805 |
} |
} else if (((std == 1) || (!std && (like_std < 2))) && |
|
else if (((std == 1) || (!std && (like_std < 2))) && |
|
806 |
((val[CAPAB_0] & (IORDY_SUP | IORDY_OFF)) || |
((val[CAPAB_0] & (IORDY_SUP | IORDY_OFF)) || |
807 |
(val[WHATS_VALID] & OK_W64_70)) ) |
(val[WHATS_VALID] & OK_W64_70)) ) |
808 |
{ |
{ |
809 |
like_std = 2; |
like_std = 2; |
810 |
} |
} |
811 |
|
|
812 |
if (!std) |
if (!std) |
813 |
printf("\n\tLikely used: %u\n",like_std); |
printf("\n\tLikely used: %u\n", like_std); |
814 |
else if (like_std > std) |
else if (like_std > std) |
815 |
printf("& some of %u\n",like_std); |
printf("& some of %u\n", like_std); |
816 |
else |
else |
817 |
puts(""); |
bb_putchar('\n'); |
818 |
} |
} else { |
|
else |
|
|
{ |
|
819 |
/* TBD: do CDROM stuff more thoroughly. For now... */ |
/* TBD: do CDROM stuff more thoroughly. For now... */ |
820 |
kk = 0; |
kk = 0; |
821 |
if (val[CDR_MINOR] == 9) |
if (val[CDR_MINOR] == 9) { |
|
{ |
|
822 |
kk = 1; |
kk = 1; |
823 |
printf("\n\tUsed: ATAPI for CD-ROMs, SFF-8020i, r2.5"); |
printf("\n\tUsed: ATAPI for CD-ROMs, SFF-8020i, r2.5"); |
824 |
} |
} |
825 |
if (val[CDR_MAJOR] && (val[CDR_MAJOR] !=NOVAL_1)) |
if (val[CDR_MAJOR] && (val[CDR_MAJOR] !=NOVAL_1)) { |
|
{ |
|
826 |
kk = 1; |
kk = 1; |
827 |
printf("\n\tSupported: CD-ROM ATAPI"); |
printf("\n\tSupported: CD-ROM ATAPI"); |
828 |
jj = val[CDR_MAJOR] >> 1; |
jj = val[CDR_MAJOR] >> 1; |
829 |
for (ii = 1; ii <15; ii++) |
for (ii = 1; ii < 15; ii++) { |
|
{ |
|
830 |
if (jj & 0x0001) printf("-%u ", ii); |
if (jj & 0x0001) printf("-%u ", ii); |
831 |
jj >>= 1; |
jj >>= 1; |
832 |
} |
} |
833 |
} |
} |
834 |
printf("%s\n", (!kk) ? "\n\tLikely used CD-ROM ATAPI-1" : "" ); |
puts(kk ? "" : "\n\tLikely used CD-ROM ATAPI-1"); |
835 |
/* the cdrom stuff is more like ATA-2 than anything else, so: */ |
/* the cdrom stuff is more like ATA-2 than anything else, so: */ |
836 |
like_std = 2; |
like_std = 2; |
837 |
} |
} |
841 |
|
|
842 |
printf("Configuration:\n"); |
printf("Configuration:\n"); |
843 |
/* more info from the general configuration word */ |
/* more info from the general configuration word */ |
844 |
if ((eqpt != CDROM) && (like_std == 1)) |
if ((eqpt != CDROM) && (like_std == 1)) { |
|
{ |
|
845 |
jj = val[GEN_CONFIG] >> 1; |
jj = val[GEN_CONFIG] >> 1; |
846 |
for (ii = 1; ii < 15; ii++) |
for (ii = 1; ii < 15; ii++) { |
847 |
{ |
if (jj & 0x0001) |
848 |
if (jj & 0x0001) printf("\t%s\n",ata1_cfg_str[ii]); |
printf("\t%s\n", nth_string(ata1_cfg_str, ii)); |
849 |
jj >>=1; |
jj >>=1; |
850 |
} |
} |
851 |
} |
} |
852 |
if (dev == ATAPI_DEV) |
if (dev == ATAPI_DEV) { |
|
{ |
|
853 |
if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_3MS_VAL) |
if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_3MS_VAL) |
854 |
strng = "3ms"; |
strng = "3ms"; |
855 |
else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_INTR_VAL) |
else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_INTR_VAL) |
857 |
else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_50US_VAL) |
else if ((val[GEN_CONFIG] & DRQ_RESPONSE_TIME) == DRQ_50US_VAL) |
858 |
strng ="50us"; |
strng ="50us"; |
859 |
else |
else |
860 |
strng = "Unknown"; |
strng = "unknown"; |
861 |
printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */ |
printf("\tDRQ response: %s\n\tPacket size: ", strng); /* Data Request (DRQ) */ |
862 |
|
|
863 |
if ((val[GEN_CONFIG] & PKT_SIZE_SUPPORTED) == PKT_SIZE_12_VAL) |
if ((val[GEN_CONFIG] & PKT_SIZE_SUPPORTED) == PKT_SIZE_12_VAL) |
865 |
else if ((val[GEN_CONFIG] & PKT_SIZE_SUPPORTED) == PKT_SIZE_16_VAL) |
else if ((val[GEN_CONFIG] & PKT_SIZE_SUPPORTED) == PKT_SIZE_16_VAL) |
866 |
strng = "16 bytes"; |
strng = "16 bytes"; |
867 |
else |
else |
868 |
strng = "Unknown"; |
strng = "unknown"; |
869 |
puts(strng); |
puts(strng); |
870 |
} |
} else { |
|
else |
|
|
{ |
|
871 |
/* addressing...CHS? See section 6.2 of ATA specs 4 or 5 */ |
/* addressing...CHS? See section 6.2 of ATA specs 4 or 5 */ |
872 |
ll = (uint32_t)val[LBA_SECTS_MSB] << 16 | val[LBA_SECTS_LSB]; |
ll = (uint32_t)val[LBA_SECTS_MSB] << 16 | val[LBA_SECTS_LSB]; |
873 |
mm = 0; bbbig = 0; |
mm = 0; bbbig = 0; |
874 |
if ( (ll > 0x00FBFC10) && (!val[LCYLS])) |
if ((ll > 0x00FBFC10) && (!val[LCYLS])) |
875 |
printf("\tCHS addressing not supported\n"); |
printf("\tCHS addressing not supported\n"); |
876 |
else |
else { |
|
{ |
|
877 |
jj = val[WHATS_VALID] & OK_W54_58; |
jj = val[WHATS_VALID] & OK_W54_58; |
878 |
printf("\tLogical\t\tmax\tcurrent\n\tcylinders\t%u\t%u\n\theads\t\t%u\t%u\n\tsectors/track\t%u\t%u\n\t--\n", |
printf("\tLogical\t\tmax\tcurrent\n\tcylinders\t%u\t%u\n\theads\t\t%u\t%u\n\tsectors/track\t%u\t%u\n\t--\n", |
879 |
val[LCYLS],jj?val[LCYLS_CUR]:0, val[LHEADS],jj?val[LHEADS_CUR]:0, val[LSECTS],jj?val[LSECTS_CUR]:0); |
val[LCYLS],jj?val[LCYLS_CUR]:0, val[LHEADS],jj?val[LHEADS_CUR]:0, val[LSECTS],jj?val[LSECTS_CUR]:0); |
880 |
|
|
881 |
if ((min_std == 1) && (val[TRACK_BYTES] || val[SECT_BYTES])) |
if ((min_std == 1) && (val[TRACK_BYTES] || val[SECT_BYTES])) |
882 |
printf("\tbytes/track: %u\tbytes/sector: %u\n",val[TRACK_BYTES], val[SECT_BYTES]); |
printf("\tbytes/track: %u\tbytes/sector: %u\n", val[TRACK_BYTES], val[SECT_BYTES]); |
883 |
|
|
884 |
if (jj) |
if (jj) { |
|
{ |
|
885 |
mm = (uint32_t)val[CAPACITY_MSB] << 16 | val[CAPACITY_LSB]; |
mm = (uint32_t)val[CAPACITY_MSB] << 16 | val[CAPACITY_LSB]; |
886 |
if (like_std < 3) |
if (like_std < 3) { |
887 |
{ |
/* check Endian of capacity bytes */ |
|
/* check Endian of capacity bytes */ |
|
888 |
nn = val[LCYLS_CUR] * val[LHEADS_CUR] * val[LSECTS_CUR]; |
nn = val[LCYLS_CUR] * val[LHEADS_CUR] * val[LSECTS_CUR]; |
889 |
oo = (uint32_t)val[CAPACITY_LSB] << 16 | val[CAPACITY_MSB]; |
oo = (uint32_t)val[CAPACITY_LSB] << 16 | val[CAPACITY_MSB]; |
890 |
if (abs(mm - nn) > abs(oo - nn)) |
if (abs(mm - nn) > abs(oo - nn)) |
891 |
mm = oo; |
mm = oo; |
892 |
} |
} |
893 |
printf("\tCHS current addressable sectors:%11u\n",mm); |
printf("\tCHS current addressable sectors:%11u\n", mm); |
894 |
} |
} |
895 |
} |
} |
896 |
/* LBA addressing */ |
/* LBA addressing */ |
897 |
printf("\tLBA user addressable sectors:%11u\n",ll); |
printf("\tLBA user addressable sectors:%11u\n", ll); |
898 |
if ( ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) && |
if (((val[CMDS_SUPP_1] & VALID) == VALID_VAL) |
899 |
(val[CMDS_SUPP_1] & SUPPORT_48_BIT) ) |
&& (val[CMDS_SUPP_1] & SUPPORT_48_BIT) |
900 |
{ |
) { |
901 |
bbbig = (uint64_t)val[LBA_64_MSB] << 48 | |
bbbig = (uint64_t)val[LBA_64_MSB] << 48 | |
902 |
(uint64_t)val[LBA_48_MSB] << 32 | |
(uint64_t)val[LBA_48_MSB] << 32 | |
903 |
(uint64_t)val[LBA_MID] << 16 | |
(uint64_t)val[LBA_MID] << 16 | |
904 |
val[LBA_LSB] ; |
val[LBA_LSB]; |
905 |
printf("\tLBA48 user addressable sectors:%11"PRIu64"\n",bbbig); |
printf("\tLBA48 user addressable sectors:%11"PRIu64"\n", bbbig); |
906 |
} |
} |
907 |
|
|
908 |
if (!bbbig) |
if (!bbbig) |
909 |
bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */ |
bbbig = (uint64_t)(ll>mm ? ll : mm); /* # 512 byte blocks */ |
910 |
printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n",bbbig>>11); |
printf("\tdevice size with M = 1024*1024: %11"PRIu64" MBytes\n", bbbig>>11); |
911 |
bbbig = (bbbig<<9)/1000000; |
bbbig = (bbbig << 9) / 1000000; |
912 |
printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ",bbbig); |
printf("\tdevice size with M = 1000*1000: %11"PRIu64" MBytes ", bbbig); |
913 |
|
|
914 |
if (bbbig > 1000) |
if (bbbig > 1000) |
915 |
printf("(%"PRIu64" GB)\n", bbbig/1000); |
printf("(%"PRIu64" GB)\n", bbbig/1000); |
916 |
else |
else |
917 |
puts(""); |
bb_putchar('\n'); |
918 |
} |
} |
919 |
|
|
920 |
/* hw support of commands (capabilities) */ |
/* hw support of commands (capabilities) */ |
921 |
printf("Capabilities:\n\t"); |
printf("Capabilities:\n\t"); |
922 |
|
|
923 |
if (dev == ATAPI_DEV) |
if (dev == ATAPI_DEV) { |
|
{ |
|
924 |
if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP)) printf("Cmd queuing, "); |
if (eqpt != CDROM && (val[CAPAB_0] & CMD_Q_SUP)) printf("Cmd queuing, "); |
925 |
if (val[CAPAB_0] & OVLP_SUP) printf("Cmd overlap, "); |
if (val[CAPAB_0] & OVLP_SUP) printf("Cmd overlap, "); |
926 |
} |
} |
927 |
if (val[CAPAB_0] & LBA_SUP) printf("LBA, "); |
if (val[CAPAB_0] & LBA_SUP) printf("LBA, "); |
928 |
|
|
929 |
if (like_std != 1) |
if (like_std != 1) { |
|
{ |
|
930 |
printf("IORDY%s(can%s be disabled)\n", |
printf("IORDY%s(can%s be disabled)\n", |
931 |
!(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "", |
!(val[CAPAB_0] & IORDY_SUP) ? "(may be)" : "", |
932 |
(val[CAPAB_0] & IORDY_OFF) ? "" :"not"); |
(val[CAPAB_0] & IORDY_OFF) ? "" :"not"); |
933 |
} |
} else |
|
else |
|
934 |
printf("no IORDY\n"); |
printf("no IORDY\n"); |
935 |
|
|
936 |
if ((like_std == 1) && val[BUF_TYPE]) |
if ((like_std == 1) && val[BUF_TYPE]) { |
|
{ |
|
937 |
printf("\tBuffer type: %04x: %s%s\n", val[BUF_TYPE], |
printf("\tBuffer type: %04x: %s%s\n", val[BUF_TYPE], |
938 |
(val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector", |
(val[BUF_TYPE] < 2) ? "single port, single-sector" : "dual port, multi-sector", |
939 |
(val[BUF_TYPE] > 2) ? " with read caching ability" : ""); |
(val[BUF_TYPE] > 2) ? " with read caching ability" : ""); |
940 |
} |
} |
941 |
|
|
942 |
if ((min_std == 1) && (val[BUFFER__SIZE] && (val[BUFFER__SIZE] != NOVAL_1))) |
if ((min_std == 1) && (val[BUFFER__SIZE] && (val[BUFFER__SIZE] != NOVAL_1))) { |
943 |
{ |
printf("\tBuffer size: %.1fkB\n", (float)val[BUFFER__SIZE]/2); |
|
printf("\tBuffer size: %.1fkB\n",(float)val[BUFFER__SIZE]/2); |
|
944 |
} |
} |
945 |
if ((min_std < 4) && (val[RW_LONG])) |
if ((min_std < 4) && (val[RW_LONG])) { |
946 |
{ |
printf("\tbytes avail on r/w long: %u\n", val[RW_LONG]); |
|
printf("\tbytes avail on r/w long: %u\n",val[RW_LONG]); |
|
947 |
} |
} |
948 |
if ((eqpt != CDROM) && (like_std > 3)) |
if ((eqpt != CDROM) && (like_std > 3)) { |
949 |
{ |
printf("\tQueue depth: %u\n", (val[QUEUE_DEPTH] & DEPTH_BITS) + 1); |
|
printf("\tQueue depth: %u\n",(val[QUEUE_DEPTH] & DEPTH_BITS)+1); |
|
950 |
} |
} |
951 |
|
|
952 |
if (dev == ATA_DEV) |
if (dev == ATA_DEV) { |
|
{ |
|
953 |
if (like_std == 1) |
if (like_std == 1) |
954 |
printf("\tCan%s perform double-word IO\n",(!val[DWORD_IO]) ?"not":""); |
printf("\tCan%s perform double-word IO\n", (!val[DWORD_IO]) ? "not" : ""); |
955 |
else |
else { |
|
{ |
|
956 |
printf("\tStandby timer values: spec'd by %s", (val[CAPAB_0] & STD_STBY) ? "Standard" : "Vendor"); |
printf("\tStandby timer values: spec'd by %s", (val[CAPAB_0] & STD_STBY) ? "Standard" : "Vendor"); |
957 |
if ((like_std > 3) && ((val[CAPAB_1] & VALID) == VALID_VAL)) |
if ((like_std > 3) && ((val[CAPAB_1] & VALID) == VALID_VAL)) |
958 |
printf(", %s device specific minimum\n",(val[CAPAB_1] & MIN_STANDBY_TIMER)?"with":"no"); |
printf(", %s device specific minimum\n", (val[CAPAB_1] & MIN_STANDBY_TIMER) ? "with" : "no"); |
959 |
else |
else |
960 |
puts(""); |
bb_putchar('\n'); |
961 |
} |
} |
962 |
printf("\tR/W multiple sector transfer: "); |
printf("\tR/W multiple sector transfer: "); |
963 |
if ((like_std < 3) && !(val[SECTOR_XFER_MAX] & SECTOR_XFER)) |
if ((like_std < 3) && !(val[SECTOR_XFER_MAX] & SECTOR_XFER)) |
964 |
printf("not supported\n"); |
printf("not supported\n"); |
965 |
else |
else { |
966 |
{ |
printf("Max = %u\tCurrent = ", val[SECTOR_XFER_MAX] & SECTOR_XFER); |
|
printf("Max = %u\tCurrent = ",val[SECTOR_XFER_MAX] & SECTOR_XFER); |
|
967 |
if (val[SECTOR_XFER_CUR] & MULTIPLE_SETTING_VALID) |
if (val[SECTOR_XFER_CUR] & MULTIPLE_SETTING_VALID) |
968 |
printf("%u\n", val[SECTOR_XFER_CUR] & SECTOR_XFER); |
printf("%u\n", val[SECTOR_XFER_CUR] & SECTOR_XFER); |
969 |
else |
else |
970 |
printf("?\n"); |
printf("?\n"); |
971 |
} |
} |
972 |
if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008)) |
if ((like_std > 3) && (val[CMDS_SUPP_1] & 0x0008)) { |
|
{ |
|
973 |
/* We print out elsewhere whether the APM feature is enabled or |
/* We print out elsewhere whether the APM feature is enabled or |
974 |
not. If it's not enabled, let's not repeat the info; just print |
not. If it's not enabled, let's not repeat the info; just print |
975 |
nothing here. */ |
nothing here. */ |
976 |
printf("\tAdvancedPM level: "); |
printf("\tAdvancedPM level: "); |
977 |
if ( (val[ADV_PWR] & 0xFF00) == 0x4000 ) |
if ((val[ADV_PWR] & 0xFF00) == 0x4000) { |
|
{ |
|
978 |
uint8_t apm_level = val[ADV_PWR] & 0x00FF; |
uint8_t apm_level = val[ADV_PWR] & 0x00FF; |
979 |
printf("%u (0x%x)\n", apm_level, apm_level); |
printf("%u (0x%x)\n", apm_level, apm_level); |
980 |
} |
} |
983 |
} |
} |
984 |
if (like_std > 5 && val[ACOUSTIC]) { |
if (like_std > 5 && val[ACOUSTIC]) { |
985 |
printf("\tRecommended acoustic management value: %u, current value: %u\n", |
printf("\tRecommended acoustic management value: %u, current value: %u\n", |
986 |
(val[ACOUSTIC] >> 8) & 0x00ff, val[ACOUSTIC] & 0x00ff); |
(val[ACOUSTIC] >> 8) & 0x00ff, val[ACOUSTIC] & 0x00ff); |
987 |
} |
} |
988 |
} |
} else { |
|
else |
|
|
{ |
|
989 |
/* ATAPI */ |
/* ATAPI */ |
990 |
if (eqpt != CDROM && (val[CAPAB_0] & SWRST_REQ)) |
if (eqpt != CDROM && (val[CAPAB_0] & SWRST_REQ)) |
991 |
printf("\tATA sw reset required\n"); |
printf("\tATA sw reset required\n"); |
992 |
|
|
993 |
if (val[PKT_REL] || val[SVC_NBSY]) |
if (val[PKT_REL] || val[SVC_NBSY]) { |
|
{ |
|
994 |
printf("\tOverlap support:"); |
printf("\tOverlap support:"); |
995 |
if (val[PKT_REL]) printf(" %uus to release bus.",val[PKT_REL]); |
if (val[PKT_REL]) printf(" %uus to release bus.", val[PKT_REL]); |
996 |
if (val[SVC_NBSY]) printf(" %uus to clear BSY after SERVICE cmd.",val[SVC_NBSY]); |
if (val[SVC_NBSY]) printf(" %uus to clear BSY after SERVICE cmd.", val[SVC_NBSY]); |
997 |
puts(""); |
bb_putchar('\n'); |
998 |
} |
} |
999 |
} |
} |
1000 |
|
|
1002 |
printf("\tDMA: "); |
printf("\tDMA: "); |
1003 |
if (!(val[CAPAB_0] & DMA_SUP)) |
if (!(val[CAPAB_0] & DMA_SUP)) |
1004 |
printf("not supported\n"); |
printf("not supported\n"); |
1005 |
else |
else { |
|
{ |
|
1006 |
if (val[DMA_MODE] && !val[SINGLE_DMA] && !val[MULTI_DMA]) |
if (val[DMA_MODE] && !val[SINGLE_DMA] && !val[MULTI_DMA]) |
1007 |
printf(" sdma%u\n",(val[DMA_MODE] & MODE) >> 8); |
printf(" sdma%u\n", (val[DMA_MODE] & MODE) >> 8); |
1008 |
if (val[SINGLE_DMA]) |
if (val[SINGLE_DMA]) { |
|
{ |
|
1009 |
jj = val[SINGLE_DMA]; |
jj = val[SINGLE_DMA]; |
1010 |
kk = val[SINGLE_DMA] >> 8; |
kk = val[SINGLE_DMA] >> 8; |
1011 |
err_dma += mode_loop(jj,kk,'s',&have_mode); |
err_dma += mode_loop(jj, kk, 's', &have_mode); |
1012 |
} |
} |
1013 |
if (val[MULTI_DMA]) |
if (val[MULTI_DMA]) { |
|
{ |
|
1014 |
jj = val[MULTI_DMA]; |
jj = val[MULTI_DMA]; |
1015 |
kk = val[MULTI_DMA] >> 8; |
kk = val[MULTI_DMA] >> 8; |
1016 |
err_dma += mode_loop(jj,kk,'m',&have_mode); |
err_dma += mode_loop(jj, kk, 'm', &have_mode); |
1017 |
} |
} |
1018 |
if ((val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) |
if ((val[WHATS_VALID] & OK_W88) && val[ULTRA_DMA]) { |
|
{ |
|
1019 |
jj = val[ULTRA_DMA]; |
jj = val[ULTRA_DMA]; |
1020 |
kk = val[ULTRA_DMA] >> 8; |
kk = val[ULTRA_DMA] >> 8; |
1021 |
err_dma += mode_loop(jj,kk,'u',&have_mode); |
err_dma += mode_loop(jj, kk, 'u', &have_mode); |
1022 |
} |
} |
1023 |
if (err_dma || !have_mode) printf("(?)"); |
if (err_dma || !have_mode) printf("(?)"); |
1024 |
puts(""); |
bb_putchar('\n'); |
1025 |
|
|
1026 |
if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP)) |
if ((dev == ATAPI_DEV) && (eqpt != CDROM) && (val[CAPAB_0] & DMA_IL_SUP)) |
1027 |
printf("\t\tInterleaved DMA support\n"); |
printf("\t\tInterleaved DMA support\n"); |
1028 |
|
|
1029 |
if ((val[WHATS_VALID] & OK_W64_70) && |
if ((val[WHATS_VALID] & OK_W64_70) |
1030 |
(val[DMA_TIME_MIN] || val[DMA_TIME_NORM])) |
&& (val[DMA_TIME_MIN] || val[DMA_TIME_NORM]) |
1031 |
{ |
) { |
1032 |
printf("\t\tCycle time:"); |
printf("\t\tCycle time:"); |
1033 |
if (val[DMA_TIME_MIN]) printf(" min=%uns",val[DMA_TIME_MIN]); |
if (val[DMA_TIME_MIN]) printf(" min=%uns", val[DMA_TIME_MIN]); |
1034 |
if (val[DMA_TIME_NORM]) printf(" recommended=%uns",val[DMA_TIME_NORM]); |
if (val[DMA_TIME_NORM]) printf(" recommended=%uns", val[DMA_TIME_NORM]); |
1035 |
puts(""); |
bb_putchar('\n'); |
1036 |
} |
} |
1037 |
} |
} |
1038 |
|
|
1040 |
printf("\tPIO: "); |
printf("\tPIO: "); |
1041 |
/* If a drive supports mode n (e.g. 3), it also supports all modes less |
/* If a drive supports mode n (e.g. 3), it also supports all modes less |
1042 |
* than n (e.g. 3, 2, 1 and 0). Print all the modes. */ |
* than n (e.g. 3, 2, 1 and 0). Print all the modes. */ |
1043 |
if ((val[WHATS_VALID] & OK_W64_70) && (val[ADV_PIO_MODES] & PIO_SUP)) |
if ((val[WHATS_VALID] & OK_W64_70) && (val[ADV_PIO_MODES] & PIO_SUP)) { |
|
{ |
|
1044 |
jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007; |
jj = ((val[ADV_PIO_MODES] & PIO_SUP) << 3) | 0x0007; |
1045 |
for (ii = 0; ii <= PIO_MODE_MAX ; ii++) |
for (ii = 0; ii <= PIO_MODE_MAX; ii++) { |
1046 |
{ |
if (jj & 0x0001) printf("pio%d ", ii); |
|
if (jj & 0x0001) printf("pio%d ",ii); |
|
1047 |
jj >>=1; |
jj >>=1; |
1048 |
} |
} |
1049 |
puts(""); |
bb_putchar('\n'); |
1050 |
} |
} else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE)) { |
|
else if (((min_std < 5) || (eqpt == CDROM)) && (val[PIO_MODE] & MODE) ) |
|
|
{ |
|
1051 |
for (ii = 0; ii <= val[PIO_MODE]>>8; ii++) |
for (ii = 0; ii <= val[PIO_MODE]>>8; ii++) |
1052 |
printf("pio%d ",ii); |
printf("pio%d ", ii); |
1053 |
puts(""); |
bb_putchar('\n'); |
1054 |
} |
} else |
1055 |
else |
puts("unknown"); |
|
printf("unknown\n"); |
|
1056 |
|
|
1057 |
if (val[WHATS_VALID] & OK_W64_70) |
if (val[WHATS_VALID] & OK_W64_70) { |
1058 |
{ |
if (val[PIO_NO_FLOW] || val[PIO_FLOW]) { |
|
if (val[PIO_NO_FLOW] || val[PIO_FLOW]) |
|
|
{ |
|
1059 |
printf("\t\tCycle time:"); |
printf("\t\tCycle time:"); |
1060 |
if (val[PIO_NO_FLOW]) printf(" no flow control=%uns", val[PIO_NO_FLOW]); |
if (val[PIO_NO_FLOW]) printf(" no flow control=%uns", val[PIO_NO_FLOW]); |
1061 |
if (val[PIO_FLOW]) printf(" IORDY flow control=%uns", val[PIO_FLOW]); |
if (val[PIO_FLOW]) printf(" IORDY flow control=%uns", val[PIO_FLOW]); |
1062 |
puts(""); |
bb_putchar('\n'); |
1063 |
} |
} |
1064 |
} |
} |
1065 |
|
|
1066 |
if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) |
if ((val[CMDS_SUPP_1] & VALID) == VALID_VAL) { |
|
{ |
|
1067 |
printf("Commands/features:\n\tEnabled\tSupported:\n"); |
printf("Commands/features:\n\tEnabled\tSupported:\n"); |
1068 |
jj = val[CMDS_SUPP_0]; |
jj = val[CMDS_SUPP_0]; |
1069 |
kk = val[CMDS_EN_0]; |
kk = val[CMDS_EN_0]; |
1070 |
for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++) |
for (ii = 0; ii < NUM_CMD_FEAT_STR; ii++) { |
1071 |
{ |
const char *feat_str = nth_string(cmd_feat_str, ii); |
1072 |
if ((jj & 0x8000) && (*cmd_feat_str[ii] != '\0')) |
if ((jj & 0x8000) && (*feat_str != '\0')) { |
1073 |
{ |
printf("\t%s\t%s\n", (kk & 0x8000) ? " *" : "", feat_str); |
|
printf("\t%s\t%s\n", (kk & 0x8000) ? " *" : "", cmd_feat_str[ii]); |
|
1074 |
} |
} |
1075 |
jj <<=1; kk<<=1; |
jj <<= 1; |
1076 |
if (ii%16 == 15) |
kk <<= 1; |
1077 |
{ |
if (ii % 16 == 15) { |
1078 |
jj = val[CMDS_SUPP_0+1+(ii/16)]; |
jj = val[CMDS_SUPP_0+1+(ii/16)]; |
1079 |
kk = val[CMDS_EN_0+1+(ii/16)]; |
kk = val[CMDS_EN_0+1+(ii/16)]; |
1080 |
} |
} |
1081 |
if (ii == 31) |
if (ii == 31) { |
|
{ |
|
1082 |
if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL) |
if ((val[CMDS_SUPP_2] & VALID) != VALID_VAL) |
1083 |
ii +=16; |
ii +=16; |
1084 |
} |
} |
1086 |
} |
} |
1087 |
/* Removable Media Status Notification feature set */ |
/* Removable Media Status Notification feature set */ |
1088 |
if ((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) |
if ((val[RM_STAT] & RM_STAT_BITS) == RM_STAT_SUP) |
1089 |
printf("\t%s supported\n", cmd_feat_str[27]); |
printf("\t%s supported\n", nth_string(cmd_feat_str, 27)); |
|
|
|
1090 |
|
|
1091 |
/* security */ |
/* security */ |
1092 |
if ((eqpt != CDROM) && (like_std > 3) && |
if ((eqpt != CDROM) && (like_std > 3) |
1093 |
(val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME])) |
&& (val[SECU_STATUS] || val[ERASE_TIME] || val[ENH_ERASE_TIME]) |
1094 |
{ |
) { |
1095 |
printf("Security:\n"); |
printf("Security:\n"); |
1096 |
if (val[PSWD_CODE] && (val[PSWD_CODE] != NOVAL_1)) |
if (val[PSWD_CODE] && (val[PSWD_CODE] != NOVAL_1)) |
1097 |
printf("\tMaster password revision code = %u\n",val[PSWD_CODE]); |
printf("\tMaster password revision code = %u\n", val[PSWD_CODE]); |
1098 |
jj = val[SECU_STATUS]; |
jj = val[SECU_STATUS]; |
1099 |
if (jj) |
if (jj) { |
1100 |
{ |
for (ii = 0; ii < NUM_SECU_STR; ii++) { |
1101 |
for (ii = 0; ii < NUM_SECU_STR; ii++) |
printf("\t%s\t%s\n", (!(jj & 0x0001)) ? "not" : "", nth_string(secu_str, ii)); |
|
{ |
|
|
printf("\t%s\t%s\n", (!(jj & 0x0001)) ? "not" : "", secu_str[ii]); |
|
1102 |
jj >>=1; |
jj >>=1; |
1103 |
} |
} |
1104 |
if (val[SECU_STATUS] & SECU_ENABLED) |
if (val[SECU_STATUS] & SECU_ENABLED) { |
|
{ |
|
1105 |
printf("\tSecurity level %s\n", (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high"); |
printf("\tSecurity level %s\n", (val[SECU_STATUS] & SECU_LEVEL) ? "maximum" : "high"); |
1106 |
} |
} |
1107 |
} |
} |
1108 |
jj = val[ERASE_TIME] & ERASE_BITS; |
jj = val[ERASE_TIME] & ERASE_BITS; |
1109 |
kk = val[ENH_ERASE_TIME] & ERASE_BITS; |
kk = val[ENH_ERASE_TIME] & ERASE_BITS; |
1110 |
if (jj || kk) |
if (jj || kk) { |
1111 |
{ |
bb_putchar('\t'); |
|
printf("\t"); |
|
1112 |
if (jj) printf("%umin for %sSECURITY ERASE UNIT. ", jj==ERASE_BITS ? 508 : jj<<1, ""); |
if (jj) printf("%umin for %sSECURITY ERASE UNIT. ", jj==ERASE_BITS ? 508 : jj<<1, ""); |
1113 |
if (kk) printf("%umin for %sSECURITY ERASE UNIT. ", kk==ERASE_BITS ? 508 : kk<<1, "ENHANCED "); |
if (kk) printf("%umin for %sSECURITY ERASE UNIT. ", kk==ERASE_BITS ? 508 : kk<<1, "ENHANCED "); |
1114 |
puts(""); |
bb_putchar('\n'); |
1115 |
} |
} |
1116 |
} |
} |
1117 |
|
|
1118 |
/* reset result */ |
/* reset result */ |
1119 |
jj = val[HWRST_RSLT]; |
jj = val[HWRST_RSLT]; |
1120 |
if ((jj & VALID) == VALID_VAL) |
if ((jj & VALID) == VALID_VAL) { |
1121 |
{ |
oo = (jj & RST0); |
1122 |
if (!(oo = (jj & RST0))) |
if (!oo) |
1123 |
jj >>= 8; |
jj >>= 8; |
1124 |
if ((jj & DEV_DET) == JUMPER_VAL) |
if ((jj & DEV_DET) == JUMPER_VAL) |
1125 |
strng = " determined by the jumper"; |
strng = " determined by the jumper"; |
1132 |
} |
} |
1133 |
|
|
1134 |
/* more stuff from std 5 */ |
/* more stuff from std 5 */ |
1135 |
if ((like_std > 4) && (eqpt != CDROM)) |
if ((like_std > 4) && (eqpt != CDROM)) { |
1136 |
{ |
if (val[CFA_PWR_MODE] & VALID_W160) { |
|
if (val[CFA_PWR_MODE] & VALID_W160) |
|
|
{ |
|
1137 |
printf("CFA power mode 1:\n\t%s%s\n", (val[CFA_PWR_MODE] & PWR_MODE_OFF) ? "disabled" : "enabled", |
printf("CFA power mode 1:\n\t%s%s\n", (val[CFA_PWR_MODE] & PWR_MODE_OFF) ? "disabled" : "enabled", |
1138 |
(val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : ""); |
(val[CFA_PWR_MODE] & PWR_MODE_REQ) ? " and required by some commands" : ""); |
1139 |
|
|
1140 |
if (val[CFA_PWR_MODE] & MAX_AMPS) printf("\tMaximum current = %uma\n",val[CFA_PWR_MODE] & MAX_AMPS); |
if (val[CFA_PWR_MODE] & MAX_AMPS) |
1141 |
|
printf("\tMaximum current = %uma\n", val[CFA_PWR_MODE] & MAX_AMPS); |
1142 |
} |
} |
1143 |
if ((val[INTEGRITY] & SIG) == SIG_VAL) |
if ((val[INTEGRITY] & SIG) == SIG_VAL) { |
|
{ |
|
1144 |
printf("Checksum: %scorrect\n", chksum ? "in" : ""); |
printf("Checksum: %scorrect\n", chksum ? "in" : ""); |
1145 |
} |
} |
1146 |
} |
} |
1149 |
} |
} |
1150 |
#endif |
#endif |
1151 |
|
|
|
static int get_identity, get_geom; |
|
|
static int do_flush; |
|
|
static int do_ctimings, do_timings; |
|
|
static unsigned long set_readahead, get_readahead, Xreadahead; |
|
|
static unsigned long set_readonly, get_readonly, readonly; |
|
|
static unsigned long set_unmask, get_unmask, unmask; |
|
|
static unsigned long set_mult, get_mult, mult; |
|
|
#ifdef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA |
|
|
static unsigned long set_dma, get_dma, dma; |
|
|
#endif |
|
|
static unsigned long set_dma_q, get_dma_q, dma_q; |
|
|
static unsigned long set_nowerr, get_nowerr, nowerr; |
|
|
static unsigned long set_keep, get_keep, keep; |
|
|
static unsigned long set_io32bit, get_io32bit, io32bit; |
|
|
static unsigned long set_piomode, noisy_piomode; |
|
|
static int piomode; |
|
|
#ifdef HDIO_DRIVE_CMD |
|
|
static unsigned long set_dkeep, get_dkeep, dkeep; |
|
|
static unsigned long set_standby, get_standby, standby_requested; |
|
|
static unsigned long set_xfermode, get_xfermode; |
|
|
static int xfermode_requested; |
|
|
static unsigned long set_lookahead, get_lookahead, lookahead; |
|
|
static unsigned long set_prefetch, get_prefetch, prefetch; |
|
|
static unsigned long set_defects, get_defects, defects; |
|
|
static unsigned long set_wcache, get_wcache, wcache; |
|
|
static unsigned long set_doorlock, get_doorlock, doorlock; |
|
|
static unsigned long set_seagate, get_seagate; |
|
|
static unsigned long set_standbynow, get_standbynow; |
|
|
static unsigned long set_sleepnow, get_sleepnow; |
|
|
static unsigned long get_powermode; |
|
|
static unsigned long set_apmmode, get_apmmode, apmmode; |
|
|
#endif |
|
|
#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY |
|
|
static int get_IDentity; |
|
|
#endif |
|
|
#ifdef CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF |
|
|
static unsigned long unregister_hwif; |
|
|
static unsigned long hwif; |
|
|
#endif |
|
|
#ifdef CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF |
|
|
static unsigned long scan_hwif; |
|
|
static unsigned long hwif_data; |
|
|
static unsigned long hwif_ctrl; |
|
|
static unsigned long hwif_irq; |
|
|
#endif |
|
|
#ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF |
|
|
static unsigned long set_busstate, get_busstate, busstate; |
|
|
#endif |
|
|
static int reread_partn; |
|
|
|
|
|
#ifdef CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET |
|
|
static int perform_reset; |
|
|
#endif /* CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET */ |
|
|
#ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF |
|
|
static unsigned long perform_tristate, tristate; |
|
|
#endif /* CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF */ |
|
|
|
|
1152 |
// Historically, if there was no HDIO_OBSOLETE_IDENTITY, then |
// Historically, if there was no HDIO_OBSOLETE_IDENTITY, then |
1153 |
// then the HDIO_GET_IDENTITY only returned 142 bytes. |
// then the HDIO_GET_IDENTITY only returned 142 bytes. |
1154 |
// Otherwise, HDIO_OBSOLETE_IDENTITY returns 142 bytes, |
// Otherwise, HDIO_OBSOLETE_IDENTITY returns 142 bytes, |
1160 |
// On a really old system, it will not, and we will be confused. |
// On a really old system, it will not, and we will be confused. |
1161 |
// Too bad, really. |
// Too bad, really. |
1162 |
|
|
1163 |
#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY |
#if ENABLE_FEATURE_HDPARM_GET_IDENTITY |
1164 |
static const char * const cfg_str[] = |
static const char cfg_str[] ALIGN1 = |
1165 |
{ "", "HardSect", "SoftSect", "NotMFM", |
"""\0" "HardSect""\0" "SoftSect""\0" "NotMFM""\0" |
1166 |
"HdSw>15uSec", "SpinMotCtl", "Fixed", "Removeable", |
"HdSw>15uSec""\0" "SpinMotCtl""\0" "Fixed""\0" "Removeable""\0" |
1167 |
"DTR<=5Mbs", "DTR>5Mbs", "DTR>10Mbs", "RotSpdTol>.5%", |
"DTR<=5Mbs""\0" "DTR>5Mbs""\0" "DTR>10Mbs""\0" "RotSpdTol>.5%""\0" |
1168 |
"dStbOff", "TrkOff", "FmtGapReq", "nonMagnetic" |
"dStbOff""\0" "TrkOff""\0" "FmtGapReq""\0" "nonMagnetic" |
1169 |
}; |
; |
1170 |
|
|
1171 |
static const char * const BuffType[] = {"Unknown", "1Sect", "DualPort", "DualPortCache"}; |
static const char BuffType[] ALIGN1 = |
1172 |
|
"unknown""\0" "1Sect""\0" "DualPort""\0" "DualPortCache" |
1173 |
|
; |
1174 |
|
|
1175 |
static void dump_identity(const struct hd_driveid *id) |
static void dump_identity(const struct hd_driveid *id) |
1176 |
{ |
{ |
1177 |
int i; |
int i; |
1178 |
const unsigned short int *id_regs= (const void*) id; |
const unsigned short *id_regs = (const void*) id; |
1179 |
|
|
1180 |
printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n Config={", |
printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s\n Config={", |
1181 |
id->model, id->fw_rev, id->serial_no); |
id->model, id->fw_rev, id->serial_no); |
1182 |
for (i=0; i<=15; i++) { |
for (i = 0; i <= 15; i++) { |
1183 |
if (id->config & (1<<i)) |
if (id->config & (1<<i)) |
1184 |
printf(" %s", cfg_str[i]); |
printf(" %s", nth_string(cfg_str, i)); |
1185 |
} |
} |
1186 |
printf( " }\n RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n" |
printf(" }\n RawCHS=%u/%u/%u, TrkSize=%u, SectSize=%u, ECCbytes=%u\n" |
1187 |
" BuffType=(%u) %s, BuffSize=%ukB, MaxMultSect=%u", |
" BuffType=(%u) %s, BuffSize=%ukB, MaxMultSect=%u", |
1188 |
id->cyls, id->heads, id->sectors, id->track_bytes, |
id->cyls, id->heads, id->sectors, id->track_bytes, |
1189 |
id->sector_bytes, id->ecc_bytes, |
id->sector_bytes, id->ecc_bytes, |
1190 |
id->buf_type, BuffType[(id->buf_type > 3) ? 0 : id->buf_type], |
id->buf_type, nth_string(BuffType, (id->buf_type > 3) ? 0 : id->buf_type), |
1191 |
id->buf_size/2, id->max_multsect); |
id->buf_size/2, id->max_multsect); |
1192 |
if (id->max_multsect) |
if (id->max_multsect) { |
|
{ |
|
1193 |
printf(", MultSect="); |
printf(", MultSect="); |
1194 |
if (!(id->multsect_valid&1)) |
if (!(id->multsect_valid & 1)) |
1195 |
printf("?%u?", id->multsect); |
printf("?%u?", id->multsect); |
1196 |
else if (id->multsect) |
else if (id->multsect) |
1197 |
printf("%u", id->multsect); |
printf("%u", id->multsect); |
1198 |
else |
else |
1199 |
printf("off"); |
printf("off"); |
1200 |
} |
} |
1201 |
puts(""); |
bb_putchar('\n'); |
1202 |
|
|
1203 |
if (!(id->field_valid&1)) |
if (!(id->field_valid & 1)) |
1204 |
printf(" (maybe):"); |
printf(" (maybe):"); |
1205 |
|
|
1206 |
printf(" CurCHS=%u/%u/%u, CurSects=%lu, LBA=%s",id->cur_cyls, id->cur_heads, |
printf(" CurCHS=%u/%u/%u, CurSects=%lu, LBA=%s", id->cur_cyls, id->cur_heads, |
1207 |
id->cur_sectors, |
id->cur_sectors, |
1208 |
(BB_BIG_ENDIAN) ? |
(BB_BIG_ENDIAN) ? |
1209 |
(long unsigned int)(id->cur_capacity0 << 16) | id->cur_capacity1 : |
(unsigned long)(id->cur_capacity0 << 16) | id->cur_capacity1 : |
1210 |
(long unsigned int)(id->cur_capacity1 << 16) | id->cur_capacity0, |
(unsigned long)(id->cur_capacity1 << 16) | id->cur_capacity0, |
1211 |
((id->capability&2) == 0) ? "no" : "yes"); |
((id->capability&2) == 0) ? "no" : "yes"); |
1212 |
|
|
1213 |
if (id->capability&2) |
if (id->capability & 2) |
1214 |
printf(", LBAsects=%u", id->lba_capacity); |
printf(", LBAsects=%u", id->lba_capacity); |
1215 |
|
|
1216 |
printf("\n IORDY=%s", (id->capability&8) ? (id->capability&4) ? "on/off" : "yes" : "no"); |
printf("\n IORDY=%s", (id->capability & 8) ? (id->capability & 4) ? "on/off" : "yes" : "no"); |
1217 |
|
|
1218 |
if (((id->capability&8) || (id->field_valid&2)) && id->field_valid&2) |
if (((id->capability & 8) || (id->field_valid & 2)) && (id->field_valid & 2)) |
1219 |
printf(", tPIO={min:%u,w/IORDY:%u}", id->eide_pio, id->eide_pio_iordy); |
printf(", tPIO={min:%u,w/IORDY:%u}", id->eide_pio, id->eide_pio_iordy); |
1220 |
|
|
1221 |
if ((id->capability&1) && (id->field_valid&2)) |
if ((id->capability & 1) && (id->field_valid & 2)) |
1222 |
printf(", tDMA={min:%u,rec:%u}", id->eide_dma_min, id->eide_dma_time); |
printf(", tDMA={min:%u,rec:%u}", id->eide_dma_min, id->eide_dma_time); |
1223 |
|
|
1224 |
printf("\n PIO modes: "); |
printf("\n PIO modes: "); |
1225 |
if (id->tPIO <= 5) |
if (id->tPIO <= 5) { |
|
{ |
|
1226 |
printf("pio0 "); |
printf("pio0 "); |
1227 |
if (id->tPIO >= 1) printf("pio1 "); |
if (id->tPIO >= 1) printf("pio1 "); |
1228 |
if (id->tPIO >= 2) printf("pio2 "); |
if (id->tPIO >= 2) printf("pio2 "); |
1229 |
} |
} |
1230 |
if (id->field_valid&2) |
if (id->field_valid & 2) { |
1231 |
{ |
static const masks_labels_t pio_modes = { |
1232 |
if (id->eide_pio_modes & 1) printf("pio3 "); |
.masks = { 1, 2, ~3 }, |
1233 |
if (id->eide_pio_modes & 2) printf("pio4 "); |
.labels = "pio3 \0""pio4 \0""pio? \0", |
1234 |
if (id->eide_pio_modes &~3) printf("pio? "); |
}; |
1235 |
} |
print_flags(&pio_modes, id->eide_pio_modes); |
1236 |
if (id->capability&1) |
} |
1237 |
{ |
if (id->capability & 1) { |
1238 |
if (id->dma_1word | id->dma_mword) |
if (id->dma_1word | id->dma_mword) { |
1239 |
{ |
static const int dma_wmode_masks[] = { 0x100, 1, 0x200, 2, 0x400, 4, 0xf800, 0xf8 }; |
1240 |
printf("\n DMA modes: "); |
printf("\n DMA modes: "); |
1241 |
if (id->dma_1word & 0x100) printf("*"); |
print_flags_separated(dma_wmode_masks, |
1242 |
if (id->dma_1word & 1) printf("sdma0 "); |
"*\0""sdma0 \0""*\0""sdma1 \0""*\0""sdma2 \0""*\0""sdma? \0", |
1243 |
if (id->dma_1word & 0x200) printf("*"); |
id->dma_1word, NULL); |
1244 |
if (id->dma_1word & 2) printf("sdma1 "); |
print_flags_separated(dma_wmode_masks, |
1245 |
if (id->dma_1word & 0x400) printf("*"); |
"*\0""mdma0\0""*\0""mdma1\0""*\0""mdma2\0""*\0""mdma?\0", |
1246 |
if (id->dma_1word & 4) printf("sdma2 "); |
id->dma_mword, NULL); |
|
if (id->dma_1word & 0xf800) printf("*"); |
|
|
if (id->dma_1word & 0xf8) printf("sdma? "); |
|
|
if (id->dma_mword & 0x100) printf("*"); |
|
|
if (id->dma_mword & 1) printf("mdma0 "); |
|
|
if (id->dma_mword & 0x200) printf("*"); |
|
|
if (id->dma_mword & 2) printf("mdma1 "); |
|
|
if (id->dma_mword & 0x400) printf("*"); |
|
|
if (id->dma_mword & 4) printf("mdma2 "); |
|
|
if (id->dma_mword & 0xf800) printf("*"); |
|
|
if (id->dma_mword & 0xf8) printf("mdma? "); |
|
1247 |
} |
} |
1248 |
} |
} |
1249 |
if (((id->capability&8) || (id->field_valid&2)) && id->field_valid&4) |
if (((id->capability & 8) || (id->field_valid & 2)) && id->field_valid & 4) { |
1250 |
{ |
static const masks_labels_t ultra_modes1 = { |
1251 |
|
.masks = { 0x100, 0x001, 0x200, 0x002, 0x400, 0x004 }, |
1252 |
|
.labels = "*\0""udma0 \0""*\0""udma1 \0""*\0""udma2 \0", |
1253 |
|
}; |
1254 |
|
|
1255 |
printf("\n UDMA modes: "); |
printf("\n UDMA modes: "); |
1256 |
if (id->dma_ultra & 0x100) printf("*"); |
print_flags(&ultra_modes1, id->dma_ultra); |
|
if (id->dma_ultra & 0x001) printf("udma0 "); |
|
|
if (id->dma_ultra & 0x200) printf("*"); |
|
|
if (id->dma_ultra & 0x002) printf("udma1 "); |
|
|
if (id->dma_ultra & 0x400) printf("*"); |
|
|
if (id->dma_ultra & 0x004) printf("udma2 "); |
|
1257 |
#ifdef __NEW_HD_DRIVE_ID |
#ifdef __NEW_HD_DRIVE_ID |
1258 |
if (id->hw_config & 0x2000) |
if (id->hw_config & 0x2000) { |
|
{ |
|
1259 |
#else /* !__NEW_HD_DRIVE_ID */ |
#else /* !__NEW_HD_DRIVE_ID */ |
1260 |
if (id->word93 & 0x2000) |
if (id->word93 & 0x2000) { |
|
{ |
|
1261 |
#endif /* __NEW_HD_DRIVE_ID */ |
#endif /* __NEW_HD_DRIVE_ID */ |
1262 |
if (id->dma_ultra & 0x0800) printf("*"); |
static const masks_labels_t ultra_modes2 = { |
1263 |
if (id->dma_ultra & 0x0008) printf("udma3 "); |
.masks = { 0x0800, 0x0008, 0x1000, 0x0010, |
1264 |
if (id->dma_ultra & 0x1000) printf("*"); |
0x2000, 0x0020, 0x4000, 0x0040, |
1265 |
if (id->dma_ultra & 0x0010) printf("udma4 "); |
0x8000, 0x0080 }, |
1266 |
if (id->dma_ultra & 0x2000) printf("*"); |
.labels = "*\0""udma3 \0""*\0""udma4 \0" |
1267 |
if (id->dma_ultra & 0x0020) printf("udma5 "); |
"*\0""udma5 \0""*\0""udma6 \0" |
1268 |
if (id->dma_ultra & 0x4000) printf("*"); |
"*\0""udma7 \0" |
1269 |
if (id->dma_ultra & 0x0040) printf("udma6 "); |
}; |
1270 |
if (id->dma_ultra & 0x8000) printf("*"); |
print_flags(&ultra_modes2, id->dma_ultra); |
1271 |
if (id->dma_ultra & 0x0080) printf("udma7 "); |
} |
1272 |
} |
} |
1273 |
} |
printf("\n AdvancedPM=%s", (!(id_regs[83] & 8)) ? "no" : "yes"); |
1274 |
printf("\n AdvancedPM=%s",((id_regs[83]&8)==0)?"no":"yes"); |
if (id_regs[83] & 8) { |
1275 |
if (id_regs[83] & 8) |
if (!(id_regs[86] & 8)) |
|
{ |
|
|
if (!(id_regs[86]&8)) |
|
1276 |
printf(": disabled (255)"); |
printf(": disabled (255)"); |
1277 |
else if ((id_regs[91]&0xFF00)!=0x4000) |
else if ((id_regs[91] & 0xFF00) != 0x4000) |
1278 |
printf(": unknown setting"); |
printf(": unknown setting"); |
1279 |
else |
else |
1280 |
printf(": mode=0x%02X (%u)",id_regs[91]&0xFF,id_regs[91]&0xFF); |
printf(": mode=0x%02X (%u)", id_regs[91] & 0xFF, id_regs[91] & 0xFF); |
1281 |
} |
} |
1282 |
if (id_regs[82]&0x20) |
if (id_regs[82] & 0x20) |
1283 |
printf(" WriteCache=%s",(id_regs[85]&0x20) ? "enabled" : "disabled"); |
printf(" WriteCache=%s", (id_regs[85] & 0x20) ? "enabled" : "disabled"); |
1284 |
#ifdef __NEW_HD_DRIVE_ID |
#ifdef __NEW_HD_DRIVE_ID |
1285 |
if ((id->minor_rev_num && id->minor_rev_num <= 31) || (id->major_rev_num && id->minor_rev_num <= 31)) |
if ((id->minor_rev_num && id->minor_rev_num <= 31) |
1286 |
{ |
|| (id->major_rev_num && id->minor_rev_num <= 31) |
1287 |
printf("\n Drive conforms to: %s: ", (id->minor_rev_num <= 31) ? minor_str[id->minor_rev_num] : "Unknown"); |
) { |
1288 |
|
printf("\n Drive conforms to: %s: ", (id->minor_rev_num <= 31) ? nth_string(minor_str, id->minor_rev_num) : "unknown"); |
1289 |
if (id->major_rev_num != 0x0000 && /* NOVAL_0 */ |
if (id->major_rev_num != 0x0000 && /* NOVAL_0 */ |
1290 |
id->major_rev_num != 0xFFFF) { /* NOVAL_1 */ |
id->major_rev_num != 0xFFFF) { /* NOVAL_1 */ |
1291 |
for (i=0; i <= 15; i++) { |
for (i = 0; i <= 15; i++) { |
1292 |
if (id->major_rev_num & (1<<i)) |
if (id->major_rev_num & (1<<i)) |
1293 |
printf(" ATA/ATAPI-%u", i); |
printf(" ATA/ATAPI-%u", i); |
1294 |
} |
} |
1299 |
} |
} |
1300 |
#endif |
#endif |
1301 |
|
|
1302 |
static void flush_buffer_cache(int fd) |
static void flush_buffer_cache(/*int fd*/ void) |
1303 |
{ |
{ |
1304 |
fsync(fd); /* flush buffers */ |
fsync(fd); /* flush buffers */ |
1305 |
bb_ioctl(fd, BLKFLSBUF, NULL,"BLKFLSBUF" ) ;/* do it again, big time */ |
ioctl_or_warn(fd, BLKFLSBUF, NULL); /* do it again, big time */ |
1306 |
#ifdef HDIO_DRIVE_CMD |
#ifdef HDIO_DRIVE_CMD |
1307 |
sleep(1); |
sleep(1); |
1308 |
if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) /* await completion */ |
if (ioctl(fd, HDIO_DRIVE_CMD, NULL) && errno != EINVAL) { /* await completion */ |
1309 |
bb_perror_msg("HDIO_DRIVE_CMD"); |
if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */ |
1310 |
|
bb_perror_msg("HDIO_DRIVE_CMD"); |
1311 |
|
else |
1312 |
|
bb_perror_msg("ioctl %#x failed", HDIO_DRIVE_CMD); |
1313 |
|
} |
1314 |
#endif |
#endif |
1315 |
} |
} |
1316 |
|
|
1317 |
static int seek_to_zero(int fd) |
static void seek_to_zero(/*int fd*/ void) |
1318 |
{ |
{ |
1319 |
if (lseek(fd, (off_t) 0, SEEK_SET)) |
xlseek(fd, (off_t) 0, SEEK_SET); |
|
return 1; |
|
|
return 0; |
|
1320 |
} |
} |
1321 |
|
|
1322 |
static int read_big_block(int fd, char *buf) |
static void read_big_block(/*int fd,*/ char *buf) |
1323 |
{ |
{ |
1324 |
int i; |
int i; |
1325 |
|
|
1326 |
if ((i = read(fd, buf, TIMING_BUF_BYTES)) != TIMING_BUF_BYTES) { |
xread(fd, buf, TIMING_BUF_BYTES); |
|
bb_error_msg("read(%d bytes) failed (rc=%d)", TIMING_BUF_BYTES, i); |
|
|
return 1; |
|
|
} |
|
1327 |
/* access all sectors of buf to ensure the read fully completed */ |
/* access all sectors of buf to ensure the read fully completed */ |
1328 |
for (i = 0; i < TIMING_BUF_BYTES; i += 512) |
for (i = 0; i < TIMING_BUF_BYTES; i += 512) |
1329 |
buf[i] &= 1; |
buf[i] &= 1; |
|
return 0; |
|
|
} |
|
|
|
|
|
static void print_timing(int t, double e) |
|
|
{ |
|
|
if (t >= e) /* more than 1MB/s */ |
|
|
printf("%2d MB in %5.2f seconds =%6.2f %cB/sec\n", t, e, t / e, 'M'); |
|
|
else |
|
|
printf("%2d MB in %5.2f seconds =%6.2f %cB/sec\n", t, e, t / e * 1024, 'k'); |
|
1330 |
} |
} |
1331 |
|
|
1332 |
static int do_blkgetsize (int fd, unsigned long long *blksize64) |
static unsigned dev_size_mb(/*int fd*/ void) |
1333 |
{ |
{ |
1334 |
int rc; |
union { |
1335 |
unsigned int blksize32 = 0; |
unsigned long long blksize64; |
1336 |
|
unsigned blksize32; |
1337 |
|
} u; |
1338 |
|
|
1339 |
if (0 == ioctl(fd, BLKGETSIZE64, blksize64)) { // returns bytes |
if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // bytes |
1340 |
*blksize64 /= 512; |
u.blksize64 /= (1024 * 1024); |
1341 |
return 0; |
} else { |
1342 |
|
xioctl(fd, BLKGETSIZE, &u.blksize32); // sectors |
1343 |
|
u.blksize64 = u.blksize32 / (2 * 1024); |
1344 |
} |
} |
1345 |
rc = ioctl(fd, BLKGETSIZE, &blksize32); // returns sectors |
if (u.blksize64 > UINT_MAX) |
1346 |
if (rc) |
return UINT_MAX; |
1347 |
bb_perror_msg("BLKGETSIZE"); |
return u.blksize64; |
|
*blksize64 = blksize32; |
|
|
return rc; |
|
1348 |
} |
} |
1349 |
|
|
1350 |
static void do_time(int flag, int fd) |
static void print_timing(unsigned m, unsigned elapsed_us) |
|
/* |
|
|
flag = 0 time_cache |
|
|
flag = 1 time_device |
|
|
*/ |
|
1351 |
{ |
{ |
1352 |
struct itimerval e1, e2; |
unsigned sec = elapsed_us / 1000000; |
1353 |
double elapsed, elapsed2; |
unsigned hs = (elapsed_us % 1000000) / 10000; |
|
unsigned int max_iterations = 1024, total_MB, iterations; |
|
|
unsigned long long blksize; |
|
|
RESERVE_CONFIG_BUFFER(buf, TIMING_BUF_BYTES); |
|
|
|
|
|
if (mlock(buf, TIMING_BUF_BYTES)) { |
|
|
bb_perror_msg("mlock"); |
|
|
goto quit2; |
|
|
} |
|
1354 |
|
|
1355 |
if (0 == do_blkgetsize(fd, &blksize)) { |
printf("%5u MB in %u.%02u seconds = %u kB/s\n", |
1356 |
max_iterations = blksize / (2 * 1024) / TIMING_BUF_MB; |
m, sec, hs, |
1357 |
} |
/* "| 1" prevents div-by-0 */ |
1358 |
|
(unsigned) ((unsigned long long)m * (1024 * 1000000) / (elapsed_us | 1)) |
1359 |
|
// ~= (m * 1024) / (elapsed_us / 1000000) |
1360 |
|
// = kb / elapsed_sec |
1361 |
|
); |
1362 |
|
} |
1363 |
|
|
1364 |
/* Clear out the device request queues & give them time to complete */ |
static void do_time(int cache /*,int fd*/) |
1365 |
|
/* cache=1: time cache: repeatedly read N MB at offset 0 |
1366 |
|
* cache=0: time device: linear read, starting at offset 0 |
1367 |
|
*/ |
1368 |
|
{ |
1369 |
|
unsigned max_iterations, iterations; |
1370 |
|
unsigned start; /* doesn't need to be long long */ |
1371 |
|
unsigned elapsed, elapsed2; |
1372 |
|
unsigned total_MB; |
1373 |
|
char *buf = xmalloc(TIMING_BUF_BYTES); |
1374 |
|
|
1375 |
|
if (mlock(buf, TIMING_BUF_BYTES)) |
1376 |
|
bb_perror_msg_and_die("mlock"); |
1377 |
|
|
1378 |
|
/* Clear out the device request queues & give them time to complete. |
1379 |
|
* NB: *small* delay. User is expected to have a clue and to not run |
1380 |
|
* heavy io in parallel with measurements. */ |
1381 |
sync(); |
sync(); |
1382 |
sleep(3); |
sleep(1); |
1383 |
|
if (cache) { /* Time cache */ |
1384 |
setitimer(ITIMER_REAL, &(struct itimerval){{1000,0},{1000,0}}, NULL); |
seek_to_zero(); |
1385 |
|
read_big_block(buf); |
1386 |
if (flag == 0) /* Time cache */ |
printf("Timing buffer-cache reads: "); |
1387 |
{ |
} else { /* Time device */ |
1388 |
if (seek_to_zero (fd)) return; |
printf("Timing buffered disk reads:"); |
1389 |
if (read_big_block (fd, buf)) return; |
} |
1390 |
printf(" Timing cached reads: "); |
fflush(stdout); |
1391 |
fflush(stdout); |
|
1392 |
|
/* Now do the timing */ |
1393 |
/* Now do the timing */ |
iterations = 0; |
1394 |
iterations = 0; |
/* Max time to run (small for cache, avoids getting |
1395 |
getitimer(ITIMER_REAL, &e1); |
* huge total_MB which can overlow unsigned type) */ |
1396 |
do { |
elapsed2 = 510000; /* cache */ |
1397 |
++iterations; |
max_iterations = UINT_MAX; |
1398 |
if (seek_to_zero (fd) || read_big_block (fd, buf)) |
if (!cache) { |
1399 |
goto quit; |
elapsed2 = 3000000; /* not cache */ |
1400 |
getitimer(ITIMER_REAL, &e2); |
/* Don't want to read past the end! */ |
1401 |
elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec) |
max_iterations = dev_size_mb() / TIMING_BUF_MB; |
1402 |
+ ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0); |
} |
1403 |
} while (elapsed < 2.0); |
start = monotonic_us(); |
1404 |
total_MB = iterations * TIMING_BUF_MB; |
do { |
1405 |
|
if (cache) |
1406 |
/* Now remove the lseek() and getitimer() overheads from the elapsed time */ |
seek_to_zero(); |
1407 |
getitimer(ITIMER_REAL, &e1); |
read_big_block(buf); |
1408 |
|
elapsed = (unsigned)monotonic_us() - start; |
1409 |
|
++iterations; |
1410 |
|
} while (elapsed < elapsed2 && iterations < max_iterations); |
1411 |
|
total_MB = iterations * TIMING_BUF_MB; |
1412 |
|
//printf(" elapsed:%u iterations:%u ", elapsed, iterations); |
1413 |
|
if (cache) { |
1414 |
|
/* Cache: remove lseek() and monotonic_us() overheads |
1415 |
|
* from elapsed */ |
1416 |
|
start = monotonic_us(); |
1417 |
do { |
do { |
1418 |
if (seek_to_zero (fd)) |
seek_to_zero(); |
1419 |
goto quit; |
elapsed2 = (unsigned)monotonic_us() - start; |
|
getitimer(ITIMER_REAL, &e2); |
|
|
elapsed2 = (e1.it_value.tv_sec - e2.it_value.tv_sec) |
|
|
+ ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0); |
|
1420 |
} while (--iterations); |
} while (--iterations); |
1421 |
|
//printf(" elapsed2:%u ", elapsed2); |
1422 |
elapsed -= elapsed2; |
elapsed -= elapsed2; |
1423 |
print_timing(BUFCACHE_FACTOR * total_MB, elapsed); |
total_MB *= 2; // BUFCACHE_FACTOR (why?) |
1424 |
flush_buffer_cache(fd); |
flush_buffer_cache(); |
|
sleep(1); |
|
|
} |
|
|
else /* Time device */ |
|
|
{ |
|
|
printf(" Timing buffered disk reads: "); |
|
|
fflush(stdout); |
|
|
/* |
|
|
* getitimer() is used rather than gettimeofday() because |
|
|
* it is much more consistent (on my machine, at least). |
|
|
*/ |
|
|
/* Now do the timings for real */ |
|
|
iterations = 0; |
|
|
getitimer(ITIMER_REAL, &e1); |
|
|
do { |
|
|
++iterations; |
|
|
if (read_big_block (fd, buf)) |
|
|
goto quit; |
|
|
getitimer(ITIMER_REAL, &e2); |
|
|
elapsed = (e1.it_value.tv_sec - e2.it_value.tv_sec) |
|
|
+ ((e1.it_value.tv_usec - e2.it_value.tv_usec) / 1000000.0); |
|
|
} while (elapsed < 3.0 && iterations < max_iterations); |
|
|
|
|
|
total_MB = iterations * TIMING_BUF_MB; |
|
|
print_timing(total_MB, elapsed); |
|
1425 |
} |
} |
1426 |
quit: |
print_timing(total_MB, elapsed); |
1427 |
munlock(buf, TIMING_BUF_BYTES); |
munlock(buf, TIMING_BUF_BYTES); |
1428 |
quit2: |
free(buf); |
|
RELEASE_CONFIG_BUFFER(buf); |
|
1429 |
} |
} |
1430 |
|
|
1431 |
static void on_off (unsigned int value) |
#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF |
1432 |
{ |
static void bus_state_value(unsigned value) |
|
printf(value ? " (on)\n" : " (off)\n"); |
|
|
} |
|
|
|
|
|
#ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF |
|
|
static void bus_state_value(unsigned int value) |
|
1433 |
{ |
{ |
1434 |
if (value == BUSSTATE_ON) |
if (value == BUSSTATE_ON) |
1435 |
on_off(1); |
on_off(1); |
1443 |
#endif |
#endif |
1444 |
|
|
1445 |
#ifdef HDIO_DRIVE_CMD |
#ifdef HDIO_DRIVE_CMD |
1446 |
static void interpret_standby(unsigned int standby) |
static void interpret_standby(uint8_t standby) |
1447 |
{ |
{ |
|
unsigned int t; |
|
|
|
|
1448 |
printf(" ("); |
printf(" ("); |
1449 |
if (standby == 0) |
if (standby == 0) { |
1450 |
printf("off"); |
printf("off"); |
1451 |
else if (standby == 252) |
} else if (standby <= 240 || standby == 252 || standby == 255) { |
1452 |
printf("21 minutes"); |
/* standby is in 5 sec units */ |
1453 |
else if (standby == 253) |
printf("%u minutes %u seconds", standby / 12, (standby*5) % 60); |
1454 |
printf("vendor-specific"); |
} else if (standby <= 251) { |
1455 |
else if (standby == 254) |
unsigned t = (standby - 240); /* t is in 30 min units */; |
1456 |
printf("Reserved"); |
printf("%u.%c hours", t / 2, (t & 1) ? '0' : '5'); |
|
else if (standby == 255) |
|
|
printf("21 minutes + 15 seconds"); |
|
|
else { |
|
|
if (standby <= 240) { |
|
|
t = standby * 5; |
|
|
printf("%u minutes + %u seconds", t / 60, t % 60); |
|
|
} else if (standby <= 251) { |
|
|
t = (standby - 240) * 30; |
|
|
printf("%u hours + %u minutes", t / 60, t % 60); |
|
|
} else |
|
|
printf("illegal value"); |
|
1457 |
} |
} |
1458 |
|
if (standby == 253) |
1459 |
|
printf("vendor-specific"); |
1460 |
|
if (standby == 254) |
1461 |
|
printf("reserved"); |
1462 |
printf(")\n"); |
printf(")\n"); |
1463 |
} |
} |
1464 |
|
|
1465 |
struct xfermode_entry { |
static const uint8_t xfermode_val[] ALIGN1 = { |
1466 |
int val; |
8, 9, 10, 11, 12, 13, 14, 15, |
1467 |
const char *name; |
16, 17, 18, 19, 20, 21, 22, 23, |
1468 |
|
32, 33, 34, 35, 36, 37, 38, 39, |
1469 |
|
64, 65, 66, 67, 68, 69, 70, 71 |
1470 |
}; |
}; |
1471 |
|
/* NB: we save size by _not_ storing terninating NUL! */ |
1472 |
static const struct xfermode_entry xfermode_table[] = { |
static const char xfermode_name[][5] ALIGN1 = { |
1473 |
{ 8, "pio0" }, |
"pio0", "pio1", "pio2", "pio3", "pio4", "pio5", "pio6", "pio7", |
1474 |
{ 9, "pio1" }, |
"sdma0","sdma1","sdma2","sdma3","sdma4","sdma5","sdma6","sdma7", |
1475 |
{ 10, "pio2" }, |
"mdma0","mdma1","mdma2","mdma3","mdma4","mdma5","mdma6","mdma7", |
1476 |
{ 11, "pio3" }, |
"udma0","udma1","udma2","udma3","udma4","udma5","udma6","udma7" |
|
{ 12, "pio4" }, |
|
|
{ 13, "pio5" }, |
|
|
{ 14, "pio6" }, |
|
|
{ 15, "pio7" }, |
|
|
{ 16, "sdma0" }, |
|
|
{ 17, "sdma1" }, |
|
|
{ 18, "sdma2" }, |
|
|
{ 19, "sdma3" }, |
|
|
{ 20, "sdma4" }, |
|
|
{ 21, "sdma5" }, |
|
|
{ 22, "sdma6" }, |
|
|
{ 23, "sdma7" }, |
|
|
{ 32, "mdma0" }, |
|
|
{ 33, "mdma1" }, |
|
|
{ 34, "mdma2" }, |
|
|
{ 35, "mdma3" }, |
|
|
{ 36, "mdma4" }, |
|
|
{ 37, "mdma5" }, |
|
|
{ 38, "mdma6" }, |
|
|
{ 39, "mdma7" }, |
|
|
{ 64, "udma0" }, |
|
|
{ 65, "udma1" }, |
|
|
{ 66, "udma2" }, |
|
|
{ 67, "udma3" }, |
|
|
{ 68, "udma4" }, |
|
|
{ 69, "udma5" }, |
|
|
{ 70, "udma6" }, |
|
|
{ 71, "udma7" }, |
|
|
{ 0, NULL } |
|
1477 |
}; |
}; |
1478 |
|
|
1479 |
static int translate_xfermode(char * name) |
static int translate_xfermode(const char *name) |
1480 |
{ |
{ |
1481 |
const struct xfermode_entry *tmp; |
int val; |
1482 |
char *endptr; |
unsigned i; |
|
int val = -1; |
|
|
|
|
|
|
|
|
for (tmp = xfermode_table; tmp->name != NULL; ++tmp) |
|
|
{ |
|
|
if (!strcmp(name, tmp->name)) |
|
|
return tmp->val; |
|
|
} |
|
1483 |
|
|
1484 |
val = strtol(name, &endptr, 10); |
for (i = 0; i < ARRAY_SIZE(xfermode_val); i++) { |
1485 |
if (*endptr == '\0') |
if (!strncmp(name, xfermode_name[i], 5)) |
1486 |
|
if (strlen(name) <= 5) |
1487 |
|
return xfermode_val[i]; |
1488 |
|
} |
1489 |
|
/* Negative numbers are invalid and are caught later */ |
1490 |
|
val = bb_strtoi(name, NULL, 10); |
1491 |
|
if (!errno) |
1492 |
return val; |
return val; |
|
|
|
1493 |
return -1; |
return -1; |
1494 |
} |
} |
1495 |
|
|
1496 |
static void interpret_xfermode(unsigned int xfermode) |
static void interpret_xfermode(unsigned xfermode) |
1497 |
{ |
{ |
1498 |
printf(" ("); |
printf(" ("); |
1499 |
if (xfermode == 0) |
if (xfermode == 0) |
1501 |
else if (xfermode == 1) |
else if (xfermode == 1) |
1502 |
printf("default PIO mode, disable IORDY"); |
printf("default PIO mode, disable IORDY"); |
1503 |
else if (xfermode >= 8 && xfermode <= 15) |
else if (xfermode >= 8 && xfermode <= 15) |
1504 |
printf("PIO flow control mode%u", xfermode-8); |
printf("PIO flow control mode%u", xfermode - 8); |
1505 |
else if (xfermode >= 16 && xfermode <= 23) |
else if (xfermode >= 16 && xfermode <= 23) |
1506 |
printf("singleword DMA mode%u", xfermode-16); |
printf("singleword DMA mode%u", xfermode - 16); |
1507 |
else if (xfermode >= 32 && xfermode <= 39) |
else if (xfermode >= 32 && xfermode <= 39) |
1508 |
printf("multiword DMA mode%u", xfermode-32); |
printf("multiword DMA mode%u", xfermode - 32); |
1509 |
else if (xfermode >= 64 && xfermode <= 71) |
else if (xfermode >= 64 && xfermode <= 71) |
1510 |
printf("UltraDMA mode%u", xfermode-64); |
printf("UltraDMA mode%u", xfermode - 64); |
1511 |
else |
else |
1512 |
printf("Unknown"); |
printf("unknown"); |
1513 |
printf(")\n"); |
printf(")\n"); |
1514 |
} |
} |
1515 |
#endif /* HDIO_DRIVE_CMD */ |
#endif /* HDIO_DRIVE_CMD */ |
1516 |
|
|
1517 |
static void print_flag(unsigned long flag, char *s, unsigned long value) |
static void print_flag(int flag, const char *s, unsigned long value) |
1518 |
{ |
{ |
1519 |
if (flag) |
if (flag) |
1520 |
printf(" setting %s to %ld\n", s, value); |
printf(" setting %s to %ld\n", s, value); |
1522 |
|
|
1523 |
static void process_dev(char *devname) |
static void process_dev(char *devname) |
1524 |
{ |
{ |
1525 |
int fd; |
/*int fd;*/ |
1526 |
static long parm, multcount; |
long parm, multcount; |
1527 |
#ifndef HDIO_DRIVE_CMD |
#ifndef HDIO_DRIVE_CMD |
1528 |
int force_operation = 0; |
int force_operation = 0; |
1529 |
#endif |
#endif |
1530 |
/* Please restore args[n] to these values after each ioctl |
/* Please restore args[n] to these values after each ioctl |
1531 |
except for args[2] */ |
except for args[2] */ |
1532 |
unsigned char args[4] = {WIN_SETFEATURES,0,0,0}; |
unsigned char args[4] = { WIN_SETFEATURES, 0, 0, 0 }; |
1533 |
const char *fmt = " %s\t= %2ld"; |
const char *fmt = " %s\t= %2ld"; |
1534 |
|
|
1535 |
fd = xopen(devname, O_RDONLY|O_NONBLOCK); |
/*fd = xopen(devname, O_RDONLY | O_NONBLOCK);*/ |
1536 |
|
xmove_fd(xopen(devname, O_RDONLY | O_NONBLOCK), fd); |
1537 |
printf("\n%s:\n", devname); |
printf("\n%s:\n", devname); |
1538 |
|
|
1539 |
if (set_readahead) |
if (set_readahead) { |
1540 |
{ |
print_flag(get_readahead, "fs readahead", Xreadahead); |
1541 |
print_flag(get_readahead,"fs readahead", Xreadahead); |
ioctl_or_warn(fd, BLKRASET, (int *)Xreadahead); |
1542 |
bb_ioctl(fd, BLKRASET,(int *)Xreadahead,"BLKRASET"); |
} |
1543 |
} |
#if ENABLE_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF |
1544 |
#ifdef CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF |
if (unregister_hwif) { |
|
if (unregister_hwif) |
|
|
{ |
|
1545 |
printf(" attempting to unregister hwif#%lu\n", hwif); |
printf(" attempting to unregister hwif#%lu\n", hwif); |
1546 |
bb_ioctl(fd, HDIO_UNREGISTER_HWIF,(int *)(unsigned long)hwif,"HDIO_UNREGISTER_HWIF"); |
ioctl_or_warn(fd, HDIO_UNREGISTER_HWIF, (int *)(unsigned long)hwif); |
1547 |
} |
} |
1548 |
#endif |
#endif |
1549 |
#ifdef CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF |
#if ENABLE_FEATURE_HDPARM_HDIO_SCAN_HWIF |
1550 |
if (scan_hwif) |
if (scan_hwif) { |
|
{ |
|
1551 |
printf(" attempting to scan hwif (0x%lx, 0x%lx, %lu)\n", hwif_data, hwif_ctrl, hwif_irq); |
printf(" attempting to scan hwif (0x%lx, 0x%lx, %lu)\n", hwif_data, hwif_ctrl, hwif_irq); |
1552 |
args[0] = hwif_data; |
args[0] = hwif_data; |
1553 |
args[1] = hwif_ctrl; |
args[1] = hwif_ctrl; |
1554 |
args[2] = hwif_irq; |
args[2] = hwif_irq; |
1555 |
bb_ioctl(fd, HDIO_SCAN_HWIF, args, "HDIO_SCAN_HWIF"); |
ioctl_or_warn(fd, HDIO_SCAN_HWIF, args); |
1556 |
args[0] = WIN_SETFEATURES; |
args[0] = WIN_SETFEATURES; |
1557 |
args[1] = 0; |
args[1] = 0; |
1558 |
} |
} |
1559 |
#endif |
#endif |
1560 |
if (set_piomode) |
if (set_piomode) { |
1561 |
{ |
if (noisy_piomode) { |
|
if (noisy_piomode) |
|
|
{ |
|
1562 |
printf(" attempting to "); |
printf(" attempting to "); |
1563 |
if (piomode == 255) |
if (piomode == 255) |
1564 |
printf("auto-tune PIO mode\n"); |
printf("auto-tune PIO mode\n"); |
1569 |
else |
else |
1570 |
printf("set UDMA mode to %d\n", (piomode-200)); |
printf("set UDMA mode to %d\n", (piomode-200)); |
1571 |
} |
} |
1572 |
bb_ioctl(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode, "HDIO_SET_PIO_MODE"); |
ioctl_or_warn(fd, HDIO_SET_PIO_MODE, (int *)(unsigned long)piomode); |
1573 |
} |
} |
1574 |
if (set_io32bit) |
if (set_io32bit) { |
1575 |
{ |
print_flag(get_io32bit, "32-bit IO_support flag", io32bit); |
1576 |
print_flag(get_io32bit,"32-bit IO_support flag", io32bit); |
ioctl_or_warn(fd, HDIO_SET_32BIT, (int *)io32bit); |
|
bb_ioctl(fd, HDIO_SET_32BIT, (int *)io32bit, "HDIO_SET_32BIT"); |
|
1577 |
} |
} |
1578 |
if (set_mult) |
if (set_mult) { |
|
{ |
|
1579 |
print_flag(get_mult, "multcount", mult); |
print_flag(get_mult, "multcount", mult); |
1580 |
#ifdef HDIO_DRIVE_CMD |
#ifdef HDIO_DRIVE_CMD |
1581 |
bb_ioctl(fd, HDIO_SET_MULTCOUNT, &mult, "HDIO_SET_MULTCOUNT"); |
ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult); |
1582 |
#else |
#else |
1583 |
force_operation |= (!bb_ioctl(fd, HDIO_SET_MULTCOUNT, &mult, "HDIO_SET_MULTCOUNT")); |
force_operation |= (!ioctl_or_warn(fd, HDIO_SET_MULTCOUNT, (void *)mult)); |
1584 |
#endif |
#endif |
1585 |
} |
} |
1586 |
if (set_readonly) |
if (set_readonly) { |
1587 |
{ |
print_flag_on_off(get_readonly, "readonly", readonly); |
1588 |
print_flag_on_off(get_readonly,"readonly", readonly); |
ioctl_or_warn(fd, BLKROSET, &readonly); |
1589 |
bb_ioctl(fd, BLKROSET, &readonly, "BLKROSET"); |
} |
1590 |
} |
if (set_unmask) { |
1591 |
if (set_unmask) |
print_flag_on_off(get_unmask, "unmaskirq", unmask); |
1592 |
{ |
ioctl_or_warn(fd, HDIO_SET_UNMASKINTR, (int *)unmask); |
1593 |
print_flag_on_off(get_unmask,"unmaskirq", unmask); |
} |
1594 |
bb_ioctl(fd, HDIO_SET_UNMASKINTR, (int *)unmask, "HDIO_SET_UNMASKINTR"); |
#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA |
1595 |
} |
if (set_dma) { |
|
#ifdef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA |
|
|
if (set_dma) |
|
|
{ |
|
1596 |
print_flag_on_off(get_dma, "using_dma", dma); |
print_flag_on_off(get_dma, "using_dma", dma); |
1597 |
bb_ioctl(fd, HDIO_SET_DMA, (int *)dma, "HDIO_SET_DMA"); |
ioctl_or_warn(fd, HDIO_SET_DMA, (int *)dma); |
1598 |
} |
} |
1599 |
#endif /* CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA */ |
#endif /* FEATURE_HDPARM_HDIO_GETSET_DMA */ |
1600 |
if (set_dma_q) |
#ifdef HDIO_SET_QDMA |
1601 |
{ |
if (set_dma_q) { |
1602 |
print_flag_on_off(get_dma_q,"DMA queue_depth", dma_q); |
print_flag_on_off(get_dma_q, "DMA queue_depth", dma_q); |
1603 |
bb_ioctl(fd, HDIO_SET_QDMA, (int *)dma_q, "HDIO_SET_QDMA"); |
ioctl_or_warn(fd, HDIO_SET_QDMA, (int *)dma_q); |
1604 |
} |
} |
1605 |
if (set_nowerr) |
#endif |
1606 |
{ |
if (set_nowerr) { |
1607 |
print_flag_on_off(get_nowerr,"nowerr", nowerr); |
print_flag_on_off(get_nowerr, "nowerr", nowerr); |
1608 |
bb_ioctl(fd, HDIO_SET_NOWERR, (int *)nowerr,"HDIO_SET_NOWERR"); |
ioctl_or_warn(fd, HDIO_SET_NOWERR, (int *)nowerr); |
1609 |
} |
} |
1610 |
if (set_keep) |
if (set_keep) { |
1611 |
{ |
print_flag_on_off(get_keep, "keep_settings", keep); |
1612 |
print_flag_on_off(get_keep,"keep_settings", keep); |
ioctl_or_warn(fd, HDIO_SET_KEEPSETTINGS, (int *)keep); |
|
bb_ioctl(fd, HDIO_SET_KEEPSETTINGS, (int *)keep,"HDIO_SET_KEEPSETTINGS"); |
|
1613 |
} |
} |
1614 |
#ifdef HDIO_DRIVE_CMD |
#ifdef HDIO_DRIVE_CMD |
1615 |
if (set_doorlock) |
if (set_doorlock) { |
|
{ |
|
1616 |
args[0] = doorlock ? WIN_DOORLOCK : WIN_DOORUNLOCK; |
args[0] = doorlock ? WIN_DOORLOCK : WIN_DOORUNLOCK; |
1617 |
args[2] = 0; |
args[2] = 0; |
1618 |
print_flag_on_off(get_doorlock,"drive doorlock", doorlock); |
print_flag_on_off(get_doorlock, "drive doorlock", doorlock); |
1619 |
bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(doorlock)"); |
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); |
1620 |
args[0] = WIN_SETFEATURES; |
args[0] = WIN_SETFEATURES; |
1621 |
} |
} |
1622 |
if (set_dkeep) |
if (set_dkeep) { |
|
{ |
|
1623 |
/* lock/unlock the drive's "feature" settings */ |
/* lock/unlock the drive's "feature" settings */ |
1624 |
print_flag_on_off(get_dkeep,"drive keep features", dkeep); |
print_flag_on_off(get_dkeep, "drive keep features", dkeep); |
1625 |
args[2] = dkeep ? 0x66 : 0xcc; |
args[2] = dkeep ? 0x66 : 0xcc; |
1626 |
bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(keepsettings)"); |
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); |
1627 |
} |
} |
1628 |
if (set_defects) |
if (set_defects) { |
|
{ |
|
1629 |
args[2] = defects ? 0x04 : 0x84; |
args[2] = defects ? 0x04 : 0x84; |
1630 |
print_flag(get_defects,"drive defect-mgmt", defects); |
print_flag(get_defects, "drive defect-mgmt", defects); |
1631 |
bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(defectmgmt)"); |
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); |
1632 |
} |
} |
1633 |
if (set_prefetch) |
if (set_prefetch) { |
|
{ |
|
1634 |
args[1] = prefetch; |
args[1] = prefetch; |
1635 |
args[2] = 0xab; |
args[2] = 0xab; |
1636 |
print_flag(get_prefetch,"drive prefetch", prefetch); |
print_flag(get_prefetch, "drive prefetch", prefetch); |
1637 |
bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setprefetch)"); |
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); |
1638 |
args[1] = 0; |
args[1] = 0; |
1639 |
} |
} |
1640 |
if (set_xfermode) |
if (set_xfermode) { |
|
{ |
|
1641 |
args[1] = xfermode_requested; |
args[1] = xfermode_requested; |
1642 |
args[2] = 3; |
args[2] = 3; |
1643 |
if (get_xfermode) |
if (get_xfermode) { |
1644 |
{ |
print_flag(1, "xfermode", xfermode_requested); |
|
print_flag(1,"xfermode", xfermode_requested); |
|
1645 |
interpret_xfermode(xfermode_requested); |
interpret_xfermode(xfermode_requested); |
1646 |
} |
} |
1647 |
bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD(setxfermode)"); |
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); |
1648 |
args[1] = 0; |
args[1] = 0; |
1649 |
} |
} |
1650 |
if (set_lookahead) |
if (set_lookahead) { |
|
{ |
|
1651 |
args[2] = lookahead ? 0xaa : 0x55; |
args[2] = lookahead ? 0xaa : 0x55; |
1652 |
print_flag_on_off(get_lookahead,"drive read-lookahead", lookahead); |
print_flag_on_off(get_lookahead, "drive read-lookahead", lookahead); |
1653 |
bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setreadahead)"); |
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); |
1654 |
} |
} |
1655 |
if (set_apmmode) |
if (set_apmmode) { |
|
{ |
|
1656 |
args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */; /* feature register */ |
args[2] = (apmmode == 255) ? 0x85 /* disable */ : 0x05 /* set */; /* feature register */ |
1657 |
args[1] = apmmode; /* sector count register 1-255 */ |
args[1] = apmmode; /* sector count register 1-255 */ |
1658 |
if (get_apmmode) |
if (get_apmmode) |
1659 |
printf(" setting APM level to %s 0x%02lX (%ld)\n", (apmmode == 255) ? "disabled" : "", apmmode, apmmode); |
printf(" setting APM level to %s 0x%02lX (%ld)\n", (apmmode == 255) ? "disabled" : "", apmmode, apmmode); |
1660 |
bb_ioctl(fd, HDIO_DRIVE_CMD, &args,"HDIO_DRIVE_CMD"); |
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); |
1661 |
args[1] = 0; |
args[1] = 0; |
1662 |
} |
} |
1663 |
if (set_wcache) |
if (set_wcache) { |
|
{ |
|
1664 |
#ifdef DO_FLUSHCACHE |
#ifdef DO_FLUSHCACHE |
1665 |
#ifndef WIN_FLUSHCACHE |
#ifndef WIN_FLUSHCACHE |
1666 |
#define WIN_FLUSHCACHE 0xe7 |
#define WIN_FLUSHCACHE 0xe7 |
1667 |
#endif |
#endif |
|
static unsigned char flushcache[4] = {WIN_FLUSHCACHE,0,0,0}; |
|
1668 |
#endif /* DO_FLUSHCACHE */ |
#endif /* DO_FLUSHCACHE */ |
1669 |
args[2] = wcache ? 0x02 : 0x82; |
args[2] = wcache ? 0x02 : 0x82; |
1670 |
print_flag_on_off(get_wcache,"drive write-caching", wcache); |
print_flag_on_off(get_wcache, "drive write-caching", wcache); |
1671 |
#ifdef DO_FLUSHCACHE |
#ifdef DO_FLUSHCACHE |
1672 |
if (!wcache) |
if (!wcache) |
1673 |
bb_ioctl(fd, HDIO_DRIVE_CMD, &flushcache, "HDIO_DRIVE_CMD(flushcache)"); |
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache); |
1674 |
#endif /* DO_FLUSHCACHE */ |
#endif /* DO_FLUSHCACHE */ |
1675 |
bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setcache)"); |
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); |
1676 |
#ifdef DO_FLUSHCACHE |
#ifdef DO_FLUSHCACHE |
1677 |
if (!wcache) |
if (!wcache) |
1678 |
bb_ioctl(fd, HDIO_DRIVE_CMD, &flushcache, "HDIO_DRIVE_CMD(flushcache)"); |
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &flushcache); |
1679 |
#endif /* DO_FLUSHCACHE */ |
#endif /* DO_FLUSHCACHE */ |
1680 |
} |
} |
1681 |
|
|
1683 |
is preserved, including args[2] */ |
is preserved, including args[2] */ |
1684 |
args[2] = 0; |
args[2] = 0; |
1685 |
|
|
1686 |
if (set_standbynow) |
if (set_standbynow) { |
|
{ |
|
1687 |
#ifndef WIN_STANDBYNOW1 |
#ifndef WIN_STANDBYNOW1 |
1688 |
#define WIN_STANDBYNOW1 0xE0 |
#define WIN_STANDBYNOW1 0xE0 |
1689 |
#endif |
#endif |
1692 |
#endif |
#endif |
1693 |
if (get_standbynow) printf(" issuing standby command\n"); |
if (get_standbynow) printf(" issuing standby command\n"); |
1694 |
args[0] = WIN_STANDBYNOW1; |
args[0] = WIN_STANDBYNOW1; |
1695 |
bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2, "HDIO_DRIVE_CMD(standby)"); |
ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_STANDBYNOW2); |
1696 |
} |
} |
1697 |
if (set_sleepnow) |
if (set_sleepnow) { |
|
{ |
|
1698 |
#ifndef WIN_SLEEPNOW1 |
#ifndef WIN_SLEEPNOW1 |
1699 |
#define WIN_SLEEPNOW1 0xE6 |
#define WIN_SLEEPNOW1 0xE6 |
1700 |
#endif |
#endif |
1703 |
#endif |
#endif |
1704 |
if (get_sleepnow) printf(" issuing sleep command\n"); |
if (get_sleepnow) printf(" issuing sleep command\n"); |
1705 |
args[0] = WIN_SLEEPNOW1; |
args[0] = WIN_SLEEPNOW1; |
1706 |
bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2, "HDIO_DRIVE_CMD(sleep)"); |
ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_SLEEPNOW2); |
1707 |
} |
} |
1708 |
if (set_seagate) |
if (set_seagate) { |
|
{ |
|
1709 |
args[0] = 0xfb; |
args[0] = 0xfb; |
1710 |
if (get_seagate) printf(" disabling Seagate auto powersaving mode\n"); |
if (get_seagate) printf(" disabling Seagate auto powersaving mode\n"); |
1711 |
bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(seagatepwrsave)"); |
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); |
1712 |
} |
} |
1713 |
if (set_standby) |
if (set_standby) { |
|
{ |
|
1714 |
args[0] = WIN_SETIDLE1; |
args[0] = WIN_SETIDLE1; |
1715 |
args[1] = standby_requested; |
args[1] = standby_requested; |
1716 |
if (get_standby) |
if (get_standby) { |
1717 |
{ |
print_flag(1, "standby", standby_requested); |
|
print_flag(1,"standby", standby_requested); |
|
1718 |
interpret_standby(standby_requested); |
interpret_standby(standby_requested); |
1719 |
} |
} |
1720 |
bb_ioctl(fd, HDIO_DRIVE_CMD, &args, "HDIO_DRIVE_CMD(setidle1)"); |
ioctl_or_warn(fd, HDIO_DRIVE_CMD, &args); |
1721 |
args[1] = 0; |
args[1] = 0; |
1722 |
} |
} |
1723 |
#else /* HDIO_DRIVE_CMD */ |
#else /* HDIO_DRIVE_CMD */ |
1724 |
if (force_operation) |
if (force_operation) { |
|
{ |
|
1725 |
char buf[512]; |
char buf[512]; |
1726 |
flush_buffer_cache(fd); |
flush_buffer_cache(); |
1727 |
if (-1 == read(fd, buf, sizeof(buf))) |
if (-1 == read(fd, buf, sizeof(buf))) |
1728 |
bb_perror_msg("read(%d bytes) failed (rc=%d)", sizeof(buf), -1); |
bb_perror_msg("read(%d bytes) failed (rc=-1)", sizeof(buf)); |
1729 |
} |
} |
1730 |
#endif /* HDIO_DRIVE_CMD */ |
#endif /* HDIO_DRIVE_CMD */ |
1731 |
|
|
1732 |
if (get_mult || get_identity) |
if (get_mult || get_identity) { |
|
{ |
|
1733 |
multcount = -1; |
multcount = -1; |
1734 |
if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) |
if (ioctl(fd, HDIO_GET_MULTCOUNT, &multcount)) { |
1735 |
{ |
if (get_mult && ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn. */ |
|
if (get_mult) |
|
1736 |
bb_perror_msg("HDIO_GET_MULTCOUNT"); |
bb_perror_msg("HDIO_GET_MULTCOUNT"); |
1737 |
} |
else |
1738 |
else if (get_mult) |
bb_perror_msg("ioctl %#x failed", HDIO_GET_MULTCOUNT); |
1739 |
{ |
} else if (get_mult) { |
1740 |
printf(fmt, "multcount", multcount); |
printf(fmt, "multcount", multcount); |
1741 |
on_off(multcount); |
on_off(multcount != 0); |
1742 |
} |
} |
1743 |
} |
} |
1744 |
if (get_io32bit) |
if (get_io32bit) { |
1745 |
{ |
if (!ioctl_or_warn(fd, HDIO_GET_32BIT, &parm)) { |
|
if (!bb_ioctl(fd, HDIO_GET_32BIT, &parm, "HDIO_GET_32BIT")) |
|
|
{ |
|
1746 |
printf(" IO_support\t=%3ld (", parm); |
printf(" IO_support\t=%3ld (", parm); |
1747 |
if (parm == 0) |
if (parm == 0) |
1748 |
printf("default 16-bit)\n"); |
printf("default 16-bit)\n"); |
1758 |
printf("\?\?\?)\n"); |
printf("\?\?\?)\n"); |
1759 |
} |
} |
1760 |
} |
} |
1761 |
if (get_unmask) |
if (get_unmask) { |
1762 |
{ |
if (!ioctl_or_warn(fd, HDIO_GET_UNMASKINTR, &parm)) |
1763 |
bb_ioctl_on_off(fd, HDIO_GET_UNMASKINTR,(unsigned long *)parm, |
print_value_on_off("unmaskirq", parm); |
|
"HDIO_GET_UNMASKINTR","unmaskirq"); |
|
1764 |
} |
} |
1765 |
|
|
1766 |
|
|
1767 |
#ifdef CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA |
#if ENABLE_FEATURE_HDPARM_HDIO_GETSET_DMA |
1768 |
if (get_dma) { |
if (get_dma) { |
1769 |
if (!bb_ioctl(fd, HDIO_GET_DMA, &parm, "HDIO_GET_DMA")) |
if (!ioctl_or_warn(fd, HDIO_GET_DMA, &parm)) { |
|
{ |
|
1770 |
printf(fmt, "using_dma", parm); |
printf(fmt, "using_dma", parm); |
1771 |
if (parm == 8) |
if (parm == 8) |
1772 |
printf(" (DMA-Assisted-PIO)\n"); |
printf(" (DMA-Assisted-PIO)\n"); |
1773 |
else |
else |
1774 |
on_off(parm); |
on_off(parm != 0); |
1775 |
} |
} |
1776 |
} |
} |
1777 |
#endif |
#endif |
1778 |
if (get_dma_q) |
#ifdef HDIO_GET_QDMA |
1779 |
{ |
if (get_dma_q) { |
1780 |
bb_ioctl_on_off (fd, HDIO_GET_QDMA,(unsigned long *)parm, |
if (!ioctl_or_warn(fd, HDIO_GET_QDMA, &parm)) |
1781 |
"HDIO_GET_QDMA","queue_depth"); |
print_value_on_off("queue_depth", parm); |
1782 |
} |
} |
1783 |
if (get_keep) |
#endif |
1784 |
{ |
if (get_keep) { |
1785 |
bb_ioctl_on_off (fd, HDIO_GET_KEEPSETTINGS,(unsigned long *)parm, |
if (!ioctl_or_warn(fd, HDIO_GET_KEEPSETTINGS, &parm)) |
1786 |
"HDIO_GET_KEEPSETTINGS","keepsettings"); |
print_value_on_off("keepsettings", parm); |
1787 |
} |
} |
1788 |
|
|
1789 |
if (get_nowerr) |
if (get_nowerr) { |
1790 |
{ |
if (!ioctl_or_warn(fd, HDIO_GET_NOWERR, &parm)) |
1791 |
bb_ioctl_on_off (fd, HDIO_GET_NOWERR,(unsigned long *)&parm, |
print_value_on_off("nowerr", parm); |
|
"HDIO_GET_NOWERR","nowerr"); |
|
1792 |
} |
} |
1793 |
if (get_readonly) |
if (get_readonly) { |
1794 |
{ |
if (!ioctl_or_warn(fd, BLKROGET, &parm)) |
1795 |
bb_ioctl_on_off(fd, BLKROGET,(unsigned long *)parm, |
print_value_on_off("readonly", parm); |
|
"BLKROGET","readonly"); |
|
1796 |
} |
} |
1797 |
if (get_readahead) |
if (get_readahead) { |
1798 |
{ |
if (!ioctl_or_warn(fd, BLKRAGET, &parm)) |
1799 |
bb_ioctl_on_off (fd, BLKRAGET, (unsigned long *) parm, |
print_value_on_off("readahead", parm); |
|
"BLKRAGET","readahead"); |
|
1800 |
} |
} |
1801 |
if (get_geom) |
if (get_geom) { |
1802 |
{ |
if (!ioctl_or_warn(fd, BLKGETSIZE, &parm)) { |
|
if (!bb_ioctl(fd, BLKGETSIZE, &parm, "BLKGETSIZE")) |
|
|
{ |
|
1803 |
struct hd_geometry g; |
struct hd_geometry g; |
1804 |
|
|
1805 |
if (!bb_ioctl(fd, HDIO_GETGEO, &g, "HDIO_GETGEO")) |
if (!ioctl_or_warn(fd, HDIO_GETGEO, &g)) |
1806 |
printf(" geometry\t= %u/%u/%u, sectors = %ld, start = %ld\n", |
printf(" geometry\t= %u/%u/%u, sectors = %ld, start = %ld\n", |
1807 |
g.cylinders, g.heads, g.sectors, parm, g.start); |
g.cylinders, g.heads, g.sectors, parm, g.start); |
1808 |
} |
} |
1809 |
} |
} |
1810 |
#ifdef HDIO_DRIVE_CMD |
#ifdef HDIO_DRIVE_CMD |
1811 |
if (get_powermode) |
if (get_powermode) { |
|
{ |
|
1812 |
#ifndef WIN_CHECKPOWERMODE1 |
#ifndef WIN_CHECKPOWERMODE1 |
1813 |
#define WIN_CHECKPOWERMODE1 0xE5 |
#define WIN_CHECKPOWERMODE1 0xE5 |
1814 |
#endif |
#endif |
1818 |
const char *state; |
const char *state; |
1819 |
|
|
1820 |
args[0] = WIN_CHECKPOWERMODE1; |
args[0] = WIN_CHECKPOWERMODE1; |
1821 |
if (bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2, 0)) |
if (ioctl_alt_or_warn(HDIO_DRIVE_CMD, args, WIN_CHECKPOWERMODE2)) { |
|
{ |
|
1822 |
if (errno != EIO || args[0] != 0 || args[1] != 0) |
if (errno != EIO || args[0] != 0 || args[1] != 0) |
1823 |
state = "Unknown"; |
state = "unknown"; |
1824 |
else |
else |
1825 |
state = "sleeping"; |
state = "sleeping"; |
1826 |
} |
} else |
|
else |
|
1827 |
state = (args[2] == 255) ? "active/idle" : "standby"; |
state = (args[2] == 255) ? "active/idle" : "standby"; |
1828 |
args[1] = args[2] = 0; |
args[1] = args[2] = 0; |
1829 |
|
|
1830 |
printf(" drive state is: %s\n", state); |
printf(" drive state is: %s\n", state); |
1831 |
} |
} |
1832 |
#endif |
#endif |
1833 |
#ifdef CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET |
#if ENABLE_FEATURE_HDPARM_HDIO_DRIVE_RESET |
1834 |
if (perform_reset) |
if (perform_reset) { |
1835 |
{ |
ioctl_or_warn(fd, HDIO_DRIVE_RESET, NULL); |
1836 |
bb_ioctl(fd, HDIO_DRIVE_RESET, NULL, "HDIO_DRIVE_RESET"); |
} |
1837 |
} |
#endif /* FEATURE_HDPARM_HDIO_DRIVE_RESET */ |
1838 |
#endif /* CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET */ |
#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF |
1839 |
#ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF |
if (perform_tristate) { |
|
if (perform_tristate) |
|
|
{ |
|
1840 |
args[0] = 0; |
args[0] = 0; |
1841 |
args[1] = tristate; |
args[1] = tristate; |
1842 |
bb_ioctl(fd, HDIO_TRISTATE_HWIF, &args, "HDIO_TRISTATE_HWIF"); |
ioctl_or_warn(fd, HDIO_TRISTATE_HWIF, &args); |
1843 |
} |
} |
1844 |
#endif /* CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF */ |
#endif /* FEATURE_HDPARM_HDIO_TRISTATE_HWIF */ |
1845 |
#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY |
#if ENABLE_FEATURE_HDPARM_GET_IDENTITY |
1846 |
if (get_identity) |
if (get_identity) { |
1847 |
{ |
struct hd_driveid id; |
|
static struct hd_driveid id; |
|
1848 |
|
|
1849 |
if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) |
if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) { |
1850 |
{ |
if (multcount != -1) { |
|
if (multcount != -1) |
|
|
{ |
|
1851 |
id.multsect = multcount; |
id.multsect = multcount; |
1852 |
id.multsect_valid |= 1; |
id.multsect_valid |= 1; |
1853 |
} |
} else |
|
else |
|
1854 |
id.multsect_valid &= ~1; |
id.multsect_valid &= ~1; |
1855 |
dump_identity(&id); |
dump_identity(&id); |
1856 |
} |
} else if (errno == -ENOMSG) |
|
else if (errno == -ENOMSG) |
|
1857 |
printf(" no identification info available\n"); |
printf(" no identification info available\n"); |
1858 |
else |
else if (ENABLE_IOCTL_HEX2STR_ERROR) /* To be coherent with ioctl_or_warn */ |
1859 |
bb_perror_msg("HDIO_GET_IDENTITY"); |
bb_perror_msg("HDIO_GET_IDENTITY"); |
1860 |
|
else |
1861 |
|
bb_perror_msg("ioctl %#x failed", HDIO_GET_IDENTITY); |
1862 |
} |
} |
1863 |
|
|
1864 |
if (get_IDentity) |
if (get_IDentity) { |
|
{ |
|
1865 |
unsigned char args1[4+512]; /* = { ... } will eat 0.5k of rodata! */ |
unsigned char args1[4+512]; /* = { ... } will eat 0.5k of rodata! */ |
1866 |
|
|
1867 |
memset(args1, 0, sizeof(args1)); |
memset(args1, 0, sizeof(args1)); |
1868 |
args1[0] = WIN_IDENTIFY; |
args1[0] = WIN_IDENTIFY; |
1869 |
args1[3] = 1; |
args1[3] = 1; |
1870 |
if (!bb_ioctl_alt(fd, HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY, "HDIO_DRIVE_CMD(identify)")) |
if (!ioctl_alt_or_warn(HDIO_DRIVE_CMD, args1, WIN_PIDENTIFY)) |
1871 |
identify((void *)(args1 + 4)); |
identify((void *)(args1 + 4)); |
1872 |
} |
} |
1873 |
#endif |
#endif |
1874 |
#ifdef CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF |
#if ENABLE_FEATURE_HDPARM_HDIO_TRISTATE_HWIF |
1875 |
if (set_busstate) |
if (set_busstate) { |
1876 |
{ |
if (get_busstate) { |
|
if (get_busstate) |
|
|
{ |
|
1877 |
print_flag(1, "bus state", busstate); |
print_flag(1, "bus state", busstate); |
1878 |
bus_state_value(busstate); |
bus_state_value(busstate); |
1879 |
} |
} |
1880 |
bb_ioctl(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate, "HDIO_SET_BUSSTATE"); |
ioctl_or_warn(fd, HDIO_SET_BUSSTATE, (int *)(unsigned long)busstate); |
1881 |
} |
} |
1882 |
if (get_busstate) |
if (get_busstate) { |
1883 |
{ |
if (!ioctl_or_warn(fd, HDIO_GET_BUSSTATE, &parm)) { |
|
if (!bb_ioctl(fd, HDIO_GET_BUSSTATE, &parm, "HDIO_GET_BUSSTATE")) |
|
|
{ |
|
1884 |
printf(fmt, "bus state", parm); |
printf(fmt, "bus state", parm); |
1885 |
bus_state_value(parm); |
bus_state_value(parm); |
1886 |
} |
} |
1887 |
} |
} |
1888 |
#endif |
#endif |
1889 |
if (reread_partn) |
if (reread_partn) |
1890 |
bb_ioctl(fd, BLKRRPART, NULL, "BLKRRPART"); |
ioctl_or_warn(fd, BLKRRPART, NULL); |
|
|
|
1891 |
|
|
1892 |
if (do_ctimings) |
if (do_ctimings) |
1893 |
do_time(0,fd); /*time cache */ |
do_time(1 /*,fd*/); /* time cache */ |
1894 |
if (do_timings) |
if (do_timings) |
1895 |
do_time(1,fd); /*time device */ |
do_time(0 /*,fd*/); /* time device */ |
1896 |
if (do_flush) |
if (do_flush) |
1897 |
flush_buffer_cache(fd); |
flush_buffer_cache(); |
1898 |
close(fd); |
close(fd); |
1899 |
} |
} |
1900 |
|
|
1901 |
#ifdef CONFIG_FEATURE_HDPARM_GET_IDENTITY |
#if ENABLE_FEATURE_HDPARM_GET_IDENTITY |
1902 |
static int fromhex(unsigned char c) |
static int fromhex(unsigned char c) |
1903 |
{ |
{ |
1904 |
if (isdigit(c)) |
if (isdigit(c)) |
1908 |
bb_error_msg_and_die("bad char: '%c' 0x%02x", c, c); |
bb_error_msg_and_die("bad char: '%c' 0x%02x", c, c); |
1909 |
} |
} |
1910 |
|
|
1911 |
|
static void identify_from_stdin(void) NORETURN; |
1912 |
static void identify_from_stdin(void) |
static void identify_from_stdin(void) |
1913 |
{ |
{ |
1914 |
uint16_t sbuf[256]; |
uint16_t sbuf[256]; |
1916 |
unsigned char *b = (unsigned char *)buf; |
unsigned char *b = (unsigned char *)buf; |
1917 |
int i; |
int i; |
1918 |
|
|
1919 |
xread(0, buf, 1280); |
xread(STDIN_FILENO, buf, 1280); |
1920 |
|
|
1921 |
// Convert the newline-separated hex data into an identify block. |
// Convert the newline-separated hex data into an identify block. |
1922 |
|
|
1923 |
for (i = 0; i<256; i++) { |
for (i = 0; i < 256; i++) { |
1924 |
int j; |
int j; |
1925 |
for (j = 0; j < 4; j++) |
for (j = 0; j < 4; j++) |
1926 |
sbuf[i] = (sbuf[i] << 4) + fromhex(*(b++)); |
sbuf[i] = (sbuf[i] << 4) + fromhex(*(b++)); |
1930 |
|
|
1931 |
identify(sbuf); |
identify(sbuf); |
1932 |
} |
} |
1933 |
|
#else |
1934 |
|
void identify_from_stdin(void); |
1935 |
#endif |
#endif |
1936 |
|
|
1937 |
/* busybox specific stuff */ |
/* busybox specific stuff */ |
1938 |
static void parse_opts(unsigned long *get, unsigned long *set, unsigned long *value, int min, int max) |
static void parse_opts(smallint *get, smallint *set, unsigned long *value, int min, int max) |
1939 |
{ |
{ |
1940 |
if (get) { |
if (get) { |
1941 |
*get = 1; |
*get = 1; |
1946 |
} |
} |
1947 |
} |
} |
1948 |
|
|
1949 |
static void parse_xfermode(int flag, unsigned long *get, unsigned long *set, int *value) |
static void parse_xfermode(int flag, smallint *get, smallint *set, int *value) |
1950 |
{ |
{ |
1951 |
if (flag) { |
if (flag) { |
1952 |
*get = 1; |
*get = 1; |
1953 |
if (optarg) { |
if (optarg) { |
1954 |
*set = ((*value = translate_xfermode(optarg)) > -1); |
*value = translate_xfermode(optarg); |
1955 |
|
*set = (*value > -1); |
1956 |
} |
} |
1957 |
} |
} |
1958 |
} |
} |
1959 |
|
|
1960 |
/*------- getopt short options --------*/ |
/*------- getopt short options --------*/ |
1961 |
static const char hdparm_options[] = "gfu::n::p:r::m::c::k::a::B:tTh" |
static const char hdparm_options[] ALIGN1 = |
1962 |
|
"gfu::n::p:r::m::c::k::a::B:tT" |
1963 |
USE_FEATURE_HDPARM_GET_IDENTITY("iI") |
USE_FEATURE_HDPARM_GET_IDENTITY("iI") |
1964 |
USE_FEATURE_HDPARM_HDIO_GETSET_DMA("d::") |
USE_FEATURE_HDPARM_HDIO_GETSET_DMA("d::") |
1965 |
#ifdef HDIO_DRIVE_CMD |
#ifdef HDIO_DRIVE_CMD |
1979 |
/*-------------------------------------*/ |
/*-------------------------------------*/ |
1980 |
|
|
1981 |
/* our main() routine: */ |
/* our main() routine: */ |
1982 |
int hdparm_main(int argc, char **argv) ATTRIBUTE_NORETURN; |
int hdparm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1983 |
int hdparm_main(int argc, char **argv) |
int hdparm_main(int argc, char **argv) |
1984 |
{ |
{ |
1985 |
int c; |
int c; |
1987 |
|
|
1988 |
while ((c = getopt(argc, argv, hdparm_options)) >= 0) { |
while ((c = getopt(argc, argv, hdparm_options)) >= 0) { |
1989 |
flagcount++; |
flagcount++; |
|
if (c == 'h') bb_show_usage(); /* EXIT */ |
|
1990 |
USE_FEATURE_HDPARM_GET_IDENTITY(get_IDentity |= (c == 'I')); |
USE_FEATURE_HDPARM_GET_IDENTITY(get_IDentity |= (c == 'I')); |
1991 |
USE_FEATURE_HDPARM_GET_IDENTITY(get_identity |= (c == 'i')); |
USE_FEATURE_HDPARM_GET_IDENTITY(get_identity |= (c == 'i')); |
1992 |
get_geom |= (c == 'g'); |
get_geom |= (c == 'g'); |
1994 |
if (c == 'u') parse_opts(&get_unmask, &set_unmask, &unmask, 0, 1); |
if (c == 'u') parse_opts(&get_unmask, &set_unmask, &unmask, 0, 1); |
1995 |
USE_FEATURE_HDPARM_HDIO_GETSET_DMA(if (c == 'd') parse_opts(&get_dma, &set_dma, &dma, 0, 9)); |
USE_FEATURE_HDPARM_HDIO_GETSET_DMA(if (c == 'd') parse_opts(&get_dma, &set_dma, &dma, 0, 9)); |
1996 |
if (c == 'n') parse_opts(&get_nowerr, &set_nowerr, &nowerr, 0, 1); |
if (c == 'n') parse_opts(&get_nowerr, &set_nowerr, &nowerr, 0, 1); |
1997 |
parse_xfermode((c == 'p'),&noisy_piomode, &set_piomode, &piomode); |
parse_xfermode((c == 'p'), &noisy_piomode, &set_piomode, &piomode); |
1998 |
if (c == 'r') parse_opts(&get_readonly, &set_readonly, &readonly, 0, 1); |
if (c == 'r') parse_opts(&get_readonly, &set_readonly, &readonly, 0, 1); |
1999 |
if (c == 'm') parse_opts(&get_mult, &set_mult, &mult, 0, INT_MAX /*32*/); |
if (c == 'm') parse_opts(&get_mult, &set_mult, &mult, 0, INT_MAX /*32*/); |
2000 |
if (c == 'c') parse_opts(&get_io32bit, &set_io32bit, &io32bit, 0, INT_MAX /*8*/); |
if (c == 'c') parse_opts(&get_io32bit, &set_io32bit, &io32bit, 0, INT_MAX /*8*/); |
2004 |
do_flush |= do_timings |= (c == 't'); |
do_flush |= do_timings |= (c == 't'); |
2005 |
do_flush |= do_ctimings |= (c == 'T'); |
do_flush |= do_ctimings |= (c == 'T'); |
2006 |
#ifdef HDIO_DRIVE_CMD |
#ifdef HDIO_DRIVE_CMD |
2007 |
if (c == 'S') parse_opts(&get_standby, &set_standby, &standby_requested, 0, INT_MAX); |
if (c == 'S') parse_opts(&get_standby, &set_standby, &standby_requested, 0, 255); |
2008 |
if (c == 'D') parse_opts(&get_defects, &set_defects, &defects, 0, INT_MAX); |
if (c == 'D') parse_opts(&get_defects, &set_defects, &defects, 0, INT_MAX); |
2009 |
if (c == 'P') parse_opts(&get_prefetch, &set_prefetch, &prefetch, 0, INT_MAX); |
if (c == 'P') parse_opts(&get_prefetch, &set_prefetch, &prefetch, 0, INT_MAX); |
2010 |
parse_xfermode((c == 'X'), &get_xfermode, &set_xfermode, &xfermode_requested); |
parse_xfermode((c == 'X'), &get_xfermode, &set_xfermode, &xfermode_requested); |
2047 |
get_mult = get_io32bit = get_unmask = get_keep = get_readonly = get_readahead = get_geom = 1; |
get_mult = get_io32bit = get_unmask = get_keep = get_readonly = get_readahead = get_geom = 1; |
2048 |
USE_FEATURE_HDPARM_HDIO_GETSET_DMA(get_dma = 1); |
USE_FEATURE_HDPARM_HDIO_GETSET_DMA(get_dma = 1); |
2049 |
} |
} |
|
argc -= optind; |
|
2050 |
argv += optind; |
argv += optind; |
2051 |
|
|
2052 |
if (argc < 1) { |
if (!*argv) { |
2053 |
if (ENABLE_FEATURE_HDPARM_GET_IDENTITY && !isatty(STDIN_FILENO)) |
if (ENABLE_FEATURE_HDPARM_GET_IDENTITY && !isatty(STDIN_FILENO)) |
2054 |
identify_from_stdin(); /* EXIT */ |
identify_from_stdin(); /* EXIT */ |
2055 |
else bb_show_usage(); |
bb_show_usage(); |
2056 |
} |
} |
2057 |
|
|
2058 |
while (argc--) { |
do { |
2059 |
process_dev(*argv); |
process_dev(*argv++); |
2060 |
argv++; |
} while (*argv); |
2061 |
} |
|
2062 |
exit(EXIT_SUCCESS); |
return EXIT_SUCCESS; |
2063 |
} |
} |