• Home
  • History
  • Annotate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/hdparm-9.43/

Lines Matching defs:*

0 /* sgio.c - by Mark Lord (C) 2007 -- freely distributable */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <sys/ioctl.h>
9 #include <sys/stat.h>
10 #include <sys/types.h>
12 #include <scsi/scsi.h>
13 #include <scsi/sg.h>
15 #include "sgio.h"
16 #include "hdparm.h"
18 #include <linux/hdreg.h>
20 extern int verbose;
21 extern int prefer_ata12;
23 static const unsigned int default_timeout_secs = 15;
26 * Taskfile layout for SG_ATA_16 cdb:
28 * LBA48:
29 * cdb[ 3] = hob_feat
30 * cdb[ 5] = hob_nsect
31 * cdb[ 7] = hob_lbal
32 * cdb[ 9] = hob_lbam
33 * cdb[11] = hob_lbah
35 * LBA28/LBA48:
36 * cdb[ 4] = feat
37 * cdb[ 6] = nsect
38 * cdb[ 8] = lbal
39 * cdb[10] = lbam
40 * cdb[12] = lbah
41 * cdb[13] = device
42 * cdb[14] = command
44 * Taskfile layout for SG_ATA_12 cdb:
46 * cdb[ 3] = feat
47 * cdb[ 4] = nsect
48 * cdb[ 5] = lbal
49 * cdb[ 6] = lbam
50 * cdb[ 7] = lbah
51 * cdb[ 8] = device
52 * cdb[ 9] = command
54 * dxfer_direction choices:
55 * SG_DXFER_TO_DEV, SG_DXFER_FROM_DEV, SG_DXFER_NONE
58 #if 0 /* maybe use this in sg16 later.. ? */
59 static inline int get_rw (__u8 ata_op)
61 switch (ata_op) {
62 case ATA_OP_DSM:
63 case ATA_OP_WRITE_PIO:
64 case ATA_OP_WRITE_LONG:
65 case ATA_OP_WRITE_LONG_ONCE:
66 case ATA_OP_WRITE_PIO_EXT:
67 case ATA_OP_WRITE_DMA_EXT:
68 case ATA_OP_WRITE_FPDMA:
69 case ATA_OP_WRITE_UNC_EXT:
70 case ATA_OP_WRITE_DMA:
71 case ATA_OP_SECURITY_UNLOCK:
72 case ATA_OP_SECURITY_DISABLE:
73 case ATA_OP_SECURITY_ERASE_UNIT:
74 case ATA_OP_SECURITY_SET_PASS:
75 return SG_WRITE;
76 default:
77 return SG_READ;
80 #endif
82 static inline int needs_lba48 (__u8 ata_op, __u64 lba, unsigned int nsect)
84 switch (ata_op) {
85 case ATA_OP_DSM:
86 case ATA_OP_READ_PIO_EXT:
87 case ATA_OP_READ_DMA_EXT:
88 case ATA_OP_WRITE_PIO_EXT:
89 case ATA_OP_WRITE_DMA_EXT:
90 case ATA_OP_READ_VERIFY_EXT:
91 case ATA_OP_WRITE_UNC_EXT:
92 case ATA_OP_READ_NATIVE_MAX_EXT:
93 case ATA_OP_SET_MAX_EXT:
94 case ATA_OP_FLUSHCACHE_EXT:
95 return 1;
96 case ATA_OP_SECURITY_ERASE_PREPARE:
97 case ATA_OP_SECURITY_ERASE_UNIT:
98 case ATA_OP_VENDOR_SPECIFIC_0x80:
99 case ATA_OP_SMART:
100 return 0;
102 if (lba >= lba28_limit)
103 return 1;
104 if (nsect) {
105 if (nsect > 0xff)
106 return 1;
107 if ((lba + nsect - 1) >= lba28_limit)
108 return 1;
110 return 0;
113 static inline int is_dma (__u8 ata_op)
115 switch (ata_op) {
116 case ATA_OP_DSM:
117 case ATA_OP_READ_DMA_EXT:
118 case ATA_OP_READ_FPDMA:
119 case ATA_OP_WRITE_DMA_EXT:
120 case ATA_OP_WRITE_FPDMA:
121 case ATA_OP_READ_DMA:
122 case ATA_OP_WRITE_DMA:
123 return SG_DMA;
124 default:
125 return SG_PIO;
129 void tf_init (struct ata_tf *tf, __u8 ata_op, __u64 lba, unsigned int nsect)
131 memset(tf, 0, sizeof(*tf));
132 tf->command = ata_op;
133 tf->dev = ATA_USING_LBA;
134 tf->lob.lbal = lba;
135 tf->lob.lbam = lba >> 8;
136 tf->lob.lbah = lba >> 16;
137 tf->lob.nsect = nsect;
138 if (needs_lba48(ata_op, lba, nsect)) {
139 tf->is_lba48 = 1;
140 tf->hob.nsect = nsect >> 8;
141 tf->hob.lbal = lba >> 24;
142 tf->hob.lbam = lba >> 32;
143 tf->hob.lbah = lba >> 40;
144 } else {
145 tf->dev |= (lba >> 24) & 0x0f;
149 #ifdef SG_IO
151 __u64 tf_to_lba (struct ata_tf *tf)
153 __u32 lba24, lbah;
154 __u64 lba64;
156 lba24 = (tf->lob.lbah << 16) | (tf->lob.lbam << 8) | (tf->lob.lbal);
157 if (tf->is_lba48)
158 lbah = (tf->hob.lbah << 16) | (tf->hob.lbam << 8) | (tf->hob.lbal);
159 else
160 lbah = (tf->dev & 0x0f);
161 lba64 = (((__u64)lbah) << 24) | (__u64)lba24;
162 return lba64;
165 enum {
166 SG_CDB2_TLEN_NODATA = 0 << 0,
167 SG_CDB2_TLEN_FEAT = 1 << 0,
168 SG_CDB2_TLEN_NSECT = 2 << 0,
170 SG_CDB2_TLEN_BYTES = 0 << 2,
171 SG_CDB2_TLEN_SECTORS = 1 << 2,
173 SG_CDB2_TDIR_TO_DEV = 0 << 3,
174 SG_CDB2_TDIR_FROM_DEV = 1 << 3,
176 SG_CDB2_CHECK_COND = 1 << 5,
179 static void dump_bytes (const char *prefix, unsigned char *p, int len)
181 int i;
183 if (prefix)
184 fprintf(stderr, "%s: ", prefix);
185 for (i = 0; i < len; ++i)
186 fprintf(stderr, " %02x", p[i]);
187 fprintf(stderr, "\n");
190 int sg16 (int fd, int rw, int dma, struct ata_tf *tf,
191 void *data, unsigned int data_bytes, unsigned int timeout_secs)
193 unsigned char cdb[SG_ATA_16_LEN];
194 unsigned char sb[32], *desc;
195 struct scsi_sg_io_hdr io_hdr;
196 int prefer12 = prefer_ata12, demanded_sense = 0;
198 if (tf->command == ATA_OP_PIDENTIFY)
199 prefer12 = 0;
201 memset(&cdb, 0, sizeof(cdb));
202 memset(&sb, 0, sizeof(sb));
203 memset(&io_hdr, 0, sizeof(struct scsi_sg_io_hdr));
204 if (data && data_bytes && !rw)
205 memset(data, 0, data_bytes);
207 if (dma) {
208 //cdb[1] = data ? (rw ? SG_ATA_PROTO_UDMA_OUT : SG_ATA_PROTO_UDMA_IN) : SG_ATA_PROTO_NON_DATA;
209 cdb[1] = data ? SG_ATA_PROTO_DMA : SG_ATA_PROTO_NON_DATA;
210 } else {
211 cdb[1] = data ? (rw ? SG_ATA_PROTO_PIO_OUT : SG_ATA_PROTO_PIO_IN) : SG_ATA_PROTO_NON_DATA;
214 /* libata/AHCI workaround: don't demand sense data for IDENTIFY commands */
215 if (data) {
216 cdb[2] |= SG_CDB2_TLEN_NSECT | SG_CDB2_TLEN_SECTORS;
217 cdb[2] |= rw ? SG_CDB2_TDIR_TO_DEV : SG_CDB2_TDIR_FROM_DEV;
218 } else {
219 cdb[2] = SG_CDB2_CHECK_COND;
222 if (!prefer12 || tf->is_lba48) {
223 cdb[ 0] = SG_ATA_16;
224 cdb[ 4] = tf->lob.feat;
225 cdb[ 6] = tf->lob.nsect;
226 cdb[ 8] = tf->lob.lbal;
227 cdb[10] = tf->lob.lbam;
228 cdb[12] = tf->lob.lbah;
229 cdb[13] = tf->dev;
230 cdb[14] = tf->command;
231 if (tf->is_lba48) {
232 cdb[ 1] |= SG_ATA_LBA48;
233 cdb[ 3] = tf->hob.feat;
234 cdb[ 5] = tf->hob.nsect;
235 cdb[ 7] = tf->hob.lbal;
236 cdb[ 9] = tf->hob.lbam;
237 cdb[11] = tf->hob.lbah;
239 io_hdr.cmd_len = SG_ATA_16_LEN;
240 } else {
241 cdb[ 0] = SG_ATA_12;
242 cdb[ 3] = tf->lob.feat;
243 cdb[ 4] = tf->lob.nsect;
244 cdb[ 5] = tf->lob.lbal;
245 cdb[ 6] = tf->lob.lbam;
246 cdb[ 7] = tf->lob.lbah;
247 cdb[ 8] = tf->dev;
248 cdb[ 9] = tf->command;
249 io_hdr.cmd_len = SG_ATA_12_LEN;
252 io_hdr.interface_id = 'S';
253 io_hdr.mx_sb_len = sizeof(sb);
254 io_hdr.dxfer_direction = data ? (rw ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV) : SG_DXFER_NONE;
255 io_hdr.dxfer_len = data ? data_bytes : 0;
256 io_hdr.dxferp = data;
257 io_hdr.cmdp = cdb;
258 io_hdr.sbp = sb;
259 io_hdr.pack_id = tf_to_lba(tf);
260 io_hdr.timeout = (timeout_secs ? timeout_secs : default_timeout_secs) * 1000; /* msecs */
262 if (verbose) {
263 dump_bytes("outgoing cdb", cdb, sizeof(cdb));
264 if (rw && data)
265 dump_bytes("outgoing_data", data, data_bytes);
268 if (ioctl(fd, SG_IO, &io_hdr) == -1) {
269 if (verbose)
270 perror("ioctl(fd,SG_IO)");
271 return -1; /* SG_IO not supported */
274 if (verbose)
275 fprintf(stderr, "SG_IO: ATA_%u status=0x%x, host_status=0x%x, driver_status=0x%x\n",
276 io_hdr.cmd_len, io_hdr.status, io_hdr.host_status, io_hdr.driver_status);
278 if (io_hdr.status && io_hdr.status != SG_CHECK_CONDITION) {
279 if (verbose)
280 fprintf(stderr, "SG_IO: bad status: 0x%x\n", io_hdr.status);
281 errno = EBADE;
282 return -1;
284 if (io_hdr.host_status) {
285 if (verbose)
286 fprintf(stderr, "SG_IO: bad host status: 0x%x\n", io_hdr.host_status);
287 errno = EBADE;
288 return -1;
290 if (verbose) {
291 dump_bytes("SG_IO: sb[]", sb, sizeof(sb));
292 if (!rw && data)
293 dump_bytes("incoming_data", data, data_bytes);
296 if (io_hdr.driver_status && (io_hdr.driver_status != SG_DRIVER_SENSE)) {
297 if (verbose)
298 fprintf(stderr, "SG_IO: bad driver status: 0x%x\n", io_hdr.driver_status);
299 errno = EBADE;
300 return -1;
303 desc = sb + 8;
304 if (io_hdr.driver_status != SG_DRIVER_SENSE) {
305 if (sb[0] | sb[1] | sb[2] | sb[3] | sb[4] | sb[5] | sb[6] | sb[7] | sb[8] | sb[9]) {
306 static int second_try = 0;
307 if (!second_try++)
308 fprintf(stderr, "SG_IO: questionable sense data, results may be incorrect\n");
309 } else if (demanded_sense) {
310 static int second_try = 0;
311 if (!second_try++)
312 fprintf(stderr, "SG_IO: missing sense data, results may be incorrect\n");
314 } else if (sb[0] != 0x72 || sb[7] < 14 || desc[0] != 0x09 || desc[1] < 0x0c) {
315 dump_bytes("SG_IO: bad/missing sense data, sb[]", sb, sizeof(sb));
318 if (verbose) {
319 unsigned int len = desc[1] + 2, maxlen = sizeof(sb) - 8 - 2;
320 if (len > maxlen)
321 len = maxlen;
322 dump_bytes("SG_IO: desc[]", desc, len);
325 tf->is_lba48 = desc[ 2] & 1;
326 tf->error = desc[ 3];
327 tf->lob.nsect = desc[ 5];
328 tf->lob.lbal = desc[ 7];
329 tf->lob.lbam = desc[ 9];
330 tf->lob.lbah = desc[11];
331 tf->dev = desc[12];
332 tf->status = desc[13];
333 tf->hob.feat = 0;
334 if (tf->is_lba48) {
335 tf->hob.nsect = desc[ 4];
336 tf->hob.lbal = desc[ 6];
337 tf->hob.lbam = desc[ 8];
338 tf->hob.lbah = desc[10];
339 } else {
340 tf->hob.nsect = 0;
341 tf->hob.lbal = 0;
342 tf->hob.lbam = 0;
343 tf->hob.lbah = 0;
346 if (verbose)
347 fprintf(stderr, " ATA_%u stat=%02x err=%02x nsect=%02x lbal=%02x lbam=%02x lbah=%02x dev=%02x\n",
348 io_hdr.cmd_len, tf->status, tf->error, tf->lob.nsect, tf->lob.lbal, tf->lob.lbam, tf->lob.lbah, tf->dev);
350 if (tf->status & (ATA_STAT_ERR | ATA_STAT_DRQ)) {
351 if (verbose) {
352 fprintf(stderr, "I/O error, ata_op=0x%02x ata_status=0x%02x ata_error=0x%02x\n",
353 tf->command, tf->status, tf->error);
355 errno = EIO;
356 return -1;
358 return 0;
361 #endif /* SG_IO */
363 int do_drive_cmd (int fd, unsigned char *args, unsigned int timeout_secs)
365 #ifdef SG_IO
367 struct ata_tf tf;
368 void *data = NULL;
369 unsigned int data_bytes = 0;
370 int rc;
372 if (args == NULL)
373 goto use_legacy_ioctl;
375 * Reformat and try to issue via SG_IO:
376 * args[0]: command in; status out.
377 * args[1]: lbal for SMART, nsect for all others; error out
378 * args[2]: feat in; nsect out.
379 * args[3]: data-count (512 multiple) for all cmds.
381 tf_init(&tf, args[0], 0, 0);
382 tf.lob.nsect = args[1];
383 tf.lob.feat = args[2];
384 if (args[3]) {
385 data_bytes = args[3] * 512;
386 data = args + 4;
387 if (!tf.lob.nsect)
388 tf.lob.nsect = args[3];
390 if (tf.command == ATA_OP_SMART) {
391 tf.lob.nsect = args[3];
392 tf.lob.lbal = args[1];
393 tf.lob.lbam = 0x4f;
394 tf.lob.lbah = 0xc2;
397 rc = sg16(fd, SG_READ, is_dma(tf.command), &tf, data, data_bytes, timeout_secs);
398 if (rc == -1) {
399 if (errno == EINVAL || errno == ENODEV || errno == EBADE)
400 goto use_legacy_ioctl;
403 if (rc == 0 || errno == EIO) {
404 args[0] = tf.status;
405 args[1] = tf.error;
406 args[2] = tf.lob.nsect;
408 return rc;
410 use_legacy_ioctl:
411 #endif /* SG_IO */
412 if (verbose) {
413 if (args)
414 fprintf(stderr, "Trying legacy HDIO_DRIVE_CMD\n");
416 return ioctl(fd, HDIO_DRIVE_CMD, args);
419 int do_taskfile_cmd (int fd, struct hdio_taskfile *r, unsigned int timeout_secs)
421 int rc;
422 #ifdef SG_IO
423 struct ata_tf tf;
424 void *data = NULL;
425 unsigned int data_bytes = 0;
426 int rw = SG_READ;
428 * Reformat and try to issue via SG_IO:
430 tf_init(&tf, 0, 0, 0);
431 #if 1 /* debugging */
432 if (verbose) {
433 printf("oflags.lob_all=0x%02x, flags={", r->oflags.lob_all);
434 if (r->oflags.lob.feat) printf(" feat");
435 if (r->oflags.lob.nsect)printf(" nsect");
436 if (r->oflags.lob.lbal) printf(" lbal");
437 if (r->oflags.lob.lbam) printf(" lbam");
438 if (r->oflags.lob.lbah) printf(" lbah");
439 if (r->oflags.lob.dev) printf(" dev");
440 if (r->oflags.lob.command) printf(" command");
441 printf(" }\n");
442 printf("oflags.hob_all=0x%02x, flags={", r->oflags.hob_all);
443 if (r->oflags.hob.feat) printf(" feat");
444 if (r->oflags.hob.nsect)printf(" nsect");
445 if (r->oflags.hob.lbal) printf(" lbal");
446 if (r->oflags.hob.lbam) printf(" lbam");
447 if (r->oflags.hob.lbah) printf(" lbah");
448 printf(" }\n");
450 #endif
451 if (r->oflags.lob.feat) tf.lob.feat = r->lob.feat;
452 if (r->oflags.lob.lbal) tf.lob.lbal = r->lob.lbal;
453 if (r->oflags.lob.nsect) tf.lob.nsect = r->lob.nsect;
454 if (r->oflags.lob.lbam) tf.lob.lbam = r->lob.lbam;
455 if (r->oflags.lob.lbah) tf.lob.lbah = r->lob.lbah;
456 if (r->oflags.lob.dev) tf.dev = r->lob.dev;
457 if (r->oflags.lob.command) tf.command = r->lob.command;
458 if (needs_lba48(tf.command,0,0) || r->oflags.hob_all || r->iflags.hob_all) {
459 tf.is_lba48 = 1;
460 if (r->oflags.hob.feat) tf.hob.feat = r->hob.feat;
461 if (r->oflags.hob.lbal) tf.hob.lbal = r->hob.lbal;
462 if (r->oflags.hob.nsect)tf.hob.nsect = r->hob.nsect;
463 if (r->oflags.hob.lbam) tf.hob.lbam = r->hob.lbam;
464 if (r->oflags.hob.lbah) tf.hob.lbah = r->hob.lbah;
465 if (verbose)
466 fprintf(stderr, "using LBA48 taskfile\n");
468 switch (r->cmd_req) {
469 case TASKFILE_CMD_REQ_OUT:
470 case TASKFILE_CMD_REQ_RAW_OUT:
471 data_bytes = r->obytes;
472 data = r->data;
473 rw = SG_WRITE;
474 break;
475 case TASKFILE_CMD_REQ_IN:
476 data_bytes = r->ibytes;
477 data = r->data;
478 break;
481 rc = sg16(fd, rw, is_dma(tf.command), &tf, data, data_bytes, timeout_secs);
482 if (rc == -1) {
483 if (errno == EINVAL || errno == ENODEV || errno == EBADE)
484 goto use_legacy_ioctl;
487 if (rc == 0 || errno == EIO) {
488 if (r->iflags.lob.feat) r->lob.feat = tf.error;
489 if (r->iflags.lob.lbal) r->lob.lbal = tf.lob.lbal;
490 if (r->iflags.lob.nsect) r->lob.nsect = tf.lob.nsect;
491 if (r->iflags.lob.lbam) r->lob.lbam = tf.lob.lbam;
492 if (r->iflags.lob.lbah) r->lob.lbah = tf.lob.lbah;
493 if (r->iflags.lob.dev) r->lob.dev = tf.dev;
494 if (r->iflags.lob.command) r->lob.command = tf.status;
495 if (r->iflags.hob.feat) r->hob.feat = tf.hob.feat;
496 if (r->iflags.hob.lbal) r->hob.lbal = tf.hob.lbal;
497 if (r->iflags.hob.nsect) r->hob.nsect = tf.hob.nsect;
498 if (r->iflags.hob.lbam) r->hob.lbam = tf.hob.lbam;
499 if (r->iflags.hob.lbah) r->hob.lbah = tf.hob.lbah;
501 return rc;
503 use_legacy_ioctl:
504 #else
505 timeout_secs = 0; /* keep compiler happy */
506 #endif /* SG_IO */
507 if (verbose)
508 fprintf(stderr, "trying legacy HDIO_DRIVE_TASKFILE\n");
509 errno = 0;
511 rc = ioctl(fd, HDIO_DRIVE_TASKFILE, r);
512 if (verbose) {
513 int err = errno;
514 fprintf(stderr, "rc=%d, errno=%d, returned ATA registers: ", rc, err);
515 if (r->iflags.lob.feat) fprintf(stderr, " er=%02x", r->lob.feat);
516 if (r->iflags.lob.nsect) fprintf(stderr, " ns=%02x", r->lob.nsect);
517 if (r->iflags.lob.lbal) fprintf(stderr, " ll=%02x", r->lob.lbal);
518 if (r->iflags.lob.lbam) fprintf(stderr, " lm=%02x", r->lob.lbam);
519 if (r->iflags.lob.lbah) fprintf(stderr, " lh=%02x", r->lob.lbah);
520 if (r->iflags.lob.dev) fprintf(stderr, " dh=%02x", r->lob.dev);
521 if (r->iflags.lob.command) fprintf(stderr, " st=%02x", r->lob.command);
522 if (r->iflags.hob.feat) fprintf(stderr, " err=%02x", r->hob.feat);
523 if (r->iflags.hob.nsect) fprintf(stderr, " err=%02x", r->hob.nsect);
524 if (r->iflags.hob.lbal) fprintf(stderr, " err=%02x", r->hob.lbal);
525 if (r->iflags.hob.lbam) fprintf(stderr, " err=%02x", r->hob.lbam);
526 if (r->iflags.hob.lbah) fprintf(stderr, " err=%02x", r->hob.lbah);
527 fprintf(stderr, "\n");
528 errno = err;
530 if (rc == -1 && errno == EINVAL) {
531 fprintf(stderr, "The running kernel lacks CONFIG_IDE_TASK_IOCTL support for this device.\n");
532 errno = EINVAL;
534 return rc;
537 void init_hdio_taskfile (struct hdio_taskfile *r, __u8 ata_op, int rw, int force_lba48,
538 __u64 lba, unsigned int nsect, int data_bytes)
540 memset(r, 0, sizeof(struct hdio_taskfile) + data_bytes);
541 if (!data_bytes) {
542 r->dphase = TASKFILE_DPHASE_NONE;
543 r->cmd_req = TASKFILE_CMD_REQ_NODATA;
544 } else if (rw == RW_WRITE) {
545 r->dphase = TASKFILE_DPHASE_PIO_OUT;
546 r->cmd_req = TASKFILE_CMD_REQ_RAW_OUT;
547 r->obytes = data_bytes;
548 } else { /* rw == RW_READ */
549 r->dphase = TASKFILE_DPHASE_PIO_IN;
550 r->cmd_req = TASKFILE_CMD_REQ_IN;
551 r->ibytes = data_bytes;
553 r->lob.command = ata_op;
554 r->oflags.lob.command = 1;
555 r->oflags.lob.dev = 1;
556 r->oflags.lob.lbal = 1;
557 r->oflags.lob.lbam = 1;
558 r->oflags.lob.lbah = 1;
559 r->oflags.lob.nsect = 1;
561 r->iflags.lob.command = 1;
562 r->iflags.lob.feat = 1;
564 r->lob.nsect = nsect;
565 r->lob.lbal = lba;
566 r->lob.lbam = lba >> 8;
567 r->lob.lbah = lba >> 16;
568 r->lob.dev = 0xa0 | ATA_USING_LBA;
570 if (needs_lba48(ata_op, lba, nsect) || force_lba48) {
571 r->hob.nsect = nsect >> 8;
572 r->hob.lbal = lba >> 24;
573 r->hob.lbam = lba >> 32;
574 r->hob.lbah = lba >> 40;
575 r->oflags.hob.nsect = 1;
576 r->oflags.hob.lbal = 1;
577 r->oflags.hob.lbam = 1;
578 r->oflags.hob.lbah = 1;
579 } else {
580 r->lob.dev |= (lba >> 24) & 0x0f;