aboutsummaryrefslogtreecommitdiff
path: root/src/hw/virtio-scsi.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2020-03-09 07:43:50 +0100
committerGerd Hoffmann <kraxel@redhat.com>2020-05-15 13:36:08 +0200
commitf82e82a5ab2366e1f4299e53ec95584f39d57dc8 (patch)
tree1515fa68510673410814c2b637bd3ad90844c18a /src/hw/virtio-scsi.c
parent040b92c6159773c36876f17f3fb02816ca9f6701 (diff)
downloadseabios-hppa-f82e82a5ab2366e1f4299e53ec95584f39d57dc8.zip
seabios-hppa-f82e82a5ab2366e1f4299e53ec95584f39d57dc8.tar.gz
seabios-hppa-f82e82a5ab2366e1f4299e53ec95584f39d57dc8.tar.bz2
virtio-mmio: add support for scsi devices.
Add new fields to struct virtio_lun_s for mmio support, add mmio parameter to virtio_scsi_init_lun(), so both pci and mmio devices can be handled. Add and use bootprio_find_scsi_mmio_device() to figure boot priority of devices connected to a virtio-mmio scsi controller. Finally add init_virtio_scsi_mmio() to initialize one virtio-mmio scsi controller. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'src/hw/virtio-scsi.c')
-rw-r--r--src/hw/virtio-scsi.c73
1 files changed, 62 insertions, 11 deletions
diff --git a/src/hw/virtio-scsi.c b/src/hw/virtio-scsi.c
index a533284..59f1c65 100644
--- a/src/hw/virtio-scsi.c
+++ b/src/hw/virtio-scsi.c
@@ -22,10 +22,13 @@
#include "virtio-pci.h"
#include "virtio-ring.h"
#include "virtio-scsi.h"
+#include "virtio-mmio.h"
struct virtio_lun_s {
struct drive_s drive;
struct pci_device *pci;
+ void *mmio;
+ char name[16];
struct vring_virtqueue *vq;
struct vp_device *vp;
u16 target;
@@ -94,7 +97,8 @@ virtio_scsi_process_op(struct disk_op_s *op)
}
static void
-virtio_scsi_init_lun(struct virtio_lun_s *vlun, struct pci_device *pci,
+virtio_scsi_init_lun(struct virtio_lun_s *vlun,
+ struct pci_device *pci, void *mmio,
struct vp_device *vp, struct vring_virtqueue *vq,
u16 target, u16 lun)
{
@@ -102,10 +106,15 @@ virtio_scsi_init_lun(struct virtio_lun_s *vlun, struct pci_device *pci,
vlun->drive.type = DTYPE_VIRTIO_SCSI;
vlun->drive.cntl_id = pci->bdf;
vlun->pci = pci;
+ vlun->mmio = mmio;
vlun->vp = vp;
vlun->vq = vq;
vlun->target = target;
vlun->lun = lun;
+ if (vlun->pci)
+ snprintf(vlun->name, sizeof(vlun->name), "pci:%pP", vlun->pci);
+ if (vlun->mmio)
+ snprintf(vlun->name, sizeof(vlun->name), "mmio:%08x", (u32)vlun->mmio);
}
static int
@@ -114,12 +123,17 @@ virtio_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv)
u8 skip_nonbootable = is_bootprio_strict();
struct virtio_lun_s *tmpl_vlun =
container_of(tmpl_drv, struct virtio_lun_s, drive);
- int prio = bootprio_find_scsi_device(tmpl_vlun->pci, tmpl_vlun->target, tmpl_vlun->lun);
+ int prio = -1;
+
+ if (tmpl_vlun->pci)
+ prio = bootprio_find_scsi_device(tmpl_vlun->pci, tmpl_vlun->target, tmpl_vlun->lun);
+ if (tmpl_vlun->mmio)
+ prio = bootprio_find_scsi_mmio_device(tmpl_vlun->mmio, tmpl_vlun->target, tmpl_vlun->lun);
if (skip_nonbootable && prio < 0) {
- dprintf(1, "skipping init of a non-bootable virtio-scsi dev at %pP,"
+ dprintf(1, "skipping init of a non-bootable virtio-scsi dev at %s,"
" target %d, lun %d\n",
- tmpl_vlun->pci, tmpl_vlun->target, tmpl_vlun->lun);
+ tmpl_vlun->name, tmpl_vlun->target, tmpl_vlun->lun);
return -1;
}
@@ -128,11 +142,12 @@ virtio_scsi_add_lun(u32 lun, struct drive_s *tmpl_drv)
warn_noalloc();
return -1;
}
- virtio_scsi_init_lun(vlun, tmpl_vlun->pci, tmpl_vlun->vp, tmpl_vlun->vq,
- tmpl_vlun->target, lun);
+ virtio_scsi_init_lun(vlun, tmpl_vlun->pci, tmpl_vlun->mmio,tmpl_vlun->vp,
+ tmpl_vlun->vq, tmpl_vlun->target, lun);
- boot_lchs_find_scsi_device(vlun->pci, vlun->target, vlun->lun,
- &(vlun->drive.lchs));
+ if (vlun->pci)
+ boot_lchs_find_scsi_device(vlun->pci, vlun->target, vlun->lun,
+ &(vlun->drive.lchs));
int ret = scsi_drive_setup(&vlun->drive, "virtio-scsi", prio);
if (ret)
goto fail;
@@ -144,13 +159,13 @@ fail:
}
static int
-virtio_scsi_scan_target(struct pci_device *pci, struct vp_device *vp,
+virtio_scsi_scan_target(struct pci_device *pci, void *mmio, struct vp_device *vp,
struct vring_virtqueue *vq, u16 target)
{
struct virtio_lun_s vlun0;
- virtio_scsi_init_lun(&vlun0, pci, vp, vq, target, 0);
+ virtio_scsi_init_lun(&vlun0, pci, mmio, vp, vq, target, 0);
int ret = scsi_rep_luns_scan(&vlun0.drive, virtio_scsi_add_lun);
return ret < 0 ? 0 : ret;
@@ -198,7 +213,43 @@ init_virtio_scsi(void *data)
int i, tot;
for (tot = 0, i = 0; i < 256; i++)
- tot += virtio_scsi_scan_target(pci, vp, vq, i);
+ tot += virtio_scsi_scan_target(pci, NULL, vp, vq, i);
+
+ if (!tot)
+ goto fail;
+
+ return;
+
+fail:
+ vp_reset(vp);
+ free(vp);
+ free(vq);
+}
+
+void
+init_virtio_scsi_mmio(void *mmio)
+{
+ dprintf(1, "found virtio-scsi-mmio at %p\n", mmio);
+ struct vring_virtqueue *vq = NULL;
+ struct vp_device *vp = malloc_high(sizeof(*vp));
+ if (!vp) {
+ warn_noalloc();
+ return;
+ }
+ vp_init_mmio(vp, mmio);
+ u8 status = VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER;
+
+ if (vp_find_vq(vp, 2, &vq) < 0 ) {
+ dprintf(1, "fail to find vq for virtio-scsi-mmio %p\n", mmio);
+ goto fail;
+ }
+
+ status |= VIRTIO_CONFIG_S_DRIVER_OK;
+ vp_set_status(vp, status);
+
+ int i, tot;
+ for (tot = 0, i = 0; i < 256; i++)
+ tot += virtio_scsi_scan_target(NULL, mmio, vp, vq, i);
if (!tot)
goto fail;