diff --git a/hw/s390x/3270-ccw.c b/hw/s390x/3270-ccw.c
index 1554aa2484..5f9efe7ac6 100644
--- a/hw/s390x/3270-ccw.c
+++ b/hw/s390x/3270-ccw.c
@@ -18,46 +18,48 @@
 #include "hw/s390x/3270-ccw.h"
 
 /* Handle READ ccw commands from guest */
-static int handle_payload_3270_read(EmulatedCcw3270Device *dev, CCW1 *ccw)
+static CcwProcStatus handle_payload_3270_read(EmulatedCcw3270Device *dev,
+                                              CCW1 *ccw)
 {
     EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
     CcwDevice *ccw_dev = CCW_DEVICE(dev);
     int len;
 
     if (!ccw->cda) {
-        return -EFAULT;
+        return CSS_DO_PGM_CHK;
     }
 
     len = ck->read_payload_3270(dev, ccw->cda, ccw->count);
     ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
 
-    return 0;
+    return CSS_DO_SUCCESS;
 }
 
 /* Handle WRITE ccw commands to write data to client */
-static int handle_payload_3270_write(EmulatedCcw3270Device *dev, CCW1 *ccw)
+static CcwProcStatus handle_payload_3270_write(EmulatedCcw3270Device *dev,
+                                               CCW1 *ccw)
 {
     EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
     CcwDevice *ccw_dev = CCW_DEVICE(dev);
     int len;
 
     if (!ccw->cda) {
-        return -EFAULT;
+        return CSS_DO_PGM_CHK;
     }
 
     len = ck->write_payload_3270(dev, ccw->cmd_code, ccw->cda, ccw->count);
 
     if (len <= 0) {
-        return -EIO;
+        return CSS_E_CUSTOM;
     }
 
     ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
-    return 0;
+    return CSS_DO_SUCCESS;
 }
 
-static int emulated_ccw_3270_cb(SubchDev *sch, CCW1 ccw)
+static CcwProcStatus emulated_ccw_3270_cb(SubchDev *sch, CCW1 ccw)
 {
-    int rc = 0;
+    CcwProcStatus rc = CSS_DO_SUCCESS;
     EmulatedCcw3270Device *dev = sch->driver_data;
 
     switch (ccw.cmd_code) {
@@ -72,11 +74,11 @@ static int emulated_ccw_3270_cb(SubchDev *sch, CCW1 ccw)
         rc = handle_payload_3270_read(dev, &ccw);
         break;
     default:
-        rc = -ENOSYS;
+        rc = CSS_DO_UNIT_CHK_REJ;
         break;
     }
 
-    if (rc == -EIO) {
+    if (rc == CSS_E_CUSTOM) {
         /* I/O error, specific devices generate specific conditions */
         SCSW *s = &sch->curr_status.scsw;
 
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index a9cdd54efc..875e9b00b8 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -784,20 +784,20 @@ static CCW1 copy_ccw_from_guest(hwaddr addr, bool fmt1)
     return ret;
 }
 
-static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
+static CcwProcStatus css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
                              bool suspend_allowed)
 {
-    int ret;
+    CcwProcStatus ret;
     bool check_len;
     int len;
     CCW1 ccw;
 
     if (!ccw_addr) {
-        return -EINVAL; /* channel-program check */
+        return CSS_DO_PGM_CHK;
     }
     /* Check doubleword aligned and 31 or 24 (fmt 0) bit addressable. */
     if (ccw_addr & (sch->ccw_fmt_1 ? 0x80000007 : 0xff000007)) {
-        return -EINVAL;
+        return CSS_DO_PGM_CHK;
     }
 
     /* Translate everything to format-1 ccws - the information is the same. */
@@ -805,31 +805,31 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
 
     /* Check for invalid command codes. */
     if ((ccw.cmd_code & 0x0f) == 0) {
-        return -EINVAL;
+        return CSS_DO_PGM_CHK;
     }
     if (((ccw.cmd_code & 0x0f) == CCW_CMD_TIC) &&
         ((ccw.cmd_code & 0xf0) != 0)) {
-        return -EINVAL;
+        return CSS_DO_PGM_CHK;
     }
     if (!sch->ccw_fmt_1 && (ccw.count == 0) &&
         (ccw.cmd_code != CCW_CMD_TIC)) {
-        return -EINVAL;
+        return CSS_DO_PGM_CHK;
     }
 
     /* We don't support MIDA. */
     if (ccw.flags & CCW_FLAG_MIDA) {
-        return -EINVAL;
+        return CSS_DO_PGM_CHK;
     }
 
     if (ccw.flags & CCW_FLAG_SUSPEND) {
-        return suspend_allowed ? -EINPROGRESS : -EINVAL;
+        return suspend_allowed ? CSS_DO_SUSPEND : CSS_DO_PGM_CHK;
     }
 
     check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC));
 
     if (!ccw.cda) {
         if (sch->ccw_no_data_cnt == 255) {
-            return -EINVAL;
+            return CSS_DO_PGM_CHK;
         }
         sch->ccw_no_data_cnt++;
     }
@@ -838,12 +838,12 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
     switch (ccw.cmd_code) {
     case CCW_CMD_NOOP:
         /* Nothing to do. */
-        ret = 0;
+        ret = CSS_DO_SUCCESS;
         break;
     case CCW_CMD_BASIC_SENSE:
         if (check_len) {
             if (ccw.count != sizeof(sch->sense_data)) {
-                ret = -EINVAL;
+                ret = CSS_DO_INCORR_LEN;
                 break;
             }
         }
@@ -851,7 +851,7 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
         cpu_physical_memory_write(ccw.cda, sch->sense_data, len);
         sch->curr_status.scsw.count = ccw.count - len;
         memset(sch->sense_data, 0, sizeof(sch->sense_data));
-        ret = 0;
+        ret = CSS_DO_SUCCESS;
         break;
     case CCW_CMD_SENSE_ID:
     {
@@ -861,7 +861,7 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
         /* Sense ID information is device specific. */
         if (check_len) {
             if (ccw.count != sizeof(sense_id)) {
-                ret = -EINVAL;
+                ret = CSS_DO_PGM_CHK;
                 break;
             }
         }
@@ -877,37 +877,37 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
         }
         cpu_physical_memory_write(ccw.cda, &sense_id, len);
         sch->curr_status.scsw.count = ccw.count - len;
-        ret = 0;
+        ret = CSS_DO_SUCCESS;
         break;
     }
     case CCW_CMD_TIC:
         if (sch->last_cmd_valid && (sch->last_cmd.cmd_code == CCW_CMD_TIC)) {
-            ret = -EINVAL;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         if (ccw.flags || ccw.count) {
             /* We have already sanitized these if converted from fmt 0. */
-            ret = -EINVAL;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         sch->channel_prog = ccw.cda;
-        ret = -EAGAIN;
+        ret = CSS_DO_CONT_CHAIN;
         break;
     default:
         if (sch->ccw_cb) {
             /* Handle device specific commands. */
             ret = sch->ccw_cb(sch, ccw);
         } else {
-            ret = -ENOSYS;
+            ret = CSS_DO_UNIT_CHK_REJ;
         }
         break;
     }
     sch->last_cmd = ccw;
     sch->last_cmd_valid = true;
-    if (ret == 0) {
+    if (ret == CSS_DO_SUCCESS) {
         if (ccw.flags & CCW_FLAG_CC) {
             sch->channel_prog += 8;
-            ret = -EAGAIN;
+            ret = CSS_DO_CONT_CHAIN;
         }
     }
 
@@ -920,7 +920,7 @@ static void sch_handle_start_func_virtual(SubchDev *sch)
     PMCW *p = &sch->curr_status.pmcw;
     SCSW *s = &sch->curr_status.scsw;
     int path;
-    int ret;
+    CcwProcStatus ret;
     bool suspend_allowed;
 
     /* Path management: In our simple css, we always choose the only path. */
@@ -954,10 +954,10 @@ static void sch_handle_start_func_virtual(SubchDev *sch)
     do {
         ret = css_interpret_ccw(sch, sch->channel_prog, suspend_allowed);
         switch (ret) {
-        case -EAGAIN:
+        case CSS_DO_CONT_CHAIN:
             /* ccw chain, continue processing */
             break;
-        case 0:
+        case CSS_DO_SUCCESS:
             /* success */
             s->ctrl &= ~SCSW_ACTL_START_PEND;
             s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
@@ -966,10 +966,10 @@ static void sch_handle_start_func_virtual(SubchDev *sch)
             s->dstat = SCSW_DSTAT_CHANNEL_END | SCSW_DSTAT_DEVICE_END;
             s->cpa = sch->channel_prog + 8;
             break;
-        case -EIO:
+        case CSS_E_CUSTOM:
             /* I/O errors, status depends on specific devices */
             break;
-        case -ENOSYS:
+        case CSS_DO_UNIT_CHK_REJ:
             /* unsupported command, generate unit check (command reject) */
             s->ctrl &= ~SCSW_ACTL_START_PEND;
             s->dstat = SCSW_DSTAT_UNIT_CHECK;
@@ -980,12 +980,21 @@ static void sch_handle_start_func_virtual(SubchDev *sch)
                     SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
             s->cpa = sch->channel_prog + 8;
             break;
-        case -EINPROGRESS:
+        case CSS_DO_SUSPEND:
             /* channel program has been suspended */
             s->ctrl &= ~SCSW_ACTL_START_PEND;
             s->ctrl |= SCSW_ACTL_SUSP;
             break;
-        default:
+        case CSS_DO_INCORR_LEN:
+            s->ctrl &= ~SCSW_ACTL_START_PEND;
+            s->cstat = SCSW_CSTAT_INCORR_LEN;
+            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
+            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
+                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
+            s->cpa = sch->channel_prog + 8;
+            break;
+
+        case CSS_DO_PGM_CHK:
             /* error, generate channel program check */
             s->ctrl &= ~SCSW_ACTL_START_PEND;
             s->cstat = SCSW_CSTAT_PROG_CHECK;
@@ -995,7 +1004,7 @@ static void sch_handle_start_func_virtual(SubchDev *sch)
             s->cpa = sch->channel_prog + 8;
             break;
         }
-    } while (ret == -EAGAIN);
+    } while (ret == CSS_DO_CONT_CHAIN);
 
 }
 
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index b1976fdd19..3d288b5343 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -207,16 +207,16 @@ static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info,
     uint64_t desc = info ? info->desc : linfo->queue;
 
     if (index >= VIRTIO_QUEUE_MAX) {
-        return -EINVAL;
+        return CSS_DO_PGM_CHK;
     }
 
     /* Current code in virtio.c relies on 4K alignment. */
     if (linfo && desc && (linfo->align != 4096)) {
-        return -EINVAL;
+        return CSS_DO_PGM_CHK;
     }
 
     if (!vdev) {
-        return -EINVAL;
+        return CSS_DO_PGM_CHK;
     }
 
     if (info) {
@@ -231,19 +231,19 @@ static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info,
             /* virtio-1 allows changing the ring size. */
             if (virtio_queue_get_max_num(vdev, index) < num) {
                 /* Fail if we exceed the maximum number. */
-                return -EINVAL;
+                return CSS_DO_PGM_CHK;
             }
             virtio_queue_set_num(vdev, index, num);
         } else if (virtio_queue_get_num(vdev, index) > num) {
             /* Fail if we don't have a big enough queue. */
-            return -EINVAL;
+            return CSS_DO_PGM_CHK;
         }
         /* We ignore possible increased num for legacy for compatibility. */
         virtio_queue_set_vector(vdev, index, index);
     }
     /* tell notify handler in case of config change */
     vdev->config_vector = VIRTIO_QUEUE_MAX;
-    return 0;
+    return CSS_DO_SUCCESS;
 }
 
 static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev, VirtIODevice *vdev)
@@ -277,14 +277,14 @@ static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
 
     if (check_len) {
         if (ccw.count != info_len) {
-            return -EINVAL;
+            return CSS_DO_INCORR_LEN;
         }
     } else if (ccw.count < info_len) {
         /* Can't execute command. */
-        return -EINVAL;
+        return CSS_DO_PGM_CHK;
     }
     if (!ccw.cda) {
-        return -EFAULT;
+        return CSS_DO_PGM_CHK;
     }
     if (is_legacy) {
         linfo.queue = address_space_ldq_be(&address_space_memory, ccw.cda,
@@ -336,7 +336,7 @@ static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
     return ret;
 }
 
-static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
+static CcwProcStatus virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
 {
     int ret;
     VirtioRevInfo revinfo;
@@ -353,7 +353,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
     VirtioThinintInfo *thinint;
 
     if (!dev) {
-        return -EINVAL;
+        return CSS_DO_PGM_CHK;
     }
 
     trace_virtio_ccw_interpret_ccw(sch->cssid, sch->ssid, sch->schid,
@@ -366,7 +366,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
          * virtio-1 drivers must start with negotiating to a revision >= 1,
          * so post a command reject for all other commands
          */
-        return -ENOSYS;
+        return CSS_DO_UNIT_CHK_REJ;
     }
 
     /* Look at the command. */
@@ -376,21 +376,21 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         break;
     case CCW_CMD_VDEV_RESET:
         virtio_ccw_reset_virtio(dev, vdev);
-        ret = 0;
+        ret = CSS_DO_SUCCESS;
         break;
     case CCW_CMD_READ_FEAT:
         if (check_len) {
             if (ccw.count != sizeof(features)) {
-                ret = -EINVAL;
+                ret = CSS_DO_INCORR_LEN;
                 break;
             }
         } else if (ccw.count < sizeof(features)) {
             /* Can't execute command. */
-            ret = -EINVAL;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         if (!ccw.cda) {
-            ret = -EFAULT;
+            ret = CSS_DO_PGM_CHK;
         } else {
             VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
 
@@ -421,22 +421,22 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
                                  features.features, MEMTXATTRS_UNSPECIFIED,
                                  NULL);
             sch->curr_status.scsw.count = ccw.count - sizeof(features);
-            ret = 0;
+            ret = CSS_DO_SUCCESS;
         }
         break;
     case CCW_CMD_WRITE_FEAT:
         if (check_len) {
             if (ccw.count != sizeof(features)) {
-                ret = -EINVAL;
+                ret = CSS_DO_INCORR_LEN;
                 break;
             }
         } else if (ccw.count < sizeof(features)) {
             /* Can't execute command. */
-            ret = -EINVAL;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         if (!ccw.cda) {
-            ret = -EFAULT;
+            ret = CSS_DO_PGM_CHK;
         } else {
             features.index = address_space_ldub(&address_space_memory,
                                                 ccw.cda
@@ -472,42 +472,42 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
                 }
             }
             sch->curr_status.scsw.count = ccw.count - sizeof(features);
-            ret = 0;
+            ret = CSS_DO_SUCCESS;
         }
         break;
     case CCW_CMD_READ_CONF:
         if (check_len) {
             if (ccw.count > vdev->config_len) {
-                ret = -EINVAL;
+                ret = CSS_DO_INCORR_LEN;
                 break;
             }
         }
         len = MIN(ccw.count, vdev->config_len);
         if (!ccw.cda) {
-            ret = -EFAULT;
+            ret = CSS_DO_PGM_CHK;
         } else {
             virtio_bus_get_vdev_config(&dev->bus, vdev->config);
             /* XXX config space endianness */
             cpu_physical_memory_write(ccw.cda, vdev->config, len);
             sch->curr_status.scsw.count = ccw.count - len;
-            ret = 0;
+            ret = CSS_DO_SUCCESS;
         }
         break;
     case CCW_CMD_WRITE_CONF:
         if (check_len) {
             if (ccw.count > vdev->config_len) {
-                ret = -EINVAL;
+                ret = CSS_DO_INCORR_LEN;
                 break;
             }
         }
         len = MIN(ccw.count, vdev->config_len);
         hw_len = len;
         if (!ccw.cda) {
-            ret = -EFAULT;
+            ret = CSS_DO_PGM_CHK;
         } else {
             config = cpu_physical_memory_map(ccw.cda, &hw_len, 0);
             if (!config) {
-                ret = -EFAULT;
+                ret = CSS_DO_PGM_CHK;
             } else {
                 len = hw_len;
                 /* XXX config space endianness */
@@ -515,43 +515,43 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
                 cpu_physical_memory_unmap(config, hw_len, 0, hw_len);
                 virtio_bus_set_vdev_config(&dev->bus, vdev->config);
                 sch->curr_status.scsw.count = ccw.count - len;
-                ret = 0;
+                ret = CSS_DO_SUCCESS;
             }
         }
         break;
     case CCW_CMD_READ_STATUS:
         if (check_len) {
             if (ccw.count != sizeof(status)) {
-                ret = -EINVAL;
+                ret = CSS_DO_INCORR_LEN;
                 break;
             }
         } else if (ccw.count < sizeof(status)) {
             /* Can't execute command. */
-            ret = -EINVAL;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         if (!ccw.cda) {
-            ret = -EFAULT;
+            ret = CSS_DO_PGM_CHK;
         } else {
             address_space_stb(&address_space_memory, ccw.cda, vdev->status,
                                         MEMTXATTRS_UNSPECIFIED, NULL);
             sch->curr_status.scsw.count = ccw.count - sizeof(vdev->status);;
-            ret = 0;
+            ret = CSS_DO_SUCCESS;
         }
         break;
     case CCW_CMD_WRITE_STATUS:
         if (check_len) {
             if (ccw.count != sizeof(status)) {
-                ret = -EINVAL;
+                ret = CSS_DO_INCORR_LEN;
                 break;
             }
         } else if (ccw.count < sizeof(status)) {
             /* Can't execute command. */
-            ret = -EINVAL;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         if (!ccw.cda) {
-            ret = -EFAULT;
+            ret = CSS_DO_PGM_CHK;
         } else {
             status = address_space_ldub(&address_space_memory, ccw.cda,
                                         MEMTXATTRS_UNSPECIFIED, NULL);
@@ -566,85 +566,85 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
                     virtio_ccw_start_ioeventfd(dev);
                 }
                 sch->curr_status.scsw.count = ccw.count - sizeof(status);
-                ret = 0;
+                ret = CSS_DO_SUCCESS;
             } else {
                 /* Trigger a command reject. */
-                ret = -ENOSYS;
+                ret = CSS_DO_UNIT_CHK_REJ;
             }
         }
         break;
     case CCW_CMD_SET_IND:
         if (check_len) {
             if (ccw.count != sizeof(indicators)) {
-                ret = -EINVAL;
+                ret = CSS_DO_INCORR_LEN;
                 break;
             }
         } else if (ccw.count < sizeof(indicators)) {
             /* Can't execute command. */
-            ret = -EINVAL;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         if (sch->thinint_active) {
             /* Trigger a command reject. */
-            ret = -ENOSYS;
+            ret = CSS_DO_UNIT_CHK_REJ;
             break;
         }
         if (virtio_get_num_queues(vdev) > NR_CLASSIC_INDICATOR_BITS) {
             /* More queues than indicator bits --> trigger a reject */
-            ret = -ENOSYS;
+            ret = CSS_DO_UNIT_CHK_REJ;
             break;
         }
         if (!ccw.cda) {
-            ret = -EFAULT;
+            ret = CSS_DO_PGM_CHK;
         } else {
             indicators = address_space_ldq_be(&address_space_memory, ccw.cda,
                                               MEMTXATTRS_UNSPECIFIED, NULL);
             dev->indicators = get_indicator(indicators, sizeof(uint64_t));
             sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
-            ret = 0;
+            ret = CSS_DO_SUCCESS;
         }
         break;
     case CCW_CMD_SET_CONF_IND:
         if (check_len) {
             if (ccw.count != sizeof(indicators)) {
-                ret = -EINVAL;
+                ret = CSS_DO_INCORR_LEN;
                 break;
             }
         } else if (ccw.count < sizeof(indicators)) {
             /* Can't execute command. */
-            ret = -EINVAL;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         if (!ccw.cda) {
-            ret = -EFAULT;
+            ret = CSS_DO_PGM_CHK;
         } else {
             indicators = address_space_ldq_be(&address_space_memory, ccw.cda,
                                               MEMTXATTRS_UNSPECIFIED, NULL);
             dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
             sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
-            ret = 0;
+            ret = CSS_DO_SUCCESS;
         }
         break;
     case CCW_CMD_READ_VQ_CONF:
         if (check_len) {
             if (ccw.count != sizeof(vq_config)) {
-                ret = -EINVAL;
+                ret = CSS_DO_INCORR_LEN;
                 break;
             }
         } else if (ccw.count < sizeof(vq_config)) {
             /* Can't execute command. */
-            ret = -EINVAL;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         if (!ccw.cda) {
-            ret = -EFAULT;
+            ret = CSS_DO_PGM_CHK;
         } else {
             vq_config.index = address_space_lduw_be(&address_space_memory,
                                                     ccw.cda,
                                                     MEMTXATTRS_UNSPECIFIED,
                                                     NULL);
             if (vq_config.index >= VIRTIO_QUEUE_MAX) {
-                ret = -EINVAL;
+                ret = CSS_DO_PGM_CHK;
                 break;
             }
             vq_config.num_max = virtio_queue_get_num(vdev,
@@ -655,31 +655,31 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
                                  MEMTXATTRS_UNSPECIFIED,
                                  NULL);
             sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
-            ret = 0;
+            ret = CSS_DO_SUCCESS;
         }
         break;
     case CCW_CMD_SET_IND_ADAPTER:
         if (check_len) {
             if (ccw.count != sizeof(*thinint)) {
-                ret = -EINVAL;
+                ret = CSS_DO_INCORR_LEN;
                 break;
             }
         } else if (ccw.count < sizeof(*thinint)) {
             /* Can't execute command. */
-            ret = -EINVAL;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         len = sizeof(*thinint);
         hw_len = len;
         if (!ccw.cda) {
-            ret = -EFAULT;
+            ret = CSS_DO_PGM_CHK;
         } else if (dev->indicators && !sch->thinint_active) {
             /* Trigger a command reject. */
-            ret = -ENOSYS;
+            ret = CSS_DO_UNIT_CHK_REJ;
         } else {
             thinint = cpu_physical_memory_map(ccw.cda, &hw_len, 0);
             if (!thinint) {
-                ret = -EFAULT;
+                ret = CSS_DO_PGM_CHK;
             } else {
                 uint64_t ind_bit = ldq_be_p(&thinint->ind_bit);
 
@@ -700,18 +700,18 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
                 sch->thinint_active = ((dev->indicators != NULL) &&
                                        (dev->summary_indicator != NULL));
                 sch->curr_status.scsw.count = ccw.count - len;
-                ret = 0;
+                ret = CSS_DO_SUCCESS;
             }
         }
         break;
     case CCW_CMD_SET_VIRTIO_REV:
         len = sizeof(revinfo);
         if (ccw.count < len) {
-            ret = -EINVAL;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         if (!ccw.cda) {
-            ret = -EFAULT;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         revinfo.revision =
@@ -723,7 +723,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
                                   MEMTXATTRS_UNSPECIFIED, NULL);
         if (ccw.count < len + revinfo.length ||
             (check_len && ccw.count > len + revinfo.length)) {
-            ret = -EINVAL;
+            ret = CSS_DO_PGM_CHK;
             break;
         }
         /*
@@ -733,14 +733,14 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
         if (dev->revision >= 0 ||
             revinfo.revision > virtio_ccw_rev_max(dev) ||
             (dev->force_revision_1 && !revinfo.revision)) {
-            ret = -ENOSYS;
+            ret = CSS_DO_UNIT_CHK_REJ;
             break;
         }
-        ret = 0;
+        ret = CSS_DO_SUCCESS;
         dev->revision = revinfo.revision;
         break;
     default:
-        ret = -ENOSYS;
+        ret = CSS_DO_UNIT_CHK_REJ;
         break;
     }
     return ret;
diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h
index 0653d3c9be..da518580be 100644
--- a/include/hw/s390x/css.h
+++ b/include/hw/s390x/css.h
@@ -75,6 +75,17 @@ typedef struct CMBE {
     uint32_t reserved[7];
 } QEMU_PACKED CMBE;
 
+
+typedef enum CcwProcStatus {
+        CSS_DO_SUCCESS = 0, /* requet successful completin */
+        CSS_DO_CONT_CHAIN,  /* request continue ccw-chaning */
+        CSS_DO_SUSPEND,     /* request subchannel suspended */
+        CSS_DO_PGM_CHK,     /* request channel-program check */
+        CSS_DO_UNIT_CHK_REJ,/* request unit check cmd reject */
+        CSS_DO_INCORR_LEN,  /* request incorrect length */
+        CSS_E_CUSTOM        /* SCSW updated by device */
+} CcwProcStatus;
+
 typedef struct SubchDev SubchDev;
 struct SubchDev {
     /* channel-subsystem related things: */
@@ -93,7 +104,7 @@ struct SubchDev {
     uint16_t migrated_schid; /* used for missmatch detection */
     ORB orb;
     /* transport-provided data: */
-    int (*ccw_cb) (SubchDev *, CCW1);
+    CcwProcStatus (*ccw_cb) (SubchDev *, CCW1);
     void (*disable_cb)(SubchDev *);
     int (*do_subchannel_work) (SubchDev *);
     SenseId id;
