1f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#include "defs.h" 2f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown 3f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#ifdef LINUX 4f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#include <sys/ioctl.h> 5f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#include <scsi/sg.h> 6f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown 7f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic const struct xlat sg_io_dxfer_direction[] = { 8f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown {SG_DXFER_NONE, "SG_DXFER_NONE"}, 9f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown {SG_DXFER_TO_DEV, "SG_DXFER_TO_DEV"}, 10f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown {SG_DXFER_FROM_DEV, "SG_DXFER_FROM_DEV"}, 11f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown {SG_DXFER_TO_FROM_DEV, "SG_DXFER_TO_FROM_DEV"}, 12f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown {0, NULL} 13f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown}; 14f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown 15f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void 16f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownprint_sg_io_buffer(struct tcb *tcp, unsigned char *addr, int len) 17f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{ 18f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown unsigned char *buf = NULL; 19f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown int allocated, i; 20f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown 21f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown if (len == 0) 22f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown return; 23f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown allocated = (len > max_strlen) ? max_strlen : len; 24f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown if (len < 0 || 25f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown (buf = malloc(allocated)) == NULL || 26f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown umoven(tcp, (unsigned long) addr, allocated, (char *) buf) < 0) { 27f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("%p", addr); 28f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown free(buf); 29f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown return; 30f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown } 31f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("%02x", buf[0]); 32f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown for (i = 1; i < allocated; ++i) 33f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf(", %02x", buf[i]); 34f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown free(buf); 35f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown if (allocated != len) 36f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf(", ..."); 37f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown} 38f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown 39f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void 40f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownprint_sg_io_req(struct tcb *tcp, struct sg_io_hdr *sg_io) 41f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{ 42f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("{'%c', ", sg_io->interface_id); 43f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown printxval(sg_io_dxfer_direction, sg_io->dxfer_direction, 44f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown "SG_DXFER_???"); 45f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf(", cmd[%u]=[", sg_io->cmd_len); 46f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown print_sg_io_buffer(tcp, sg_io->cmdp, sg_io->cmd_len); 47f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("], mx_sb_len=%d, ", sg_io->mx_sb_len); 48f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("iovec_count=%d, ", sg_io->iovec_count); 49f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("dxfer_len=%u, ", sg_io->dxfer_len); 50f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("timeout=%u, ", sg_io->timeout); 51f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("flags=%#x", sg_io->flags); 52f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown 53f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown if (sg_io->dxfer_direction == SG_DXFER_TO_DEV || 54f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown sg_io->dxfer_direction == SG_DXFER_TO_FROM_DEV) { 55f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf(", data[%u]=[", sg_io->dxfer_len); 56f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown printstr(tcp, (unsigned long) sg_io->dxferp, 57f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown sg_io->dxfer_len); 58f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("]"); 59f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown } 60f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown} 61f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown 62f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownstatic void 63f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownprint_sg_io_res(struct tcb *tcp, struct sg_io_hdr *sg_io) 64f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{ 65f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown if (sg_io->dxfer_direction == SG_DXFER_FROM_DEV || 66f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown sg_io->dxfer_direction == SG_DXFER_TO_FROM_DEV) { 67f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf(", data[%u]=[", sg_io->dxfer_len); 68f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown printstr(tcp, (unsigned long) sg_io->dxferp, 69f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown sg_io->dxfer_len); 70f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("]"); 71f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown } 72f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf(", status=%02x, ", sg_io->status); 73f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("masked_status=%02x, ", sg_io->masked_status); 74f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("sb[%u]=[", sg_io->sb_len_wr); 75f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown print_sg_io_buffer(tcp, sg_io->sbp, sg_io->sb_len_wr); 76f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("], host_status=%#x, ", sg_io->host_status); 77f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("driver_status=%#x, ", sg_io->driver_status); 78f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("resid=%d, ", sg_io->resid); 79f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("duration=%d, ", sg_io->duration); 80f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("info=%#x}", sg_io->info); 81f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown} 82f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown 83f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownint 84f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brownscsi_ioctl(struct tcb *tcp, long code, long arg) 85f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown{ 86f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown switch (code) { 87f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown case SG_IO: 88f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown if (entering(tcp)) { 89f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown struct sg_io_hdr sg_io; 90f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown 91f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown if (umove(tcp, arg, &sg_io) < 0) 92f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf(", %#lx", arg); 93f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown else { 94f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf(", "); 95f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown print_sg_io_req(tcp, &sg_io); 96f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown } 97f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown } 98f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown if (exiting(tcp)) { 99f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown struct sg_io_hdr sg_io; 100f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown 101f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown if (!syserror(tcp) && umove(tcp, arg, &sg_io) >= 0) 102f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown print_sg_io_res(tcp, &sg_io); 103f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown else 104f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf("}"); 105f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown } 106f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown break; 107f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown default: 108f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown if (entering(tcp)) 109f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown tprintf(", %#lx", arg); 110f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown break; 111f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown } 112f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown return 1; 113f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown} 114f76f96e20f766e6bb91593885b1e800f8bc14a52Jeff Brown#endif /* LINUX */ 115