mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 16:53:55 -06:00
hw/scsi: cleanups before VPD BL emulation
To add support for the emulation of Block Limits VPD page for passthrough devices, a few adjustments in the current code base is required to avoid repetition and improve clarity. In scsi-generic.c, detach the Inquiry handling from scsi_read_complete and put it into a new function called scsi_handle_inquiry_reply. This change aims to avoid cluttering of scsi_read_complete when we more logic in the Inquiry response handling is added in the next patches, centralizing the changes in the new function. In scsi-disk.c, take the build of all emulated VPD pages from scsi_disk_emulate_inquiry and make it available to other files into a non-static function called scsi_disk_emulate_vpd_page. Making it public will allow the future VPD BL emulation code for passthrough devices to use it from scsi-generic.c, avoiding copy/pasting this code solely for that purpose. It also has the advantage of providing emulation of all VPD pages in case we need to emulate other pages in other scenarios. As a bonus, scsi_disk_emulate_inquiry got tidier. Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> Message-Id: <20180627172432.11120-2-danielhb413@gmail.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
2ad9b50f71
commit
0a96ca2437
3 changed files with 258 additions and 239 deletions
|
@ -142,6 +142,43 @@ static int execute_command(BlockBackend *blk,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
|
||||
{
|
||||
/*
|
||||
* EVPD set to zero returns the standard INQUIRY data.
|
||||
*
|
||||
* Check if scsi_version is unset (-1) to avoid re-defining it
|
||||
* each time an INQUIRY with standard data is received.
|
||||
* scsi_version is initialized with -1 in scsi_generic_reset
|
||||
* and scsi_disk_reset, making sure that we'll set the
|
||||
* scsi_version after a reset. If the version field of the
|
||||
* INQUIRY response somehow changes after a guest reboot,
|
||||
* we'll be able to keep track of it.
|
||||
*
|
||||
* On SCSI-2 and older, first 3 bits of byte 2 is the
|
||||
* ANSI-approved version, while on later versions the
|
||||
* whole byte 2 contains the version. Check if we're dealing
|
||||
* with a newer version and, in that case, assign the
|
||||
* whole byte.
|
||||
*/
|
||||
if (s->scsi_version == -1 && !(r->req.cmd.buf[1] & 0x01)) {
|
||||
s->scsi_version = r->buf[2] & 0x07;
|
||||
if (s->scsi_version > 2) {
|
||||
s->scsi_version = r->buf[2];
|
||||
}
|
||||
}
|
||||
if (s->type == TYPE_DISK && 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])));
|
||||
}
|
||||
}
|
||||
|
||||
static void scsi_read_complete(void * opaque, int ret)
|
||||
{
|
||||
SCSIGenericReq *r = (SCSIGenericReq *)opaque;
|
||||
|
@ -194,39 +231,7 @@ static void scsi_read_complete(void * opaque, int ret)
|
|||
}
|
||||
}
|
||||
if (r->req.cmd.buf[0] == INQUIRY) {
|
||||
/*
|
||||
* EVPD set to zero returns the standard INQUIRY data.
|
||||
*
|
||||
* Check if scsi_version is unset (-1) to avoid re-defining it
|
||||
* each time an INQUIRY with standard data is received.
|
||||
* scsi_version is initialized with -1 in scsi_generic_reset
|
||||
* and scsi_disk_reset, making sure that we'll set the
|
||||
* scsi_version after a reset. If the version field of the
|
||||
* INQUIRY response somehow changes after a guest reboot,
|
||||
* we'll be able to keep track of it.
|
||||
*
|
||||
* On SCSI-2 and older, first 3 bits of byte 2 is the
|
||||
* ANSI-approved version, while on later versions the
|
||||
* whole byte 2 contains the version. Check if we're dealing
|
||||
* with a newer version and, in that case, assign the
|
||||
* whole byte.
|
||||
*/
|
||||
if (s->scsi_version == -1 && !(r->req.cmd.buf[1] & 0x01)) {
|
||||
s->scsi_version = r->buf[2] & 0x07;
|
||||
if (s->scsi_version > 2) {
|
||||
s->scsi_version = r->buf[2];
|
||||
}
|
||||
}
|
||||
if (s->type == TYPE_DISK && 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_handle_inquiry_reply(r, s);
|
||||
}
|
||||
scsi_req_data(&r->req, len);
|
||||
scsi_req_unref(&r->req);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue