Home | History | Annotate | Download | only in strace
      1 #include "defs.h"
      2 
      3 #ifdef LINUX
      4 #include <sys/ioctl.h>
      5 #include <scsi/sg.h>
      6 
      7 static const struct xlat sg_io_dxfer_direction[] = {
      8 	{SG_DXFER_NONE,        "SG_DXFER_NONE"},
      9 	{SG_DXFER_TO_DEV,      "SG_DXFER_TO_DEV"},
     10 	{SG_DXFER_FROM_DEV,    "SG_DXFER_FROM_DEV"},
     11 	{SG_DXFER_TO_FROM_DEV, "SG_DXFER_TO_FROM_DEV"},
     12 	{0, NULL}
     13 };
     14 
     15 static void
     16 print_sg_io_buffer(struct tcb *tcp, unsigned char *addr, int len)
     17 {
     18 	unsigned char *buf = NULL;
     19 	int     allocated, i;
     20 
     21 	if (len == 0)
     22 		return;
     23 	allocated = (len > max_strlen) ? max_strlen : len;
     24 	if (len < 0 ||
     25 	    (buf = malloc(allocated)) == NULL ||
     26 	    umoven(tcp, (unsigned long) addr, allocated, (char *) buf) < 0) {
     27 		tprintf("%p", addr);
     28 		free(buf);
     29 		return;
     30 	}
     31 	tprintf("%02x", buf[0]);
     32 	for (i = 1; i < allocated; ++i)
     33 		tprintf(", %02x", buf[i]);
     34 	free(buf);
     35 	if (allocated != len)
     36 		tprintf(", ...");
     37 }
     38 
     39 static void
     40 print_sg_io_req(struct tcb *tcp, struct sg_io_hdr *sg_io)
     41 {
     42 	tprintf("{'%c', ", sg_io->interface_id);
     43 	printxval(sg_io_dxfer_direction, sg_io->dxfer_direction,
     44 		  "SG_DXFER_???");
     45 	tprintf(", cmd[%u]=[", sg_io->cmd_len);
     46 	print_sg_io_buffer(tcp, sg_io->cmdp, sg_io->cmd_len);
     47 	tprintf("], mx_sb_len=%d, ", sg_io->mx_sb_len);
     48 	tprintf("iovec_count=%d, ", sg_io->iovec_count);
     49 	tprintf("dxfer_len=%u, ", sg_io->dxfer_len);
     50 	tprintf("timeout=%u, ", sg_io->timeout);
     51 	tprintf("flags=%#x", sg_io->flags);
     52 
     53 	if (sg_io->dxfer_direction == SG_DXFER_TO_DEV ||
     54 	    sg_io->dxfer_direction == SG_DXFER_TO_FROM_DEV) {
     55 		tprintf(", data[%u]=[", sg_io->dxfer_len);
     56 		printstr(tcp, (unsigned long) sg_io->dxferp,
     57 			 sg_io->dxfer_len);
     58 		tprintf("]");
     59 	}
     60 }
     61 
     62 static void
     63 print_sg_io_res(struct tcb *tcp, struct sg_io_hdr *sg_io)
     64 {
     65 	if (sg_io->dxfer_direction == SG_DXFER_FROM_DEV ||
     66 	    sg_io->dxfer_direction == SG_DXFER_TO_FROM_DEV) {
     67 		tprintf(", data[%u]=[", sg_io->dxfer_len);
     68 		printstr(tcp, (unsigned long) sg_io->dxferp,
     69 			 sg_io->dxfer_len);
     70 		tprintf("]");
     71 	}
     72 	tprintf(", status=%02x, ", sg_io->status);
     73 	tprintf("masked_status=%02x, ", sg_io->masked_status);
     74 	tprintf("sb[%u]=[", sg_io->sb_len_wr);
     75 	print_sg_io_buffer(tcp, sg_io->sbp, sg_io->sb_len_wr);
     76 	tprintf("], host_status=%#x, ", sg_io->host_status);
     77 	tprintf("driver_status=%#x, ", sg_io->driver_status);
     78 	tprintf("resid=%d, ", sg_io->resid);
     79 	tprintf("duration=%d, ", sg_io->duration);
     80 	tprintf("info=%#x}", sg_io->info);
     81 }
     82 
     83 int
     84 scsi_ioctl(struct tcb *tcp, long code, long arg)
     85 {
     86 	switch (code) {
     87 	case SG_IO:
     88 		if (entering(tcp)) {
     89 			struct sg_io_hdr sg_io;
     90 
     91 			if (umove(tcp, arg, &sg_io) < 0)
     92 				tprintf(", %#lx", arg);
     93 			else {
     94 				tprintf(", ");
     95 				print_sg_io_req(tcp, &sg_io);
     96 			}
     97 		}
     98 		if (exiting(tcp)) {
     99 			struct sg_io_hdr sg_io;
    100 
    101 			if (!syserror(tcp) && umove(tcp, arg, &sg_io) >= 0)
    102 				print_sg_io_res(tcp, &sg_io);
    103 			else
    104 				tprintf("}");
    105 		}
    106 		break;
    107 	default:
    108 		if (entering(tcp))
    109 			tprintf(", %#lx", arg);
    110 		break;
    111 	}
    112 	return 1;
    113 }
    114 #endif /* LINUX */
    115