1*49ab747fSPaolo Bonzini /* 2*49ab747fSPaolo Bonzini * Generic SCSI Device support 3*49ab747fSPaolo Bonzini * 4*49ab747fSPaolo Bonzini * Copyright (c) 2007 Bull S.A.S. 5*49ab747fSPaolo Bonzini * Based on code by Paul Brook 6*49ab747fSPaolo Bonzini * Based on code by Fabrice Bellard 7*49ab747fSPaolo Bonzini * 8*49ab747fSPaolo Bonzini * Written by Laurent Vivier <Laurent.Vivier@bull.net> 9*49ab747fSPaolo Bonzini * 10*49ab747fSPaolo Bonzini * This code is licensed under the LGPL. 11*49ab747fSPaolo Bonzini * 12*49ab747fSPaolo Bonzini */ 13*49ab747fSPaolo Bonzini 14*49ab747fSPaolo Bonzini #include "qemu-common.h" 15*49ab747fSPaolo Bonzini #include "qemu/error-report.h" 16*49ab747fSPaolo Bonzini #include "hw/scsi/scsi.h" 17*49ab747fSPaolo Bonzini #include "sysemu/blockdev.h" 18*49ab747fSPaolo Bonzini 19*49ab747fSPaolo Bonzini #ifdef __linux__ 20*49ab747fSPaolo Bonzini 21*49ab747fSPaolo Bonzini //#define DEBUG_SCSI 22*49ab747fSPaolo Bonzini 23*49ab747fSPaolo Bonzini #ifdef DEBUG_SCSI 24*49ab747fSPaolo Bonzini #define DPRINTF(fmt, ...) \ 25*49ab747fSPaolo Bonzini do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0) 26*49ab747fSPaolo Bonzini #else 27*49ab747fSPaolo Bonzini #define DPRINTF(fmt, ...) do {} while(0) 28*49ab747fSPaolo Bonzini #endif 29*49ab747fSPaolo Bonzini 30*49ab747fSPaolo Bonzini #define BADF(fmt, ...) \ 31*49ab747fSPaolo Bonzini do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0) 32*49ab747fSPaolo Bonzini 33*49ab747fSPaolo Bonzini #include <stdio.h> 34*49ab747fSPaolo Bonzini #include <sys/types.h> 35*49ab747fSPaolo Bonzini #include <sys/stat.h> 36*49ab747fSPaolo Bonzini #include <unistd.h> 37*49ab747fSPaolo Bonzini #include <scsi/sg.h> 38*49ab747fSPaolo Bonzini #include "block/scsi.h" 39*49ab747fSPaolo Bonzini 40*49ab747fSPaolo Bonzini #define SCSI_SENSE_BUF_SIZE 96 41*49ab747fSPaolo Bonzini 42*49ab747fSPaolo Bonzini #define SG_ERR_DRIVER_TIMEOUT 0x06 43*49ab747fSPaolo Bonzini #define SG_ERR_DRIVER_SENSE 0x08 44*49ab747fSPaolo Bonzini 45*49ab747fSPaolo Bonzini #define SG_ERR_DID_OK 0x00 46*49ab747fSPaolo Bonzini #define SG_ERR_DID_NO_CONNECT 0x01 47*49ab747fSPaolo Bonzini #define SG_ERR_DID_BUS_BUSY 0x02 48*49ab747fSPaolo Bonzini #define SG_ERR_DID_TIME_OUT 0x03 49*49ab747fSPaolo Bonzini 50*49ab747fSPaolo Bonzini #ifndef MAX_UINT 51*49ab747fSPaolo Bonzini #define MAX_UINT ((unsigned int)-1) 52*49ab747fSPaolo Bonzini #endif 53*49ab747fSPaolo Bonzini 54*49ab747fSPaolo Bonzini typedef struct SCSIGenericReq { 55*49ab747fSPaolo Bonzini SCSIRequest req; 56*49ab747fSPaolo Bonzini uint8_t *buf; 57*49ab747fSPaolo Bonzini int buflen; 58*49ab747fSPaolo Bonzini int len; 59*49ab747fSPaolo Bonzini sg_io_hdr_t io_header; 60*49ab747fSPaolo Bonzini } SCSIGenericReq; 61*49ab747fSPaolo Bonzini 62*49ab747fSPaolo Bonzini static void scsi_generic_save_request(QEMUFile *f, SCSIRequest *req) 63*49ab747fSPaolo Bonzini { 64*49ab747fSPaolo Bonzini SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); 65*49ab747fSPaolo Bonzini 66*49ab747fSPaolo Bonzini qemu_put_sbe32s(f, &r->buflen); 67*49ab747fSPaolo Bonzini if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) { 68*49ab747fSPaolo Bonzini assert(!r->req.sg); 69*49ab747fSPaolo Bonzini qemu_put_buffer(f, r->buf, r->req.cmd.xfer); 70*49ab747fSPaolo Bonzini } 71*49ab747fSPaolo Bonzini } 72*49ab747fSPaolo Bonzini 73*49ab747fSPaolo Bonzini static void scsi_generic_load_request(QEMUFile *f, SCSIRequest *req) 74*49ab747fSPaolo Bonzini { 75*49ab747fSPaolo Bonzini SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); 76*49ab747fSPaolo Bonzini 77*49ab747fSPaolo Bonzini qemu_get_sbe32s(f, &r->buflen); 78*49ab747fSPaolo Bonzini if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) { 79*49ab747fSPaolo Bonzini assert(!r->req.sg); 80*49ab747fSPaolo Bonzini qemu_get_buffer(f, r->buf, r->req.cmd.xfer); 81*49ab747fSPaolo Bonzini } 82*49ab747fSPaolo Bonzini } 83*49ab747fSPaolo Bonzini 84*49ab747fSPaolo Bonzini static void scsi_free_request(SCSIRequest *req) 85*49ab747fSPaolo Bonzini { 86*49ab747fSPaolo Bonzini SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); 87*49ab747fSPaolo Bonzini 88*49ab747fSPaolo Bonzini g_free(r->buf); 89*49ab747fSPaolo Bonzini } 90*49ab747fSPaolo Bonzini 91*49ab747fSPaolo Bonzini /* Helper function for command completion. */ 92*49ab747fSPaolo Bonzini static void scsi_command_complete(void *opaque, int ret) 93*49ab747fSPaolo Bonzini { 94*49ab747fSPaolo Bonzini int status; 95*49ab747fSPaolo Bonzini SCSIGenericReq *r = (SCSIGenericReq *)opaque; 96*49ab747fSPaolo Bonzini 97*49ab747fSPaolo Bonzini r->req.aiocb = NULL; 98*49ab747fSPaolo Bonzini if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) { 99*49ab747fSPaolo Bonzini r->req.sense_len = r->io_header.sb_len_wr; 100*49ab747fSPaolo Bonzini } 101*49ab747fSPaolo Bonzini 102*49ab747fSPaolo Bonzini if (ret != 0) { 103*49ab747fSPaolo Bonzini switch (ret) { 104*49ab747fSPaolo Bonzini case -EDOM: 105*49ab747fSPaolo Bonzini status = TASK_SET_FULL; 106*49ab747fSPaolo Bonzini break; 107*49ab747fSPaolo Bonzini case -ENOMEM: 108*49ab747fSPaolo Bonzini status = CHECK_CONDITION; 109*49ab747fSPaolo Bonzini scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE)); 110*49ab747fSPaolo Bonzini break; 111*49ab747fSPaolo Bonzini default: 112*49ab747fSPaolo Bonzini status = CHECK_CONDITION; 113*49ab747fSPaolo Bonzini scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR)); 114*49ab747fSPaolo Bonzini break; 115*49ab747fSPaolo Bonzini } 116*49ab747fSPaolo Bonzini } else { 117*49ab747fSPaolo Bonzini if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT || 118*49ab747fSPaolo Bonzini r->io_header.host_status == SG_ERR_DID_BUS_BUSY || 119*49ab747fSPaolo Bonzini r->io_header.host_status == SG_ERR_DID_TIME_OUT || 120*49ab747fSPaolo Bonzini (r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) { 121*49ab747fSPaolo Bonzini status = BUSY; 122*49ab747fSPaolo Bonzini BADF("Driver Timeout\n"); 123*49ab747fSPaolo Bonzini } else if (r->io_header.host_status) { 124*49ab747fSPaolo Bonzini status = CHECK_CONDITION; 125*49ab747fSPaolo Bonzini scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS)); 126*49ab747fSPaolo Bonzini } else if (r->io_header.status) { 127*49ab747fSPaolo Bonzini status = r->io_header.status; 128*49ab747fSPaolo Bonzini } else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) { 129*49ab747fSPaolo Bonzini status = CHECK_CONDITION; 130*49ab747fSPaolo Bonzini } else { 131*49ab747fSPaolo Bonzini status = GOOD; 132*49ab747fSPaolo Bonzini } 133*49ab747fSPaolo Bonzini } 134*49ab747fSPaolo Bonzini DPRINTF("Command complete 0x%p tag=0x%x status=%d\n", 135*49ab747fSPaolo Bonzini r, r->req.tag, status); 136*49ab747fSPaolo Bonzini 137*49ab747fSPaolo Bonzini scsi_req_complete(&r->req, status); 138*49ab747fSPaolo Bonzini if (!r->req.io_canceled) { 139*49ab747fSPaolo Bonzini scsi_req_unref(&r->req); 140*49ab747fSPaolo Bonzini } 141*49ab747fSPaolo Bonzini } 142*49ab747fSPaolo Bonzini 143*49ab747fSPaolo Bonzini /* Cancel a pending data transfer. */ 144*49ab747fSPaolo Bonzini static void scsi_cancel_io(SCSIRequest *req) 145*49ab747fSPaolo Bonzini { 146*49ab747fSPaolo Bonzini SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); 147*49ab747fSPaolo Bonzini 148*49ab747fSPaolo Bonzini DPRINTF("Cancel tag=0x%x\n", req->tag); 149*49ab747fSPaolo Bonzini if (r->req.aiocb) { 150*49ab747fSPaolo Bonzini bdrv_aio_cancel(r->req.aiocb); 151*49ab747fSPaolo Bonzini 152*49ab747fSPaolo Bonzini /* This reference was left in by scsi_*_data. We take ownership of 153*49ab747fSPaolo Bonzini * it independent of whether bdrv_aio_cancel completes the request 154*49ab747fSPaolo Bonzini * or not. */ 155*49ab747fSPaolo Bonzini scsi_req_unref(&r->req); 156*49ab747fSPaolo Bonzini } 157*49ab747fSPaolo Bonzini r->req.aiocb = NULL; 158*49ab747fSPaolo Bonzini } 159*49ab747fSPaolo Bonzini 160*49ab747fSPaolo Bonzini static int execute_command(BlockDriverState *bdrv, 161*49ab747fSPaolo Bonzini SCSIGenericReq *r, int direction, 162*49ab747fSPaolo Bonzini BlockDriverCompletionFunc *complete) 163*49ab747fSPaolo Bonzini { 164*49ab747fSPaolo Bonzini r->io_header.interface_id = 'S'; 165*49ab747fSPaolo Bonzini r->io_header.dxfer_direction = direction; 166*49ab747fSPaolo Bonzini r->io_header.dxferp = r->buf; 167*49ab747fSPaolo Bonzini r->io_header.dxfer_len = r->buflen; 168*49ab747fSPaolo Bonzini r->io_header.cmdp = r->req.cmd.buf; 169*49ab747fSPaolo Bonzini r->io_header.cmd_len = r->req.cmd.len; 170*49ab747fSPaolo Bonzini r->io_header.mx_sb_len = sizeof(r->req.sense); 171*49ab747fSPaolo Bonzini r->io_header.sbp = r->req.sense; 172*49ab747fSPaolo Bonzini r->io_header.timeout = MAX_UINT; 173*49ab747fSPaolo Bonzini r->io_header.usr_ptr = r; 174*49ab747fSPaolo Bonzini r->io_header.flags |= SG_FLAG_DIRECT_IO; 175*49ab747fSPaolo Bonzini 176*49ab747fSPaolo Bonzini r->req.aiocb = bdrv_aio_ioctl(bdrv, SG_IO, &r->io_header, complete, r); 177*49ab747fSPaolo Bonzini 178*49ab747fSPaolo Bonzini return 0; 179*49ab747fSPaolo Bonzini } 180*49ab747fSPaolo Bonzini 181*49ab747fSPaolo Bonzini static void scsi_read_complete(void * opaque, int ret) 182*49ab747fSPaolo Bonzini { 183*49ab747fSPaolo Bonzini SCSIGenericReq *r = (SCSIGenericReq *)opaque; 184*49ab747fSPaolo Bonzini SCSIDevice *s = r->req.dev; 185*49ab747fSPaolo Bonzini int len; 186*49ab747fSPaolo Bonzini 187*49ab747fSPaolo Bonzini r->req.aiocb = NULL; 188*49ab747fSPaolo Bonzini if (ret) { 189*49ab747fSPaolo Bonzini DPRINTF("IO error ret %d\n", ret); 190*49ab747fSPaolo Bonzini scsi_command_complete(r, ret); 191*49ab747fSPaolo Bonzini return; 192*49ab747fSPaolo Bonzini } 193*49ab747fSPaolo Bonzini len = r->io_header.dxfer_len - r->io_header.resid; 194*49ab747fSPaolo Bonzini DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len); 195*49ab747fSPaolo Bonzini 196*49ab747fSPaolo Bonzini r->len = -1; 197*49ab747fSPaolo Bonzini if (len == 0) { 198*49ab747fSPaolo Bonzini scsi_command_complete(r, 0); 199*49ab747fSPaolo Bonzini } else { 200*49ab747fSPaolo Bonzini /* Snoop READ CAPACITY output to set the blocksize. */ 201*49ab747fSPaolo Bonzini if (r->req.cmd.buf[0] == READ_CAPACITY_10) { 202*49ab747fSPaolo Bonzini s->blocksize = ldl_be_p(&r->buf[4]); 203*49ab747fSPaolo Bonzini s->max_lba = ldl_be_p(&r->buf[0]); 204*49ab747fSPaolo Bonzini } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 && 205*49ab747fSPaolo Bonzini (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) { 206*49ab747fSPaolo Bonzini s->blocksize = ldl_be_p(&r->buf[8]); 207*49ab747fSPaolo Bonzini s->max_lba = ldq_be_p(&r->buf[0]); 208*49ab747fSPaolo Bonzini } 209*49ab747fSPaolo Bonzini bdrv_set_buffer_alignment(s->conf.bs, s->blocksize); 210*49ab747fSPaolo Bonzini 211*49ab747fSPaolo Bonzini scsi_req_data(&r->req, len); 212*49ab747fSPaolo Bonzini if (!r->req.io_canceled) { 213*49ab747fSPaolo Bonzini scsi_req_unref(&r->req); 214*49ab747fSPaolo Bonzini } 215*49ab747fSPaolo Bonzini } 216*49ab747fSPaolo Bonzini } 217*49ab747fSPaolo Bonzini 218*49ab747fSPaolo Bonzini /* Read more data from scsi device into buffer. */ 219*49ab747fSPaolo Bonzini static void scsi_read_data(SCSIRequest *req) 220*49ab747fSPaolo Bonzini { 221*49ab747fSPaolo Bonzini SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); 222*49ab747fSPaolo Bonzini SCSIDevice *s = r->req.dev; 223*49ab747fSPaolo Bonzini int ret; 224*49ab747fSPaolo Bonzini 225*49ab747fSPaolo Bonzini DPRINTF("scsi_read_data 0x%x\n", req->tag); 226*49ab747fSPaolo Bonzini 227*49ab747fSPaolo Bonzini /* The request is used as the AIO opaque value, so add a ref. */ 228*49ab747fSPaolo Bonzini scsi_req_ref(&r->req); 229*49ab747fSPaolo Bonzini if (r->len == -1) { 230*49ab747fSPaolo Bonzini scsi_command_complete(r, 0); 231*49ab747fSPaolo Bonzini return; 232*49ab747fSPaolo Bonzini } 233*49ab747fSPaolo Bonzini 234*49ab747fSPaolo Bonzini ret = execute_command(s->conf.bs, r, SG_DXFER_FROM_DEV, scsi_read_complete); 235*49ab747fSPaolo Bonzini if (ret < 0) { 236*49ab747fSPaolo Bonzini scsi_command_complete(r, ret); 237*49ab747fSPaolo Bonzini } 238*49ab747fSPaolo Bonzini } 239*49ab747fSPaolo Bonzini 240*49ab747fSPaolo Bonzini static void scsi_write_complete(void * opaque, int ret) 241*49ab747fSPaolo Bonzini { 242*49ab747fSPaolo Bonzini SCSIGenericReq *r = (SCSIGenericReq *)opaque; 243*49ab747fSPaolo Bonzini SCSIDevice *s = r->req.dev; 244*49ab747fSPaolo Bonzini 245*49ab747fSPaolo Bonzini DPRINTF("scsi_write_complete() ret = %d\n", ret); 246*49ab747fSPaolo Bonzini r->req.aiocb = NULL; 247*49ab747fSPaolo Bonzini if (ret) { 248*49ab747fSPaolo Bonzini DPRINTF("IO error\n"); 249*49ab747fSPaolo Bonzini scsi_command_complete(r, ret); 250*49ab747fSPaolo Bonzini return; 251*49ab747fSPaolo Bonzini } 252*49ab747fSPaolo Bonzini 253*49ab747fSPaolo Bonzini if (r->req.cmd.buf[0] == MODE_SELECT && r->req.cmd.buf[4] == 12 && 254*49ab747fSPaolo Bonzini s->type == TYPE_TAPE) { 255*49ab747fSPaolo Bonzini s->blocksize = (r->buf[9] << 16) | (r->buf[10] << 8) | r->buf[11]; 256*49ab747fSPaolo Bonzini DPRINTF("block size %d\n", s->blocksize); 257*49ab747fSPaolo Bonzini } 258*49ab747fSPaolo Bonzini 259*49ab747fSPaolo Bonzini scsi_command_complete(r, ret); 260*49ab747fSPaolo Bonzini } 261*49ab747fSPaolo Bonzini 262*49ab747fSPaolo Bonzini /* Write data to a scsi device. Returns nonzero on failure. 263*49ab747fSPaolo Bonzini The transfer may complete asynchronously. */ 264*49ab747fSPaolo Bonzini static void scsi_write_data(SCSIRequest *req) 265*49ab747fSPaolo Bonzini { 266*49ab747fSPaolo Bonzini SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); 267*49ab747fSPaolo Bonzini SCSIDevice *s = r->req.dev; 268*49ab747fSPaolo Bonzini int ret; 269*49ab747fSPaolo Bonzini 270*49ab747fSPaolo Bonzini DPRINTF("scsi_write_data 0x%x\n", req->tag); 271*49ab747fSPaolo Bonzini if (r->len == 0) { 272*49ab747fSPaolo Bonzini r->len = r->buflen; 273*49ab747fSPaolo Bonzini scsi_req_data(&r->req, r->len); 274*49ab747fSPaolo Bonzini return; 275*49ab747fSPaolo Bonzini } 276*49ab747fSPaolo Bonzini 277*49ab747fSPaolo Bonzini /* The request is used as the AIO opaque value, so add a ref. */ 278*49ab747fSPaolo Bonzini scsi_req_ref(&r->req); 279*49ab747fSPaolo Bonzini ret = execute_command(s->conf.bs, r, SG_DXFER_TO_DEV, scsi_write_complete); 280*49ab747fSPaolo Bonzini if (ret < 0) { 281*49ab747fSPaolo Bonzini scsi_command_complete(r, ret); 282*49ab747fSPaolo Bonzini } 283*49ab747fSPaolo Bonzini } 284*49ab747fSPaolo Bonzini 285*49ab747fSPaolo Bonzini /* Return a pointer to the data buffer. */ 286*49ab747fSPaolo Bonzini static uint8_t *scsi_get_buf(SCSIRequest *req) 287*49ab747fSPaolo Bonzini { 288*49ab747fSPaolo Bonzini SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); 289*49ab747fSPaolo Bonzini 290*49ab747fSPaolo Bonzini return r->buf; 291*49ab747fSPaolo Bonzini } 292*49ab747fSPaolo Bonzini 293*49ab747fSPaolo Bonzini /* Execute a scsi command. Returns the length of the data expected by the 294*49ab747fSPaolo Bonzini command. This will be Positive for data transfers from the device 295*49ab747fSPaolo Bonzini (eg. disk reads), negative for transfers to the device (eg. disk writes), 296*49ab747fSPaolo Bonzini and zero if the command does not transfer any data. */ 297*49ab747fSPaolo Bonzini 298*49ab747fSPaolo Bonzini static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) 299*49ab747fSPaolo Bonzini { 300*49ab747fSPaolo Bonzini SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); 301*49ab747fSPaolo Bonzini SCSIDevice *s = r->req.dev; 302*49ab747fSPaolo Bonzini int ret; 303*49ab747fSPaolo Bonzini 304*49ab747fSPaolo Bonzini DPRINTF("Command: lun=%d tag=0x%x len %zd data=0x%02x", lun, tag, 305*49ab747fSPaolo Bonzini r->req.cmd.xfer, cmd[0]); 306*49ab747fSPaolo Bonzini 307*49ab747fSPaolo Bonzini #ifdef DEBUG_SCSI 308*49ab747fSPaolo Bonzini { 309*49ab747fSPaolo Bonzini int i; 310*49ab747fSPaolo Bonzini for (i = 1; i < r->req.cmd.len; i++) { 311*49ab747fSPaolo Bonzini printf(" 0x%02x", cmd[i]); 312*49ab747fSPaolo Bonzini } 313*49ab747fSPaolo Bonzini printf("\n"); 314*49ab747fSPaolo Bonzini } 315*49ab747fSPaolo Bonzini #endif 316*49ab747fSPaolo Bonzini 317*49ab747fSPaolo Bonzini if (r->req.cmd.xfer == 0) { 318*49ab747fSPaolo Bonzini if (r->buf != NULL) 319*49ab747fSPaolo Bonzini g_free(r->buf); 320*49ab747fSPaolo Bonzini r->buflen = 0; 321*49ab747fSPaolo Bonzini r->buf = NULL; 322*49ab747fSPaolo Bonzini /* The request is used as the AIO opaque value, so add a ref. */ 323*49ab747fSPaolo Bonzini scsi_req_ref(&r->req); 324*49ab747fSPaolo Bonzini ret = execute_command(s->conf.bs, r, SG_DXFER_NONE, scsi_command_complete); 325*49ab747fSPaolo Bonzini if (ret < 0) { 326*49ab747fSPaolo Bonzini scsi_command_complete(r, ret); 327*49ab747fSPaolo Bonzini return 0; 328*49ab747fSPaolo Bonzini } 329*49ab747fSPaolo Bonzini return 0; 330*49ab747fSPaolo Bonzini } 331*49ab747fSPaolo Bonzini 332*49ab747fSPaolo Bonzini if (r->buflen != r->req.cmd.xfer) { 333*49ab747fSPaolo Bonzini if (r->buf != NULL) 334*49ab747fSPaolo Bonzini g_free(r->buf); 335*49ab747fSPaolo Bonzini r->buf = g_malloc(r->req.cmd.xfer); 336*49ab747fSPaolo Bonzini r->buflen = r->req.cmd.xfer; 337*49ab747fSPaolo Bonzini } 338*49ab747fSPaolo Bonzini 339*49ab747fSPaolo Bonzini memset(r->buf, 0, r->buflen); 340*49ab747fSPaolo Bonzini r->len = r->req.cmd.xfer; 341*49ab747fSPaolo Bonzini if (r->req.cmd.mode == SCSI_XFER_TO_DEV) { 342*49ab747fSPaolo Bonzini r->len = 0; 343*49ab747fSPaolo Bonzini return -r->req.cmd.xfer; 344*49ab747fSPaolo Bonzini } else { 345*49ab747fSPaolo Bonzini return r->req.cmd.xfer; 346*49ab747fSPaolo Bonzini } 347*49ab747fSPaolo Bonzini } 348*49ab747fSPaolo Bonzini 349*49ab747fSPaolo Bonzini static int get_stream_blocksize(BlockDriverState *bdrv) 350*49ab747fSPaolo Bonzini { 351*49ab747fSPaolo Bonzini uint8_t cmd[6]; 352*49ab747fSPaolo Bonzini uint8_t buf[12]; 353*49ab747fSPaolo Bonzini uint8_t sensebuf[8]; 354*49ab747fSPaolo Bonzini sg_io_hdr_t io_header; 355*49ab747fSPaolo Bonzini int ret; 356*49ab747fSPaolo Bonzini 357*49ab747fSPaolo Bonzini memset(cmd, 0, sizeof(cmd)); 358*49ab747fSPaolo Bonzini memset(buf, 0, sizeof(buf)); 359*49ab747fSPaolo Bonzini cmd[0] = MODE_SENSE; 360*49ab747fSPaolo Bonzini cmd[4] = sizeof(buf); 361*49ab747fSPaolo Bonzini 362*49ab747fSPaolo Bonzini memset(&io_header, 0, sizeof(io_header)); 363*49ab747fSPaolo Bonzini io_header.interface_id = 'S'; 364*49ab747fSPaolo Bonzini io_header.dxfer_direction = SG_DXFER_FROM_DEV; 365*49ab747fSPaolo Bonzini io_header.dxfer_len = sizeof(buf); 366*49ab747fSPaolo Bonzini io_header.dxferp = buf; 367*49ab747fSPaolo Bonzini io_header.cmdp = cmd; 368*49ab747fSPaolo Bonzini io_header.cmd_len = sizeof(cmd); 369*49ab747fSPaolo Bonzini io_header.mx_sb_len = sizeof(sensebuf); 370*49ab747fSPaolo Bonzini io_header.sbp = sensebuf; 371*49ab747fSPaolo Bonzini io_header.timeout = 6000; /* XXX */ 372*49ab747fSPaolo Bonzini 373*49ab747fSPaolo Bonzini ret = bdrv_ioctl(bdrv, SG_IO, &io_header); 374*49ab747fSPaolo Bonzini if (ret < 0 || io_header.driver_status || io_header.host_status) { 375*49ab747fSPaolo Bonzini return -1; 376*49ab747fSPaolo Bonzini } 377*49ab747fSPaolo Bonzini return (buf[9] << 16) | (buf[10] << 8) | buf[11]; 378*49ab747fSPaolo Bonzini } 379*49ab747fSPaolo Bonzini 380*49ab747fSPaolo Bonzini static void scsi_generic_reset(DeviceState *dev) 381*49ab747fSPaolo Bonzini { 382*49ab747fSPaolo Bonzini SCSIDevice *s = SCSI_DEVICE(dev); 383*49ab747fSPaolo Bonzini 384*49ab747fSPaolo Bonzini scsi_device_purge_requests(s, SENSE_CODE(RESET)); 385*49ab747fSPaolo Bonzini } 386*49ab747fSPaolo Bonzini 387*49ab747fSPaolo Bonzini static void scsi_destroy(SCSIDevice *s) 388*49ab747fSPaolo Bonzini { 389*49ab747fSPaolo Bonzini scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE)); 390*49ab747fSPaolo Bonzini blockdev_mark_auto_del(s->conf.bs); 391*49ab747fSPaolo Bonzini } 392*49ab747fSPaolo Bonzini 393*49ab747fSPaolo Bonzini static int scsi_generic_initfn(SCSIDevice *s) 394*49ab747fSPaolo Bonzini { 395*49ab747fSPaolo Bonzini int sg_version; 396*49ab747fSPaolo Bonzini struct sg_scsi_id scsiid; 397*49ab747fSPaolo Bonzini 398*49ab747fSPaolo Bonzini if (!s->conf.bs) { 399*49ab747fSPaolo Bonzini error_report("drive property not set"); 400*49ab747fSPaolo Bonzini return -1; 401*49ab747fSPaolo Bonzini } 402*49ab747fSPaolo Bonzini 403*49ab747fSPaolo Bonzini if (bdrv_get_on_error(s->conf.bs, 0) != BLOCKDEV_ON_ERROR_ENOSPC) { 404*49ab747fSPaolo Bonzini error_report("Device doesn't support drive option werror"); 405*49ab747fSPaolo Bonzini return -1; 406*49ab747fSPaolo Bonzini } 407*49ab747fSPaolo Bonzini if (bdrv_get_on_error(s->conf.bs, 1) != BLOCKDEV_ON_ERROR_REPORT) { 408*49ab747fSPaolo Bonzini error_report("Device doesn't support drive option rerror"); 409*49ab747fSPaolo Bonzini return -1; 410*49ab747fSPaolo Bonzini } 411*49ab747fSPaolo Bonzini 412*49ab747fSPaolo Bonzini /* check we are using a driver managing SG_IO (version 3 and after */ 413*49ab747fSPaolo Bonzini if (bdrv_ioctl(s->conf.bs, SG_GET_VERSION_NUM, &sg_version) < 0) { 414*49ab747fSPaolo Bonzini error_report("scsi generic interface not supported"); 415*49ab747fSPaolo Bonzini return -1; 416*49ab747fSPaolo Bonzini } 417*49ab747fSPaolo Bonzini if (sg_version < 30000) { 418*49ab747fSPaolo Bonzini error_report("scsi generic interface too old"); 419*49ab747fSPaolo Bonzini return -1; 420*49ab747fSPaolo Bonzini } 421*49ab747fSPaolo Bonzini 422*49ab747fSPaolo Bonzini /* get LUN of the /dev/sg? */ 423*49ab747fSPaolo Bonzini if (bdrv_ioctl(s->conf.bs, SG_GET_SCSI_ID, &scsiid)) { 424*49ab747fSPaolo Bonzini error_report("SG_GET_SCSI_ID ioctl failed"); 425*49ab747fSPaolo Bonzini return -1; 426*49ab747fSPaolo Bonzini } 427*49ab747fSPaolo Bonzini 428*49ab747fSPaolo Bonzini /* define device state */ 429*49ab747fSPaolo Bonzini s->type = scsiid.scsi_type; 430*49ab747fSPaolo Bonzini DPRINTF("device type %d\n", s->type); 431*49ab747fSPaolo Bonzini if (s->type == TYPE_DISK || s->type == TYPE_ROM) { 432*49ab747fSPaolo Bonzini add_boot_device_path(s->conf.bootindex, &s->qdev, NULL); 433*49ab747fSPaolo Bonzini } 434*49ab747fSPaolo Bonzini 435*49ab747fSPaolo Bonzini switch (s->type) { 436*49ab747fSPaolo Bonzini case TYPE_TAPE: 437*49ab747fSPaolo Bonzini s->blocksize = get_stream_blocksize(s->conf.bs); 438*49ab747fSPaolo Bonzini if (s->blocksize == -1) { 439*49ab747fSPaolo Bonzini s->blocksize = 0; 440*49ab747fSPaolo Bonzini } 441*49ab747fSPaolo Bonzini break; 442*49ab747fSPaolo Bonzini 443*49ab747fSPaolo Bonzini /* Make a guess for block devices, we'll fix it when the guest sends. 444*49ab747fSPaolo Bonzini * READ CAPACITY. If they don't, they likely would assume these sizes 445*49ab747fSPaolo Bonzini * anyway. (TODO: they could also send MODE SENSE). 446*49ab747fSPaolo Bonzini */ 447*49ab747fSPaolo Bonzini case TYPE_ROM: 448*49ab747fSPaolo Bonzini case TYPE_WORM: 449*49ab747fSPaolo Bonzini s->blocksize = 2048; 450*49ab747fSPaolo Bonzini break; 451*49ab747fSPaolo Bonzini default: 452*49ab747fSPaolo Bonzini s->blocksize = 512; 453*49ab747fSPaolo Bonzini break; 454*49ab747fSPaolo Bonzini } 455*49ab747fSPaolo Bonzini 456*49ab747fSPaolo Bonzini DPRINTF("block size %d\n", s->blocksize); 457*49ab747fSPaolo Bonzini return 0; 458*49ab747fSPaolo Bonzini } 459*49ab747fSPaolo Bonzini 460*49ab747fSPaolo Bonzini const SCSIReqOps scsi_generic_req_ops = { 461*49ab747fSPaolo Bonzini .size = sizeof(SCSIGenericReq), 462*49ab747fSPaolo Bonzini .free_req = scsi_free_request, 463*49ab747fSPaolo Bonzini .send_command = scsi_send_command, 464*49ab747fSPaolo Bonzini .read_data = scsi_read_data, 465*49ab747fSPaolo Bonzini .write_data = scsi_write_data, 466*49ab747fSPaolo Bonzini .cancel_io = scsi_cancel_io, 467*49ab747fSPaolo Bonzini .get_buf = scsi_get_buf, 468*49ab747fSPaolo Bonzini .load_request = scsi_generic_load_request, 469*49ab747fSPaolo Bonzini .save_request = scsi_generic_save_request, 470*49ab747fSPaolo Bonzini }; 471*49ab747fSPaolo Bonzini 472*49ab747fSPaolo Bonzini static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun, 473*49ab747fSPaolo Bonzini uint8_t *buf, void *hba_private) 474*49ab747fSPaolo Bonzini { 475*49ab747fSPaolo Bonzini SCSIRequest *req; 476*49ab747fSPaolo Bonzini 477*49ab747fSPaolo Bonzini req = scsi_req_alloc(&scsi_generic_req_ops, d, tag, lun, hba_private); 478*49ab747fSPaolo Bonzini return req; 479*49ab747fSPaolo Bonzini } 480*49ab747fSPaolo Bonzini 481*49ab747fSPaolo Bonzini static Property scsi_generic_properties[] = { 482*49ab747fSPaolo Bonzini DEFINE_PROP_DRIVE("drive", SCSIDevice, conf.bs), 483*49ab747fSPaolo Bonzini DEFINE_PROP_INT32("bootindex", SCSIDevice, conf.bootindex, -1), 484*49ab747fSPaolo Bonzini DEFINE_PROP_END_OF_LIST(), 485*49ab747fSPaolo Bonzini }; 486*49ab747fSPaolo Bonzini 487*49ab747fSPaolo Bonzini static void scsi_generic_class_initfn(ObjectClass *klass, void *data) 488*49ab747fSPaolo Bonzini { 489*49ab747fSPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass); 490*49ab747fSPaolo Bonzini SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass); 491*49ab747fSPaolo Bonzini 492*49ab747fSPaolo Bonzini sc->init = scsi_generic_initfn; 493*49ab747fSPaolo Bonzini sc->destroy = scsi_destroy; 494*49ab747fSPaolo Bonzini sc->alloc_req = scsi_new_request; 495*49ab747fSPaolo Bonzini dc->fw_name = "disk"; 496*49ab747fSPaolo Bonzini dc->desc = "pass through generic scsi device (/dev/sg*)"; 497*49ab747fSPaolo Bonzini dc->reset = scsi_generic_reset; 498*49ab747fSPaolo Bonzini dc->props = scsi_generic_properties; 499*49ab747fSPaolo Bonzini dc->vmsd = &vmstate_scsi_device; 500*49ab747fSPaolo Bonzini } 501*49ab747fSPaolo Bonzini 502*49ab747fSPaolo Bonzini static const TypeInfo scsi_generic_info = { 503*49ab747fSPaolo Bonzini .name = "scsi-generic", 504*49ab747fSPaolo Bonzini .parent = TYPE_SCSI_DEVICE, 505*49ab747fSPaolo Bonzini .instance_size = sizeof(SCSIDevice), 506*49ab747fSPaolo Bonzini .class_init = scsi_generic_class_initfn, 507*49ab747fSPaolo Bonzini }; 508*49ab747fSPaolo Bonzini 509*49ab747fSPaolo Bonzini static void scsi_generic_register_types(void) 510*49ab747fSPaolo Bonzini { 511*49ab747fSPaolo Bonzini type_register_static(&scsi_generic_info); 512*49ab747fSPaolo Bonzini } 513*49ab747fSPaolo Bonzini 514*49ab747fSPaolo Bonzini type_init(scsi_generic_register_types) 515*49ab747fSPaolo Bonzini 516*49ab747fSPaolo Bonzini #endif /* __linux__ */ 517