summaryrefslogtreecommitdiff
path: root/hw/vfio/ccw.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/vfio/ccw.c')
-rw-r--r--hw/vfio/ccw.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index 76323c6bde..636729c03d 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -47,9 +47,9 @@ struct VFIODeviceOps vfio_ccw_ops = {
.vfio_compute_needs_reset = vfio_ccw_compute_needs_reset,
};
-static int vfio_ccw_handle_request(ORB *orb, SCSW *scsw, void *data)
+static IOInstEnding vfio_ccw_handle_request(SubchDev *sch)
{
- S390CCWDevice *cdev = data;
+ S390CCWDevice *cdev = sch->driver_data;
VFIOCCWDevice *vcdev = DO_UPCAST(VFIOCCWDevice, cdev, cdev);
struct ccw_io_region *region = vcdev->io_region;
int ret;
@@ -60,8 +60,8 @@ static int vfio_ccw_handle_request(ORB *orb, SCSW *scsw, void *data)
memset(region, 0, sizeof(*region));
- memcpy(region->orb_area, orb, sizeof(ORB));
- memcpy(region->scsw_area, scsw, sizeof(SCSW));
+ memcpy(region->orb_area, &sch->orb, sizeof(ORB));
+ memcpy(region->scsw_area, &sch->curr_status.scsw, sizeof(SCSW));
again:
ret = pwrite(vcdev->vdev.fd, region,
@@ -71,10 +71,24 @@ again:
goto again;
}
error_report("vfio-ccw: wirte I/O region failed with errno=%d", errno);
- return -errno;
+ ret = -errno;
+ } else {
+ ret = region->ret_code;
+ }
+ switch (ret) {
+ case 0:
+ return IOINST_CC_EXPECTED;
+ case -EBUSY:
+ return IOINST_CC_BUSY;
+ case -ENODEV:
+ case -EACCES:
+ return IOINST_CC_NOT_OPERATIONAL;
+ case -EFAULT:
+ default:
+ sch_gen_unit_exception(sch);
+ css_inject_io_interrupt(sch);
+ return IOINST_CC_EXPECTED;
}
-
- return region->ret_code;
}
static void vfio_ccw_reset(DeviceState *dev)