aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/s390x/3270-ccw.c1
-rw-r--r--hw/s390x/css.c45
-rw-r--r--hw/s390x/virtio-ccw.c1
-rw-r--r--include/hw/s390x/css.h2
4 files changed, 33 insertions, 16 deletions
diff --git a/hw/s390x/3270-ccw.c b/hw/s390x/3270-ccw.c
index 13e93d8d8f..69e6783ade 100644
--- a/hw/s390x/3270-ccw.c
+++ b/hw/s390x/3270-ccw.c
@@ -129,6 +129,7 @@ static void emulated_ccw_3270_realize(DeviceState *ds, Error **errp)
EMULATED_CCW_3270_CHPID_TYPE);
sch->do_subchannel_work = do_subchannel_work_virtual;
sch->ccw_cb = emulated_ccw_3270_cb;
+ sch->irb_cb = build_irb_virtual;
ck->init(dev, &err);
if (err) {
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 26bd01458f..1a3aad5163 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -1650,6 +1650,30 @@ static void build_irb_sense_data(SubchDev *sch, IRB *irb)
}
}
+void build_irb_virtual(SubchDev *sch, IRB *irb)
+{
+ SCHIB *schib = &sch->curr_status;
+ uint16_t stctl = schib->scsw.ctrl & SCSW_CTRL_MASK_STCTL;
+
+ if (stctl & SCSW_STCTL_STATUS_PEND) {
+ if (schib->scsw.cstat & (SCSW_CSTAT_DATA_CHECK |
+ SCSW_CSTAT_CHN_CTRL_CHK |
+ SCSW_CSTAT_INTF_CTRL_CHK)) {
+ irb->scsw.flags |= SCSW_FLAGS_MASK_ESWF;
+ irb->esw.word0 = 0x04804000;
+ } else {
+ irb->esw.word0 = 0x00800000;
+ }
+ /* If a unit check is pending, copy sense data. */
+ if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) &&
+ (schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) {
+ irb->scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL;
+ build_irb_sense_data(sch, irb);
+ irb->esw.erw = ESW_ERW_SENSE | (sizeof(sch->sense_data) << 8);
+ }
+ }
+}
+
int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
{
SCHIB *schib = &sch->curr_status;
@@ -1668,23 +1692,12 @@ int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
/* Copy scsw from current status. */
irb.scsw = schib->scsw;
- if (stctl & SCSW_STCTL_STATUS_PEND) {
- if (schib->scsw.cstat & (SCSW_CSTAT_DATA_CHECK |
- SCSW_CSTAT_CHN_CTRL_CHK |
- SCSW_CSTAT_INTF_CTRL_CHK)) {
- irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF;
- irb.esw.word0 = 0x04804000;
- } else {
- irb.esw.word0 = 0x00800000;
- }
- /* If a unit check is pending, copy sense data. */
- if ((schib->scsw.dstat & SCSW_DSTAT_UNIT_CHECK) &&
- (schib->pmcw.chars & PMCW_CHARS_MASK_CSENSE)) {
- irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL;
- build_irb_sense_data(sch, &irb);
- irb.esw.erw = ESW_ERW_SENSE | (sizeof(sch->sense_data) << 8);
- }
+
+ /* Build other IRB data, if necessary */
+ if (sch->irb_cb) {
+ sch->irb_cb(sch, &irb);
}
+
/* Store the irb to the guest. */
p = schib->pmcw;
copy_irb_to_guest(target_irb, &irb, &p, irb_len);
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 220b9efcf9..d68888fccd 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -753,6 +753,7 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
sch->id.reserved = 0xff;
sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
sch->do_subchannel_work = do_subchannel_work_virtual;
+ sch->irb_cb = build_irb_virtual;
ccw_dev->sch = sch;
dev->indicators = NULL;
dev->revision = -1;
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index bba7593d2e..7c23a13f3d 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -138,6 +138,7 @@ struct SubchDev {
int (*ccw_cb) (SubchDev *, CCW1);
void (*disable_cb)(SubchDev *);
IOInstEnding (*do_subchannel_work) (SubchDev *);
+ void (*irb_cb)(SubchDev *, IRB *);
SenseId id;
void *driver_data;
};
@@ -215,6 +216,7 @@ void css_clear_sei_pending(void);
IOInstEnding s390_ccw_cmd_request(SubchDev *sch);
IOInstEnding do_subchannel_work_virtual(SubchDev *sub);
IOInstEnding do_subchannel_work_passthrough(SubchDev *sub);
+void build_irb_virtual(SubchDev *sch, IRB *irb);
int s390_ccw_halt(SubchDev *sch);
int s390_ccw_clear(SubchDev *sch);