diff options
Diffstat (limited to 'hw/scsi/emulation.c')
-rw-r--r-- | hw/scsi/emulation.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/hw/scsi/emulation.c b/hw/scsi/emulation.c new file mode 100644 index 000000000..06d62f3c3 --- /dev/null +++ b/hw/scsi/emulation.c @@ -0,0 +1,42 @@ +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu/bswap.h" +#include "hw/scsi/emulation.h" + +int scsi_emulate_block_limits(uint8_t *outbuf, const SCSIBlockLimits *bl) +{ + /* required VPD size with unmap support */ + memset(outbuf, 0, 0x3c); + + outbuf[0] = bl->wsnz; /* wsnz */ + + if (bl->max_io_sectors) { + /* optimal transfer length granularity. This field and the optimal + * transfer length can't be greater than maximum transfer length. + */ + stw_be_p(outbuf + 2, MIN(bl->min_io_size, bl->max_io_sectors)); + + /* maximum transfer length */ + stl_be_p(outbuf + 4, bl->max_io_sectors); + + /* optimal transfer length */ + stl_be_p(outbuf + 8, MIN(bl->opt_io_size, bl->max_io_sectors)); + } else { + stw_be_p(outbuf + 2, bl->min_io_size); + stl_be_p(outbuf + 8, bl->opt_io_size); + } + + /* max unmap LBA count */ + stl_be_p(outbuf + 16, bl->max_unmap_sectors); + + /* max unmap descriptors */ + stl_be_p(outbuf + 20, bl->max_unmap_descr); + + /* optimal unmap granularity; alignment is zero */ + stl_be_p(outbuf + 24, bl->unmap_sectors); + + /* max write same size, make it the same as maximum transfer length */ + stl_be_p(outbuf + 36, bl->max_io_sectors); + + return 0x3c; +} |