This allows passthrough of devices with LUN != 0, by redirecting them to LUN0 in the emulated target.
Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- hw/scsi-generic.c | 38 +++++++++++++++++++++++++++++++++----- 1 files changed, 33 insertions(+), 5 deletions(-) diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index e6f0efd..fb38934 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -230,8 +230,11 @@ static void scsi_read_data(SCSIRequest *req) return; } - if (r->req.cmd.buf[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE) - { + switch (r->req.cmd.buf[0]) { + case REQUEST_SENSE: + if (!(s->driver_status & SG_ERR_DRIVER_SENSE)) { + break; + } s->senselen = MIN(r->len, s->senselen); memcpy(r->buf, s->sensebuf, s->senselen); r->io_header.driver_status = 0; @@ -246,6 +249,32 @@ static void scsi_read_data(SCSIRequest *req) /* Clear sensebuf after REQUEST_SENSE */ scsi_clear_sense(s); return; + + case REPORT_LUNS: + assert(!s->lun); + if (r->req.cmd.xfer < 16) { + scsi_command_complete(r, -EINVAL); + return; + } + r->io_header.driver_status = 0; + r->io_header.status = 0; + r->io_header.dxfer_len = 16; + r->len = -1; + r->buf[3] = 8; + scsi_req_data(&r->req, 16); + scsi_command_complete(r, 0); + return; + + case INQUIRY: + if (req->lun != s->lun) { + if (r->req.cmd.xfer < 1) { + scsi_command_complete(r, -EINVAL); + return; + } + outbuf[0] = 0x7f; + return MIN(req->cmd.xfer, SCSI_MAX_INQUIRY_LEN); + } + break; } ret = execute_command(s->bs, r, SG_DXFER_FROM_DEV, scsi_read_complete); @@ -335,7 +364,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd) SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); int ret; - if (cmd[0] != REQUEST_SENSE && req->lun != s->lun) { + if (cmd[0] != REQUEST_SENSE && cmd[0] != INQUIRY && req->lun != s->lun) { DPRINTF("Unimplemented LUN %d\n", req->lun); scsi_set_sense(s, SENSE_CODE(LUN_NOT_SUPPORTED)); r->req.status = CHECK_CONDITION; @@ -510,8 +539,6 @@ static int scsi_generic_initfn(SCSIDevice *dev) } /* define device state */ - s->lun = scsiid.lun; - DPRINTF("LUN %d\n", s->lun); s->qdev.type = scsiid.scsi_type; DPRINTF("device type %d\n", s->qdev.type); if (s->qdev.type == TYPE_TAPE) { @@ -552,6 +579,7 @@ static SCSIDeviceInfo scsi_generic_info = { .get_sense = scsi_get_sense, .qdev.props = (Property[]) { DEFINE_BLOCK_PROPERTIES(SCSIGenericState, qdev.conf), + DEFINE_PROP_UINT32("lun", SCSIDiskState, lun, 0), DEFINE_PROP_END_OF_LIST(), }, }; -- 1.7.4.4