static void scsi_read_complete(void * opaque, int ret) { SCSIGenericReq *r = (SCSIGenericReq *)opaque; SCSIDevice *s = r->req.dev; int len; r->req.aiocb = NULL; if (ret || r->req.io_canceled) { scsi_command_complete(r, ret); return; } len = r->io_header.dxfer_len - r->io_header.resid; DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len); r->len = -1; if (len == 0) { scsi_command_complete(r, 0); } else { /* Snoop READ CAPACITY output to set the blocksize. */ if (r->req.cmd.buf[0] == READ_CAPACITY_10 && (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) { s->blocksize = ldl_be_p(&r->buf[4]); s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL; } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 && (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) { s->blocksize = ldl_be_p(&r->buf[8]); s->max_lba = ldq_be_p(&r->buf[0]); } blk_set_guest_block_size(s->conf.blk, s->blocksize); scsi_req_data(&r->req, len); scsi_req_unref(&r->req); } }
static void scsi_read_complete(void * opaque, int ret) { SCSIGenericReq *r = (SCSIGenericReq *)opaque; SCSIDevice *s = r->req.dev; int len; assert(r->req.aiocb != NULL); r->req.aiocb = NULL; if (ret || r->req.io_canceled) { scsi_command_complete_noio(r, ret); return; } len = r->io_header.dxfer_len - r->io_header.resid; DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len); r->len = -1; if (len == 0) { scsi_command_complete_noio(r, 0); return; } /* Snoop READ CAPACITY output to set the blocksize. */ if (r->req.cmd.buf[0] == READ_CAPACITY_10 && (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) { s->blocksize = ldl_be_p(&r->buf[4]); s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL; } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 && (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) { s->blocksize = ldl_be_p(&r->buf[8]); s->max_lba = ldq_be_p(&r->buf[0]); } blk_set_guest_block_size(s->conf.blk, s->blocksize); /* Patch MODE SENSE device specific parameters if the BDS is opened * readonly. */ if ((s->type == TYPE_DISK || s->type == TYPE_TAPE) && blk_is_read_only(s->conf.blk) && (r->req.cmd.buf[0] == MODE_SENSE || r->req.cmd.buf[0] == MODE_SENSE_10) && (r->req.cmd.buf[1] & 0x8) == 0) { if (r->req.cmd.buf[0] == MODE_SENSE) { r->buf[2] |= 0x80; } else { r->buf[3] |= 0x80; } } scsi_req_data(&r->req, len); scsi_req_unref(&r->req); }
static void scsi_read_complete(void * opaque, int ret) { SCSIGenericReq *r = (SCSIGenericReq *)opaque; SCSIDevice *s = r->req.dev; int len; assert(r->req.aiocb != NULL); r->req.aiocb = NULL; aio_context_acquire(blk_get_aio_context(s->conf.blk)); if (ret || r->req.io_canceled) { scsi_command_complete_noio(r, ret); goto done; } len = r->io_header.dxfer_len - r->io_header.resid; DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len); r->len = -1; if (len == 0) { scsi_command_complete_noio(r, 0); goto done; } /* Snoop READ CAPACITY output to set the blocksize. */ if (r->req.cmd.buf[0] == READ_CAPACITY_10 && (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) { s->blocksize = ldl_be_p(&r->buf[4]); s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL; } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 && (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) { s->blocksize = ldl_be_p(&r->buf[8]); s->max_lba = ldq_be_p(&r->buf[0]); } blk_set_guest_block_size(s->conf.blk, s->blocksize); /* Patch MODE SENSE device specific parameters if the BDS is opened * readonly. */ if ((s->type == TYPE_DISK || s->type == TYPE_TAPE) && blk_is_read_only(s->conf.blk) && (r->req.cmd.buf[0] == MODE_SENSE || r->req.cmd.buf[0] == MODE_SENSE_10) && (r->req.cmd.buf[1] & 0x8) == 0) { if (r->req.cmd.buf[0] == MODE_SENSE) { r->buf[2] |= 0x80; } else { r->buf[3] |= 0x80; } } if (s->type == TYPE_DISK && r->req.cmd.buf[0] == INQUIRY && r->req.cmd.buf[2] == 0xb0) { uint32_t max_transfer = blk_get_max_transfer(s->conf.blk) / s->blocksize; assert(max_transfer); stl_be_p(&r->buf[8], max_transfer); /* Also take care of the opt xfer len. */ stl_be_p(&r->buf[12], MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12]))); } scsi_req_data(&r->req, len); scsi_req_unref(&r->req); done: aio_context_release(blk_get_aio_context(s->conf.blk)); }