aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pc-bios/s390-ccw/s390-ccw.h7
-rw-r--r--pc-bios/s390-ccw/virtio-scsi.c20
2 files changed, 22 insertions, 5 deletions
diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h
index 07d8cbcb20..2089274842 100644
--- a/pc-bios/s390-ccw/s390-ccw.h
+++ b/pc-bios/s390-ccw/s390-ccw.h
@@ -42,6 +42,13 @@ typedef unsigned long long __u64;
#ifndef NULL
#define NULL 0
#endif
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef MIN_NON_ZERO
+#define MIN_NON_ZERO(a, b) ((a) == 0 ? (b) : \
+ ((b) == 0 ? (a) : (MIN(a, b))))
+#endif
#include "cio.h"
#include "iplb.h"
diff --git a/pc-bios/s390-ccw/virtio-scsi.c b/pc-bios/s390-ccw/virtio-scsi.c
index 6d070e2f73..ff65e2ee30 100644
--- a/pc-bios/s390-ccw/virtio-scsi.c
+++ b/pc-bios/s390-ccw/virtio-scsi.c
@@ -202,6 +202,7 @@ static void virtio_scsi_locate_device(VDev *vdev)
debug_print_int("config.scsi.max_channel", vdev->config.scsi.max_channel);
debug_print_int("config.scsi.max_target ", vdev->config.scsi.max_target);
debug_print_int("config.scsi.max_lun ", vdev->config.scsi.max_lun);
+ debug_print_int("config.scsi.max_sectors", vdev->config.scsi.max_sectors);
if (vdev->scsi_device_selected) {
sdev->channel = vdev->selected_scsi_device.channel;
@@ -254,12 +255,21 @@ static void virtio_scsi_locate_device(VDev *vdev)
int virtio_scsi_read_many(VDev *vdev,
ulong sector, void *load_addr, int sec_num)
{
+ int sector_count;
int f = vdev->blk_factor;
- unsigned int data_size = sec_num * virtio_get_block_size() * f;
-
- if (!scsi_read_10(vdev, sector * f, sec_num * f, load_addr, data_size)) {
- virtio_scsi_verify_response(&resp, "virtio-scsi:read_many");
- }
+ unsigned int data_size;
+
+ do {
+ sector_count = MIN_NON_ZERO(sec_num, vdev->config.scsi.max_sectors);
+ data_size = sector_count * virtio_get_block_size() * f;
+ if (!scsi_read_10(vdev, sector * f, sector_count * f, load_addr,
+ data_size)) {
+ virtio_scsi_verify_response(&resp, "virtio-scsi:read_many");
+ }
+ load_addr += data_size;
+ sector += sector_count;
+ sec_num -= sector_count;
+ } while (sec_num > 0);
return 0;
}