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