(root)/
strace-6.5/
src/
scsi.c
       1  /*
       2   * Copyright (c) 2007 Vladimir Nadvornik <nadvornik@suse.cz>
       3   * Copyright (c) 2007-2018 Dmitry V. Levin <ldv@strace.io>
       4   * Copyright (c) 2007-2022 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: LGPL-2.1-or-later
       8   */
       9  
      10  #include "defs.h"
      11  
      12  #ifdef HAVE_SCSI_SG_H
      13  # include <scsi/sg.h>
      14  #endif
      15  
      16  #define XLAT_MACROS_ONLY
      17  # include "xlat/scsi_sg_commands.h"
      18  #undef XLAT_MACROS_ONLY
      19  #include "xlat/sg_scsi_reset.h"
      20  
      21  static int
      22  decode_sg_io(struct tcb *const tcp, const uint32_t iid,
      23  	     const kernel_ulong_t arg)
      24  {
      25  	switch (iid) {
      26  		case 'S':
      27  			return decode_sg_io_v3(tcp, arg);
      28  		case 'Q':
      29  			return decode_sg_io_v4(tcp, arg);
      30  		default:
      31  			tprint_indirect_begin();
      32  			PRINT_VAL_U(iid);
      33  			tprint_indirect_end();
      34  			return RVAL_IOCTL_DECODED;
      35  	}
      36  
      37  }
      38  
      39  #ifdef HAVE_SCSI_SG_H
      40  
      41  static int
      42  decode_sg_scsi_id(struct tcb *const tcp, const kernel_ulong_t arg)
      43  {
      44  	struct sg_scsi_id id;
      45  
      46  	if (entering(tcp))
      47  		return 0;
      48  
      49  	tprint_arg_next();
      50  	if (!umove_or_printaddr(tcp, arg, &id)) {
      51  		tprint_struct_begin();
      52  		PRINT_FIELD_D(id, host_no);
      53  		tprint_struct_next();
      54  		PRINT_FIELD_D(id, channel);
      55  		tprint_struct_next();
      56  		PRINT_FIELD_X(id, scsi_id);
      57  		tprint_struct_next();
      58  		PRINT_FIELD_D(id, lun);
      59  		tprint_struct_next();
      60  		PRINT_FIELD_X(id, scsi_type);
      61  		tprint_struct_next();
      62  		PRINT_FIELD_D(id, h_cmd_per_lun);
      63  		tprint_struct_next();
      64  		PRINT_FIELD_D(id, d_queue_depth);
      65  		tprint_struct_end();
      66  	}
      67  	return RVAL_IOCTL_DECODED;
      68  }
      69  
      70  #endif /* HAVE_SCSI_SG_H */
      71  
      72  int
      73  scsi_ioctl(struct tcb *const tcp, const unsigned int code,
      74  	   const kernel_ulong_t arg)
      75  {
      76  	switch (code) {
      77  	case SG_IO:
      78  		if (entering(tcp)) {
      79  			uint32_t iid;
      80  
      81  			tprint_arg_next();
      82  			if (umove_or_printaddr(tcp, arg, &iid)) {
      83  				break;
      84  			} else {
      85  				return decode_sg_io(tcp, iid, arg);
      86  			}
      87  		} else {
      88  			uint32_t *piid = get_tcb_priv_data(tcp);
      89  			if (piid)
      90  				decode_sg_io(tcp, *piid, arg);
      91  			tprint_struct_end();
      92  			break;
      93  		}
      94  
      95  #ifdef HAVE_SCSI_SG_H
      96  	/* returns struct sg_scsi_id */
      97  	case SG_GET_SCSI_ID:
      98  		return decode_sg_scsi_id(tcp, arg);
      99  	/* returns struct sg_req_info */
     100  	case SG_GET_REQUEST_TABLE:
     101  		return decode_sg_req_info(tcp, arg);
     102  #endif /* HAVE_SCSI_SG_H */
     103  
     104  	/* takes a value by pointer */
     105  	case SG_SCSI_RESET: {
     106  		unsigned int val;
     107  		tprint_arg_next();
     108  		if (!umove_or_printaddr(tcp, arg, &val)) {
     109  			tprint_indirect_begin();
     110  			tprint_flags_begin();
     111  			if (val & SG_SCSI_RESET_NO_ESCALATE) {
     112  				printxval(sg_scsi_reset,
     113  					  SG_SCSI_RESET_NO_ESCALATE, 0);
     114  				tprint_flags_or();
     115  			}
     116  			printxval(sg_scsi_reset,
     117  				  val & ~SG_SCSI_RESET_NO_ESCALATE,
     118  				  "SG_SCSI_RESET_???");
     119  			tprint_flags_end();
     120  			tprint_indirect_end();
     121  
     122  		}
     123  		break;
     124  	}
     125  
     126  	/* takes a signed int by pointer */
     127  	case SG_NEXT_CMD_LEN:
     128  	case SG_SET_COMMAND_Q:
     129  	case SG_SET_DEBUG:
     130  	case SG_SET_FORCE_LOW_DMA:
     131  	case SG_SET_FORCE_PACK_ID:
     132  	case SG_SET_KEEP_ORPHAN:
     133  	case SG_SET_RESERVED_SIZE:
     134  	case SG_SET_TIMEOUT:
     135  		tprint_arg_next();
     136  		printnum_int(tcp, arg, "%d");
     137  		break;
     138  
     139  	/* returns a signed int by pointer */
     140  	case SG_EMULATED_HOST:
     141  	case SG_GET_ACCESS_COUNT:
     142  	case SG_GET_COMMAND_Q:
     143  	case SG_GET_KEEP_ORPHAN:
     144  	case SG_GET_LOW_DMA:
     145  	case SG_GET_NUM_WAITING:
     146  	case SG_GET_PACK_ID:
     147  	case SG_GET_RESERVED_SIZE:
     148  	case SG_GET_SG_TABLESIZE:
     149  	case SG_GET_TRANSFORM:
     150  	case SG_GET_VERSION_NUM:
     151  		if (entering(tcp))
     152  			return 0;
     153  		tprint_arg_next();
     154  		printnum_int(tcp, arg, "%d");
     155  		break;
     156  
     157  	/* takes an integer by value */
     158  	case SG_SET_TRANSFORM:
     159  		tprint_arg_next();
     160  		PRINT_VAL_X((unsigned int) arg);
     161  		break;
     162  
     163  	/* no arguments */
     164  	case SG_GET_TIMEOUT:
     165  		break;
     166  
     167  	default:
     168  		return RVAL_DECODED;
     169  	}
     170  
     171  	return RVAL_IOCTL_DECODED;
     172  }