aboutsummaryrefslogtreecommitdiff
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
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>
-rw-r--r--src/boot.c10
-rw-r--r--src/hw/virtio-mmio.c3
-rw-r--r--src/hw/virtio-scsi.c73
-rw-r--r--src/hw/virtio-scsi.h1
-rw-r--r--src/util.h1
5 files changed, 76 insertions, 12 deletions
diff --git a/src/boot.c b/src/boot.c
index 4f12988..f2f084b 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -328,6 +328,16 @@ int bootprio_find_scsi_device(struct pci_device *pci, int target, int lun)
return find_prio(desc);
}
+int bootprio_find_scsi_mmio_device(void *mmio, int target, int lun)
+{
+ if (!CONFIG_BOOTORDER)
+ return -1;
+ char desc[256];
+ snprintf(desc, sizeof(desc), "/virtio-mmio@%016x/*@0/*@%x,%x",
+ (u32)mmio, target, lun);
+ return find_prio(desc);
+}
+
int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave)
{
if (CONFIG_CSM)
diff --git a/src/hw/virtio-mmio.c b/src/hw/virtio-mmio.c
index 0d6ef6e..daca8a0 100644
--- a/src/hw/virtio-mmio.c
+++ b/src/hw/virtio-mmio.c
@@ -4,6 +4,7 @@
#include "stacks.h" // run_thread
#include "string.h" // memset
#include "virtio-pci.h"
+#include "virtio-scsi.h"
#include "virtio-ring.h"
#include "virtio-mmio.h"
@@ -37,7 +38,7 @@ void virtio_mmio_setup_one(u64 addr)
/* TODO */
break;
case 8: /* scsi */
- /* TODO */
+ run_thread(init_virtio_scsi_mmio, mmio);
break;
default:
break;
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;
diff --git a/src/hw/virtio-scsi.h b/src/hw/virtio-scsi.h
index 7532cc9..8f01de4 100644
--- a/src/hw/virtio-scsi.h
+++ b/src/hw/virtio-scsi.h
@@ -43,5 +43,6 @@ struct virtio_scsi_resp_cmd {
struct disk_op_s;
int virtio_scsi_process_op(struct disk_op_s *op);
void virtio_scsi_setup(void);
+void init_virtio_scsi_mmio(void *data);
#endif /* _VIRTIO_SCSI_H */
diff --git a/src/util.h b/src/util.h
index 94592a2..1c82e09 100644
--- a/src/util.h
+++ b/src/util.h
@@ -31,6 +31,7 @@ u8 is_bootprio_strict(void);
struct pci_device;
int bootprio_find_pci_device(struct pci_device *pci);
int bootprio_find_scsi_device(struct pci_device *pci, int target, int lun);
+int bootprio_find_scsi_mmio_device(void *mmio, int target, int lun);
int bootprio_find_ata_device(struct pci_device *pci, int chanid, int slave);
int bootprio_find_fdc_device(struct pci_device *pci, int port, int fdid);
int bootprio_find_pci_rom(struct pci_device *pci, int instance);