• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
print_sg_io_buffer(struct tcb * tcp,unsigned char * addr,int len)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
print_sg_io_req(struct tcb * tcp,struct sg_io_hdr * sg_io)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
print_sg_io_res(struct tcb * tcp,struct sg_io_hdr * sg_io)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
scsi_ioctl(struct tcb * tcp,long code,long arg)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