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