summaryrefslogtreecommitdiffstats
path: root/hw/scsi/emulation.c
diff options
context:
space:
mode:
authorDaniel Baumann <mail@daniel-baumann.ch>2025-06-06 10:05:23 +0000
committerDaniel Baumann <mail@daniel-baumann.ch>2025-06-06 10:05:23 +0000
commit755cc582a2473d06f3a2131d506d0311cc70e9f9 (patch)
tree3efb1ddb8d57bbb4539ac0d229b384871c57820f /hw/scsi/emulation.c
parentInitial commit. (diff)
downloadqemu-upstream.tar.xz
qemu-upstream.zip
Adding upstream version 1:7.2+dfsg.upstream/1%7.2+dfsgupstream
Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
Diffstat (limited to 'hw/scsi/emulation.c')
-rw-r--r--hw/scsi/emulation.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/hw/scsi/emulation.c b/hw/scsi/emulation.c
new file mode 100644
index 00000000..06d62f3c
--- /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;
+}