Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 2007 Vladimir Nadvornik <nadvornik (at) suse.cz>
      3  * Copyright (c) 2007 Dmitry V. Levin <ldv (at) altlinux.org>
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. The name of the author may not be used to endorse or promote products
     15  *    derived from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include "defs.h"
     30 
     31 #ifdef HAVE_SCSI_SG_H
     32 
     33 # include <sys/ioctl.h>
     34 # include <scsi/sg.h>
     35 
     36 #include "xlat/sg_io_dxfer_direction.h"
     37 
     38 static void
     39 print_sg_io_buffer(struct tcb *tcp, unsigned char *addr, int len)
     40 {
     41 	unsigned char *buf = NULL;
     42 	int     allocated, i;
     43 
     44 	if (len == 0)
     45 		return;
     46 	allocated = (len > max_strlen) ? max_strlen : len;
     47 	if (len < 0 ||
     48 	    (buf = malloc(allocated)) == NULL ||
     49 	    umoven(tcp, (unsigned long) addr, allocated, (char *) buf) < 0) {
     50 		tprintf("%p", addr);
     51 		free(buf);
     52 		return;
     53 	}
     54 	tprintf("%02x", buf[0]);
     55 	for (i = 1; i < allocated; ++i)
     56 		tprintf(", %02x", buf[i]);
     57 	free(buf);
     58 	if (allocated != len)
     59 		tprints(", ...");
     60 }
     61 
     62 static void
     63 print_sg_io_req(struct tcb *tcp, struct sg_io_hdr *sg_io)
     64 {
     65 	tprintf("{'%c', ", sg_io->interface_id);
     66 	printxval(sg_io_dxfer_direction, sg_io->dxfer_direction,
     67 		  "SG_DXFER_???");
     68 	tprintf(", cmd[%u]=[", sg_io->cmd_len);
     69 	print_sg_io_buffer(tcp, sg_io->cmdp, sg_io->cmd_len);
     70 	tprintf("], mx_sb_len=%d, ", sg_io->mx_sb_len);
     71 	tprintf("iovec_count=%d, ", sg_io->iovec_count);
     72 	tprintf("dxfer_len=%u, ", sg_io->dxfer_len);
     73 	tprintf("timeout=%u, ", sg_io->timeout);
     74 	tprintf("flags=%#x", sg_io->flags);
     75 
     76 	if (sg_io->dxfer_direction == SG_DXFER_TO_DEV ||
     77 	    sg_io->dxfer_direction == SG_DXFER_TO_FROM_DEV) {
     78 		tprintf(", data[%u]=[", sg_io->dxfer_len);
     79 		printstr(tcp, (unsigned long) sg_io->dxferp,
     80 			 sg_io->dxfer_len);
     81 		tprints("]");
     82 	}
     83 }
     84 
     85 static void
     86 print_sg_io_res(struct tcb *tcp, struct sg_io_hdr *sg_io)
     87 {
     88 	if (sg_io->dxfer_direction == SG_DXFER_FROM_DEV ||
     89 	    sg_io->dxfer_direction == SG_DXFER_TO_FROM_DEV) {
     90 		tprintf(", data[%u]=[", sg_io->dxfer_len);
     91 		printstr(tcp, (unsigned long) sg_io->dxferp,
     92 			 sg_io->dxfer_len);
     93 		tprints("]");
     94 	}
     95 	tprintf(", status=%02x, ", sg_io->status);
     96 	tprintf("masked_status=%02x, ", sg_io->masked_status);
     97 	tprintf("sb[%u]=[", sg_io->sb_len_wr);
     98 	print_sg_io_buffer(tcp, sg_io->sbp, sg_io->sb_len_wr);
     99 	tprintf("], host_status=%#x, ", sg_io->host_status);
    100 	tprintf("driver_status=%#x, ", sg_io->driver_status);
    101 	tprintf("resid=%d, ", sg_io->resid);
    102 	tprintf("duration=%d, ", sg_io->duration);
    103 	tprintf("info=%#x}", sg_io->info);
    104 }
    105 
    106 int
    107 scsi_ioctl(struct tcb *tcp, long code, long arg)
    108 {
    109 	switch (code) {
    110 	case SG_IO:
    111 		if (entering(tcp)) {
    112 			struct sg_io_hdr sg_io;
    113 
    114 			if (umove(tcp, arg, &sg_io) < 0)
    115 				tprintf(", %#lx", arg);
    116 			else {
    117 				tprints(", ");
    118 				print_sg_io_req(tcp, &sg_io);
    119 			}
    120 		}
    121 		if (exiting(tcp)) {
    122 			struct sg_io_hdr sg_io;
    123 
    124 			if (!syserror(tcp) && umove(tcp, arg, &sg_io) >= 0)
    125 				print_sg_io_res(tcp, &sg_io);
    126 			else
    127 				tprints("}");
    128 		}
    129 		break;
    130 	default:
    131 		if (entering(tcp))
    132 			tprintf(", %#lx", arg);
    133 		break;
    134 	}
    135 	return 1;
    136 }
    137 
    138 #endif /* HAVE_SCSI_SG_H */
    139