From: Jared Rossi <[email protected]>

Add logic to identify a virtio-pci scsi controller and target lun with
assigned bootindex, then build IPLB for it.

Unfence PCI case for scsi devices in BIOS.

Signed-off-by: Jared Rossi <[email protected]>
---
 hw/s390x/ipl.c          | 37 +++++++++++++++++++++++++++++++++++++
 pc-bios/s390-ccw/main.c |  3 +++
 2 files changed, 40 insertions(+)

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 6969e11b27..0cab043b12 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -402,6 +402,7 @@ static CcwDevice *s390_get_ccw_device(DeviceState *dev_st, 
int *devtype)
 }
 
 #define PCI_DEVTYPE_VIRTIO       0x05
+#define PCI_DEVTYPE_SCSI         0x06
 
 static S390PCIBusDevice *s390_get_pci_device(DeviceState *dev_st, int *devtype)
 {
@@ -417,6 +418,26 @@ static S390PCIBusDevice *s390_get_pci_device(DeviceState 
*dev_st, int *devtype)
             if (pbdev) {
                 tmp_dt = PCI_DEVTYPE_VIRTIO;
             }
+        } else {
+            SCSIDevice *sd = (SCSIDevice *)
+                object_dynamic_cast(OBJECT(dev_st), TYPE_SCSI_DEVICE);
+            if (sd) {
+                SCSIBus *sbus = scsi_bus_from_device(sd);
+                VirtIODevice *vdev = (VirtIODevice *)
+                    object_dynamic_cast(OBJECT(sbus->qbus.parent),
+                                                TYPE_VIRTIO_DEVICE);
+                if (vdev) {
+                    pci_dev = (PCIDevice *)
+                        
object_dynamic_cast(OBJECT(qdev_get_parent_bus(DEVICE(vdev))->parent),
+                                            TYPE_PCI_DEVICE);
+                    if (pci_dev) {
+                        pbdev = s390_pci_find_dev_by_pci(s390_get_phb(), 
pci_dev);
+                        if (pbdev) {
+                            tmp_dt = PCI_DEVTYPE_SCSI;
+                        }
+                    }
+                }
+            }
         }
     }
     if (devtype) {
@@ -621,6 +642,22 @@ static bool s390_build_iplb(DeviceState *dev_st, 
IplParameterBlock *iplb)
             iplb->pbt = S390_IPL_TYPE_PCI;
             iplb->pci.fid = cpu_to_be32(pbdev->fid);
             break;
+        case PCI_DEVTYPE_SCSI:
+            sd = SCSI_DEVICE(dev_st);
+            scsi_lp = object_property_get_str(OBJECT(sd), "loadparm", NULL);
+            if (scsi_lp && strlen(scsi_lp) > 0) {
+                lp = scsi_lp;
+            }
+            iplb->len = cpu_to_be32(S390_IPLB_MIN_PCI_LEN);
+            iplb->blk0_len =
+                cpu_to_be32(S390_IPLB_MIN_PCI_LEN - S390_IPLB_HEADER_LEN);
+            iplb->pbt = S390_IPL_TYPE_QEMU_SCSI;
+            iplb->scsi.lun = cpu_to_be32(sd->lun);
+            iplb->scsi.target = cpu_to_be16(sd->id);
+            iplb->scsi.channel = cpu_to_be16(sd->channel);
+            iplb->scsi.bus = S390_IPL_TYPE_PCI;
+            iplb->scsi.fid = cpu_to_be32(pbdev->fid);
+            break;
         default:
             return false;
         }
diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c
index a2a24b024f..d2a2ac3138 100644
--- a/pc-bios/s390-ccw/main.c
+++ b/pc-bios/s390-ccw/main.c
@@ -267,6 +267,9 @@ static bool find_boot_device(void)
             blk_schid.ssid = iplb->scsi.ssid & 0x3;
             found = find_subch(iplb->scsi.devno);
             break;
+        case S390_IPL_TYPE_PCI:
+            found = find_fid(iplb->scsi.fid);
+            break;
         default:
             puts("Unrecognized SCSI controller");
             break;
-- 
2.54.0


Reply via email to