Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 2007 Vladimir Nadvornik <nadvornik (at) suse.cz>
      3  * Copyright (c) 2007-2017 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 # include <scsi/sg.h>
     33 #endif
     34 
     35 #include "xlat/scsi_sg_commands.h"
     36 #include "xlat/sg_scsi_reset.h"
     37 
     38 static int
     39 decode_sg_io(struct tcb *const tcp, const uint32_t iid,
     40 	     const kernel_ulong_t arg)
     41 {
     42 	switch (iid) {
     43 		case 'S':
     44 			return decode_sg_io_v3(tcp, arg);
     45 		case 'Q':
     46 			return decode_sg_io_v4(tcp, arg);
     47 		default:
     48 			tprintf("[%u]", iid);
     49 			return RVAL_IOCTL_DECODED;
     50 	}
     51 
     52 }
     53 
     54 #ifdef HAVE_SCSI_SG_H
     55 
     56 static int
     57 decode_sg_scsi_id(struct tcb *const tcp, const kernel_ulong_t arg)
     58 {
     59 	struct sg_scsi_id id;
     60 
     61 	if (entering(tcp))
     62 		return 0;
     63 
     64 	tprints(", ");
     65 	if (!umove_or_printaddr(tcp, arg, &id)) {
     66 		tprintf("{host_no=%d"
     67 			", channel=%d"
     68 			", scsi_id=%#x"
     69 			", lun=%d"
     70 			", scsi_type=%#x"
     71 			", h_cmd_per_lun=%hd"
     72 			", d_queue_depth=%hd}",
     73 			id.host_no,
     74 			id.channel,
     75 			id.scsi_id,
     76 			id.lun,
     77 			id.scsi_type,
     78 			id.h_cmd_per_lun,
     79 			id.d_queue_depth);
     80 	}
     81 	return RVAL_IOCTL_DECODED;
     82 }
     83 
     84 #endif /* HAVE_SCSI_SG_H */
     85 
     86 int
     87 scsi_ioctl(struct tcb *const tcp, const unsigned int code,
     88 	   const kernel_ulong_t arg)
     89 {
     90 	switch (code) {
     91 	case SG_IO:
     92 		if (entering(tcp)) {
     93 			uint32_t iid;
     94 
     95 			tprints(", ");
     96 			if (umove_or_printaddr(tcp, arg, &iid)) {
     97 				break;
     98 			} else {
     99 				return decode_sg_io(tcp, iid, arg);
    100 			}
    101 		} else {
    102 			uint32_t *piid = get_tcb_priv_data(tcp);
    103 			if (piid)
    104 				decode_sg_io(tcp, *piid, arg);
    105 			tprints("}");
    106 			break;
    107 		}
    108 
    109 #ifdef HAVE_SCSI_SG_H
    110 	/* returns struct sg_scsi_id */
    111 	case SG_GET_SCSI_ID:
    112 		return decode_sg_scsi_id(tcp, arg);
    113 	/* returns struct sg_req_info */
    114 	case SG_GET_REQUEST_TABLE:
    115 		return decode_sg_req_info(tcp, arg);
    116 #endif /* HAVE_SCSI_SG_H */
    117 
    118 	/* takes a value by pointer */
    119 	case SG_SCSI_RESET: {
    120 		unsigned int val;
    121 		tprints(", ");
    122 		if (!umove_or_printaddr(tcp, arg, &val)) {
    123 			tprints("[");
    124 			if (val & SG_SCSI_RESET_NO_ESCALATE) {
    125 				printxval(sg_scsi_reset,
    126 					  SG_SCSI_RESET_NO_ESCALATE, 0);
    127 				tprints("|");
    128 			}
    129 			printxval(sg_scsi_reset,
    130 				  val & ~SG_SCSI_RESET_NO_ESCALATE,
    131 				  "SG_SCSI_RESET_???");
    132 			tprints("]");
    133 
    134 		}
    135 		break;
    136 	}
    137 
    138 	/* takes a signed int by pointer */
    139 	case SG_NEXT_CMD_LEN:
    140 	case SG_SET_COMMAND_Q:
    141 	case SG_SET_DEBUG:
    142 	case SG_SET_FORCE_LOW_DMA:
    143 	case SG_SET_FORCE_PACK_ID:
    144 	case SG_SET_KEEP_ORPHAN:
    145 	case SG_SET_RESERVED_SIZE:
    146 	case SG_SET_TIMEOUT:
    147 		tprints(", ");
    148 		printnum_int(tcp, arg, "%d");
    149 		break;
    150 
    151 	/* returns a signed int by pointer */
    152 	case SG_EMULATED_HOST:
    153 	case SG_GET_ACCESS_COUNT:
    154 	case SG_GET_COMMAND_Q:
    155 	case SG_GET_KEEP_ORPHAN:
    156 	case SG_GET_LOW_DMA:
    157 	case SG_GET_NUM_WAITING:
    158 	case SG_GET_PACK_ID:
    159 	case SG_GET_RESERVED_SIZE:
    160 	case SG_GET_SG_TABLESIZE:
    161 	case SG_GET_TRANSFORM:
    162 	case SG_GET_VERSION_NUM:
    163 		if (entering(tcp))
    164 			return 0;
    165 		tprints(", ");
    166 		printnum_int(tcp, arg, "%d");
    167 		break;
    168 
    169 	/* takes an integer by value */
    170 	case SG_SET_TRANSFORM:
    171 		tprintf(", %#x", (unsigned int) arg);
    172 		break;
    173 
    174 	/* no arguments */
    175 	case SG_GET_TIMEOUT:
    176 		break;
    177 
    178 	default:
    179 		return RVAL_DECODED;
    180 	}
    181 
    182 	return RVAL_IOCTL_DECODED;
    183 }
    184