qemu/hw/s390x/css.c
<<
>>
Prefs
   1/*
   2 * Channel subsystem base support.
   3 *
   4 * Copyright 2012 IBM Corp.
   5 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
   6 *
   7 * This work is licensed under the terms of the GNU GPL, version 2 or (at
   8 * your option) any later version. See the COPYING file in the top-level
   9 * directory.
  10 */
  11
  12#include <hw/qdev.h>
  13#include "qemu/bitops.h"
  14#include "cpu.h"
  15#include "ioinst.h"
  16#include "css.h"
  17#include "trace.h"
  18
  19typedef struct CrwContainer {
  20    CRW crw;
  21    QTAILQ_ENTRY(CrwContainer) sibling;
  22} CrwContainer;
  23
  24typedef struct ChpInfo {
  25    uint8_t in_use;
  26    uint8_t type;
  27    uint8_t is_virtual;
  28} ChpInfo;
  29
  30typedef struct SubchSet {
  31    SubchDev *sch[MAX_SCHID + 1];
  32    unsigned long schids_used[BITS_TO_LONGS(MAX_SCHID + 1)];
  33    unsigned long devnos_used[BITS_TO_LONGS(MAX_SCHID + 1)];
  34} SubchSet;
  35
  36typedef struct CssImage {
  37    SubchSet *sch_set[MAX_SSID + 1];
  38    ChpInfo chpids[MAX_CHPID + 1];
  39} CssImage;
  40
  41typedef struct ChannelSubSys {
  42    QTAILQ_HEAD(, CrwContainer) pending_crws;
  43    bool do_crw_mchk;
  44    bool crws_lost;
  45    uint8_t max_cssid;
  46    uint8_t max_ssid;
  47    bool chnmon_active;
  48    uint64_t chnmon_area;
  49    CssImage *css[MAX_CSSID + 1];
  50    uint8_t default_cssid;
  51} ChannelSubSys;
  52
  53static ChannelSubSys *channel_subsys;
  54
  55int css_create_css_image(uint8_t cssid, bool default_image)
  56{
  57    trace_css_new_image(cssid, default_image ? "(default)" : "");
  58    if (cssid > MAX_CSSID) {
  59        return -EINVAL;
  60    }
  61    if (channel_subsys->css[cssid]) {
  62        return -EBUSY;
  63    }
  64    channel_subsys->css[cssid] = g_malloc0(sizeof(CssImage));
  65    if (default_image) {
  66        channel_subsys->default_cssid = cssid;
  67    }
  68    return 0;
  69}
  70
  71uint16_t css_build_subchannel_id(SubchDev *sch)
  72{
  73    if (channel_subsys->max_cssid > 0) {
  74        return (sch->cssid << 8) | (1 << 3) | (sch->ssid << 1) | 1;
  75    }
  76    return (sch->ssid << 1) | 1;
  77}
  78
  79static void css_inject_io_interrupt(SubchDev *sch)
  80{
  81    S390CPU *cpu = s390_cpu_addr2state(0);
  82    uint8_t isc = (sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ISC) >> 11;
  83
  84    trace_css_io_interrupt(sch->cssid, sch->ssid, sch->schid,
  85                           sch->curr_status.pmcw.intparm, isc, "");
  86    s390_io_interrupt(cpu,
  87                      css_build_subchannel_id(sch),
  88                      sch->schid,
  89                      sch->curr_status.pmcw.intparm,
  90                      isc << 27);
  91}
  92
  93void css_conditional_io_interrupt(SubchDev *sch)
  94{
  95    /*
  96     * If the subchannel is not currently status pending, make it pending
  97     * with alert status.
  98     */
  99    if (!(sch->curr_status.scsw.ctrl & SCSW_STCTL_STATUS_PEND)) {
 100        S390CPU *cpu = s390_cpu_addr2state(0);
 101        uint8_t isc = (sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ISC) >> 11;
 102
 103        trace_css_io_interrupt(sch->cssid, sch->ssid, sch->schid,
 104                               sch->curr_status.pmcw.intparm, isc,
 105                               "(unsolicited)");
 106        sch->curr_status.scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
 107        sch->curr_status.scsw.ctrl |=
 108            SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
 109        /* Inject an I/O interrupt. */
 110        s390_io_interrupt(cpu,
 111                          css_build_subchannel_id(sch),
 112                          sch->schid,
 113                          sch->curr_status.pmcw.intparm,
 114                          isc << 27);
 115    }
 116}
 117
 118static void sch_handle_clear_func(SubchDev *sch)
 119{
 120    PMCW *p = &sch->curr_status.pmcw;
 121    SCSW *s = &sch->curr_status.scsw;
 122    int path;
 123
 124    /* Path management: In our simple css, we always choose the only path. */
 125    path = 0x80;
 126
 127    /* Reset values prior to 'issuing the clear signal'. */
 128    p->lpum = 0;
 129    p->pom = 0xff;
 130    s->flags &= ~SCSW_FLAGS_MASK_PNO;
 131
 132    /* We always 'attempt to issue the clear signal', and we always succeed. */
 133    sch->orb = NULL;
 134    sch->channel_prog = 0x0;
 135    sch->last_cmd_valid = false;
 136    s->ctrl &= ~SCSW_ACTL_CLEAR_PEND;
 137    s->ctrl |= SCSW_STCTL_STATUS_PEND;
 138
 139    s->dstat = 0;
 140    s->cstat = 0;
 141    p->lpum = path;
 142
 143}
 144
 145static void sch_handle_halt_func(SubchDev *sch)
 146{
 147
 148    PMCW *p = &sch->curr_status.pmcw;
 149    SCSW *s = &sch->curr_status.scsw;
 150    int path;
 151
 152    /* Path management: In our simple css, we always choose the only path. */
 153    path = 0x80;
 154
 155    /* We always 'attempt to issue the halt signal', and we always succeed. */
 156    sch->orb = NULL;
 157    sch->channel_prog = 0x0;
 158    sch->last_cmd_valid = false;
 159    s->ctrl &= ~SCSW_ACTL_HALT_PEND;
 160    s->ctrl |= SCSW_STCTL_STATUS_PEND;
 161
 162    if ((s->ctrl & (SCSW_ACTL_SUBCH_ACTIVE | SCSW_ACTL_DEVICE_ACTIVE)) ||
 163        !((s->ctrl & SCSW_ACTL_START_PEND) ||
 164          (s->ctrl & SCSW_ACTL_SUSP))) {
 165        s->dstat = SCSW_DSTAT_DEVICE_END;
 166    }
 167    s->cstat = 0;
 168    p->lpum = path;
 169
 170}
 171
 172static void copy_sense_id_to_guest(SenseId *dest, SenseId *src)
 173{
 174    int i;
 175
 176    dest->reserved = src->reserved;
 177    dest->cu_type = cpu_to_be16(src->cu_type);
 178    dest->cu_model = src->cu_model;
 179    dest->dev_type = cpu_to_be16(src->dev_type);
 180    dest->dev_model = src->dev_model;
 181    dest->unused = src->unused;
 182    for (i = 0; i < ARRAY_SIZE(dest->ciw); i++) {
 183        dest->ciw[i].type = src->ciw[i].type;
 184        dest->ciw[i].command = src->ciw[i].command;
 185        dest->ciw[i].count = cpu_to_be16(src->ciw[i].count);
 186    }
 187}
 188
 189static CCW1 copy_ccw_from_guest(hwaddr addr)
 190{
 191    CCW1 tmp;
 192    CCW1 ret;
 193
 194    cpu_physical_memory_read(addr, &tmp, sizeof(tmp));
 195    ret.cmd_code = tmp.cmd_code;
 196    ret.flags = tmp.flags;
 197    ret.count = be16_to_cpu(tmp.count);
 198    ret.cda = be32_to_cpu(tmp.cda);
 199
 200    return ret;
 201}
 202
 203static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr)
 204{
 205    int ret;
 206    bool check_len;
 207    int len;
 208    CCW1 ccw;
 209
 210    if (!ccw_addr) {
 211        return -EIO;
 212    }
 213
 214    ccw = copy_ccw_from_guest(ccw_addr);
 215
 216    /* Check for invalid command codes. */
 217    if ((ccw.cmd_code & 0x0f) == 0) {
 218        return -EINVAL;
 219    }
 220    if (((ccw.cmd_code & 0x0f) == CCW_CMD_TIC) &&
 221        ((ccw.cmd_code & 0xf0) != 0)) {
 222        return -EINVAL;
 223    }
 224
 225    if (ccw.flags & CCW_FLAG_SUSPEND) {
 226        return -EINPROGRESS;
 227    }
 228
 229    check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC));
 230
 231    /* Look at the command. */
 232    switch (ccw.cmd_code) {
 233    case CCW_CMD_NOOP:
 234        /* Nothing to do. */
 235        ret = 0;
 236        break;
 237    case CCW_CMD_BASIC_SENSE:
 238        if (check_len) {
 239            if (ccw.count != sizeof(sch->sense_data)) {
 240                ret = -EINVAL;
 241                break;
 242            }
 243        }
 244        len = MIN(ccw.count, sizeof(sch->sense_data));
 245        cpu_physical_memory_write(ccw.cda, sch->sense_data, len);
 246        sch->curr_status.scsw.count = ccw.count - len;
 247        memset(sch->sense_data, 0, sizeof(sch->sense_data));
 248        ret = 0;
 249        break;
 250    case CCW_CMD_SENSE_ID:
 251    {
 252        SenseId sense_id;
 253
 254        copy_sense_id_to_guest(&sense_id, &sch->id);
 255        /* Sense ID information is device specific. */
 256        if (check_len) {
 257            if (ccw.count != sizeof(sense_id)) {
 258                ret = -EINVAL;
 259                break;
 260            }
 261        }
 262        len = MIN(ccw.count, sizeof(sense_id));
 263        /*
 264         * Only indicate 0xff in the first sense byte if we actually
 265         * have enough place to store at least bytes 0-3.
 266         */
 267        if (len >= 4) {
 268            sense_id.reserved = 0xff;
 269        } else {
 270            sense_id.reserved = 0;
 271        }
 272        cpu_physical_memory_write(ccw.cda, &sense_id, len);
 273        sch->curr_status.scsw.count = ccw.count - len;
 274        ret = 0;
 275        break;
 276    }
 277    case CCW_CMD_TIC:
 278        if (sch->last_cmd_valid && (sch->last_cmd.cmd_code == CCW_CMD_TIC)) {
 279            ret = -EINVAL;
 280            break;
 281        }
 282        if (ccw.flags & (CCW_FLAG_CC | CCW_FLAG_DC)) {
 283            ret = -EINVAL;
 284            break;
 285        }
 286        sch->channel_prog = ccw.cda;
 287        ret = -EAGAIN;
 288        break;
 289    default:
 290        if (sch->ccw_cb) {
 291            /* Handle device specific commands. */
 292            ret = sch->ccw_cb(sch, ccw);
 293        } else {
 294            ret = -ENOSYS;
 295        }
 296        break;
 297    }
 298    sch->last_cmd = ccw;
 299    sch->last_cmd_valid = true;
 300    if (ret == 0) {
 301        if (ccw.flags & CCW_FLAG_CC) {
 302            sch->channel_prog += 8;
 303            ret = -EAGAIN;
 304        }
 305    }
 306
 307    return ret;
 308}
 309
 310static void sch_handle_start_func(SubchDev *sch)
 311{
 312
 313    PMCW *p = &sch->curr_status.pmcw;
 314    SCSW *s = &sch->curr_status.scsw;
 315    ORB *orb = sch->orb;
 316    int path;
 317    int ret;
 318
 319    /* Path management: In our simple css, we always choose the only path. */
 320    path = 0x80;
 321
 322    if (!(s->ctrl & SCSW_ACTL_SUSP)) {
 323        /* Look at the orb and try to execute the channel program. */
 324        p->intparm = orb->intparm;
 325        if (!(orb->lpm & path)) {
 326            /* Generate a deferred cc 3 condition. */
 327            s->flags |= SCSW_FLAGS_MASK_CC;
 328            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
 329            s->ctrl |= (SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND);
 330            return;
 331        }
 332    } else {
 333        s->ctrl &= ~(SCSW_ACTL_SUSP | SCSW_ACTL_RESUME_PEND);
 334    }
 335    sch->last_cmd_valid = false;
 336    do {
 337        ret = css_interpret_ccw(sch, sch->channel_prog);
 338        switch (ret) {
 339        case -EAGAIN:
 340            /* ccw chain, continue processing */
 341            break;
 342        case 0:
 343            /* success */
 344            s->ctrl &= ~SCSW_ACTL_START_PEND;
 345            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
 346            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
 347                    SCSW_STCTL_STATUS_PEND;
 348            s->dstat = SCSW_DSTAT_CHANNEL_END | SCSW_DSTAT_DEVICE_END;
 349            break;
 350        case -ENOSYS:
 351            /* unsupported command, generate unit check (command reject) */
 352            s->ctrl &= ~SCSW_ACTL_START_PEND;
 353            s->dstat = SCSW_DSTAT_UNIT_CHECK;
 354            /* Set sense bit 0 in ecw0. */
 355            sch->sense_data[0] = 0x80;
 356            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
 357            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
 358                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
 359            break;
 360        case -EFAULT:
 361            /* memory problem, generate channel data check */
 362            s->ctrl &= ~SCSW_ACTL_START_PEND;
 363            s->cstat = SCSW_CSTAT_DATA_CHECK;
 364            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
 365            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
 366                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
 367            break;
 368        case -EBUSY:
 369            /* subchannel busy, generate deferred cc 1 */
 370            s->flags &= ~SCSW_FLAGS_MASK_CC;
 371            s->flags |= (1 << 8);
 372            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
 373            s->ctrl |= SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
 374            break;
 375        case -EINPROGRESS:
 376            /* channel program has been suspended */
 377            s->ctrl &= ~SCSW_ACTL_START_PEND;
 378            s->ctrl |= SCSW_ACTL_SUSP;
 379            break;
 380        default:
 381            /* error, generate channel program check */
 382            s->ctrl &= ~SCSW_ACTL_START_PEND;
 383            s->cstat = SCSW_CSTAT_PROG_CHECK;
 384            s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
 385            s->ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
 386                    SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
 387            break;
 388        }
 389    } while (ret == -EAGAIN);
 390
 391}
 392
 393/*
 394 * On real machines, this would run asynchronously to the main vcpus.
 395 * We might want to make some parts of the ssch handling (interpreting
 396 * read/writes) asynchronous later on if we start supporting more than
 397 * our current very simple devices.
 398 */
 399static void do_subchannel_work(SubchDev *sch)
 400{
 401
 402    SCSW *s = &sch->curr_status.scsw;
 403
 404    if (s->ctrl & SCSW_FCTL_CLEAR_FUNC) {
 405        sch_handle_clear_func(sch);
 406    } else if (s->ctrl & SCSW_FCTL_HALT_FUNC) {
 407        sch_handle_halt_func(sch);
 408    } else if (s->ctrl & SCSW_FCTL_START_FUNC) {
 409        sch_handle_start_func(sch);
 410    } else {
 411        /* Cannot happen. */
 412        return;
 413    }
 414    css_inject_io_interrupt(sch);
 415}
 416
 417static void copy_pmcw_to_guest(PMCW *dest, const PMCW *src)
 418{
 419    int i;
 420
 421    dest->intparm = cpu_to_be32(src->intparm);
 422    dest->flags = cpu_to_be16(src->flags);
 423    dest->devno = cpu_to_be16(src->devno);
 424    dest->lpm = src->lpm;
 425    dest->pnom = src->pnom;
 426    dest->lpum = src->lpum;
 427    dest->pim = src->pim;
 428    dest->mbi = cpu_to_be16(src->mbi);
 429    dest->pom = src->pom;
 430    dest->pam = src->pam;
 431    for (i = 0; i < ARRAY_SIZE(dest->chpid); i++) {
 432        dest->chpid[i] = src->chpid[i];
 433    }
 434    dest->chars = cpu_to_be32(src->chars);
 435}
 436
 437static void copy_scsw_to_guest(SCSW *dest, const SCSW *src)
 438{
 439    dest->flags = cpu_to_be16(src->flags);
 440    dest->ctrl = cpu_to_be16(src->ctrl);
 441    dest->cpa = cpu_to_be32(src->cpa);
 442    dest->dstat = src->dstat;
 443    dest->cstat = src->cstat;
 444    dest->count = cpu_to_be16(src->count);
 445}
 446
 447static void copy_schib_to_guest(SCHIB *dest, const SCHIB *src)
 448{
 449    int i;
 450
 451    copy_pmcw_to_guest(&dest->pmcw, &src->pmcw);
 452    copy_scsw_to_guest(&dest->scsw, &src->scsw);
 453    dest->mba = cpu_to_be64(src->mba);
 454    for (i = 0; i < ARRAY_SIZE(dest->mda); i++) {
 455        dest->mda[i] = src->mda[i];
 456    }
 457}
 458
 459int css_do_stsch(SubchDev *sch, SCHIB *schib)
 460{
 461    /* Use current status. */
 462    copy_schib_to_guest(schib, &sch->curr_status);
 463    return 0;
 464}
 465
 466static void copy_pmcw_from_guest(PMCW *dest, const PMCW *src)
 467{
 468    int i;
 469
 470    dest->intparm = be32_to_cpu(src->intparm);
 471    dest->flags = be16_to_cpu(src->flags);
 472    dest->devno = be16_to_cpu(src->devno);
 473    dest->lpm = src->lpm;
 474    dest->pnom = src->pnom;
 475    dest->lpum = src->lpum;
 476    dest->pim = src->pim;
 477    dest->mbi = be16_to_cpu(src->mbi);
 478    dest->pom = src->pom;
 479    dest->pam = src->pam;
 480    for (i = 0; i < ARRAY_SIZE(dest->chpid); i++) {
 481        dest->chpid[i] = src->chpid[i];
 482    }
 483    dest->chars = be32_to_cpu(src->chars);
 484}
 485
 486static void copy_scsw_from_guest(SCSW *dest, const SCSW *src)
 487{
 488    dest->flags = be16_to_cpu(src->flags);
 489    dest->ctrl = be16_to_cpu(src->ctrl);
 490    dest->cpa = be32_to_cpu(src->cpa);
 491    dest->dstat = src->dstat;
 492    dest->cstat = src->cstat;
 493    dest->count = be16_to_cpu(src->count);
 494}
 495
 496static void copy_schib_from_guest(SCHIB *dest, const SCHIB *src)
 497{
 498    int i;
 499
 500    copy_pmcw_from_guest(&dest->pmcw, &src->pmcw);
 501    copy_scsw_from_guest(&dest->scsw, &src->scsw);
 502    dest->mba = be64_to_cpu(src->mba);
 503    for (i = 0; i < ARRAY_SIZE(dest->mda); i++) {
 504        dest->mda[i] = src->mda[i];
 505    }
 506}
 507
 508int css_do_msch(SubchDev *sch, SCHIB *orig_schib)
 509{
 510    SCSW *s = &sch->curr_status.scsw;
 511    PMCW *p = &sch->curr_status.pmcw;
 512    int ret;
 513    SCHIB schib;
 514
 515    if (!(sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_DNV)) {
 516        ret = 0;
 517        goto out;
 518    }
 519
 520    if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
 521        ret = -EINPROGRESS;
 522        goto out;
 523    }
 524
 525    if (s->ctrl &
 526        (SCSW_FCTL_START_FUNC|SCSW_FCTL_HALT_FUNC|SCSW_FCTL_CLEAR_FUNC)) {
 527        ret = -EBUSY;
 528        goto out;
 529    }
 530
 531    copy_schib_from_guest(&schib, orig_schib);
 532    /* Only update the program-modifiable fields. */
 533    p->intparm = schib.pmcw.intparm;
 534    p->flags &= ~(PMCW_FLAGS_MASK_ISC | PMCW_FLAGS_MASK_ENA |
 535                  PMCW_FLAGS_MASK_LM | PMCW_FLAGS_MASK_MME |
 536                  PMCW_FLAGS_MASK_MP);
 537    p->flags |= schib.pmcw.flags &
 538            (PMCW_FLAGS_MASK_ISC | PMCW_FLAGS_MASK_ENA |
 539             PMCW_FLAGS_MASK_LM | PMCW_FLAGS_MASK_MME |
 540             PMCW_FLAGS_MASK_MP);
 541    p->lpm = schib.pmcw.lpm;
 542    p->mbi = schib.pmcw.mbi;
 543    p->pom = schib.pmcw.pom;
 544    p->chars &= ~(PMCW_CHARS_MASK_MBFC | PMCW_CHARS_MASK_CSENSE);
 545    p->chars |= schib.pmcw.chars &
 546            (PMCW_CHARS_MASK_MBFC | PMCW_CHARS_MASK_CSENSE);
 547    sch->curr_status.mba = schib.mba;
 548
 549    ret = 0;
 550
 551out:
 552    return ret;
 553}
 554
 555int css_do_xsch(SubchDev *sch)
 556{
 557    SCSW *s = &sch->curr_status.scsw;
 558    PMCW *p = &sch->curr_status.pmcw;
 559    int ret;
 560
 561    if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
 562        ret = -ENODEV;
 563        goto out;
 564    }
 565
 566    if (!(s->ctrl & SCSW_CTRL_MASK_FCTL) ||
 567        ((s->ctrl & SCSW_CTRL_MASK_FCTL) != SCSW_FCTL_START_FUNC) ||
 568        (!(s->ctrl &
 569           (SCSW_ACTL_RESUME_PEND | SCSW_ACTL_START_PEND | SCSW_ACTL_SUSP))) ||
 570        (s->ctrl & SCSW_ACTL_SUBCH_ACTIVE)) {
 571        ret = -EINPROGRESS;
 572        goto out;
 573    }
 574
 575    if (s->ctrl & SCSW_CTRL_MASK_STCTL) {
 576        ret = -EBUSY;
 577        goto out;
 578    }
 579
 580    /* Cancel the current operation. */
 581    s->ctrl &= ~(SCSW_FCTL_START_FUNC |
 582                 SCSW_ACTL_RESUME_PEND |
 583                 SCSW_ACTL_START_PEND |
 584                 SCSW_ACTL_SUSP);
 585    sch->channel_prog = 0x0;
 586    sch->last_cmd_valid = false;
 587    sch->orb = NULL;
 588    s->dstat = 0;
 589    s->cstat = 0;
 590    ret = 0;
 591
 592out:
 593    return ret;
 594}
 595
 596int css_do_csch(SubchDev *sch)
 597{
 598    SCSW *s = &sch->curr_status.scsw;
 599    PMCW *p = &sch->curr_status.pmcw;
 600    int ret;
 601
 602    if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
 603        ret = -ENODEV;
 604        goto out;
 605    }
 606
 607    /* Trigger the clear function. */
 608    s->ctrl &= ~(SCSW_CTRL_MASK_FCTL | SCSW_CTRL_MASK_ACTL);
 609    s->ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_CLEAR_FUNC;
 610
 611    do_subchannel_work(sch);
 612    ret = 0;
 613
 614out:
 615    return ret;
 616}
 617
 618int css_do_hsch(SubchDev *sch)
 619{
 620    SCSW *s = &sch->curr_status.scsw;
 621    PMCW *p = &sch->curr_status.pmcw;
 622    int ret;
 623
 624    if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
 625        ret = -ENODEV;
 626        goto out;
 627    }
 628
 629    if (((s->ctrl & SCSW_CTRL_MASK_STCTL) == SCSW_STCTL_STATUS_PEND) ||
 630        (s->ctrl & (SCSW_STCTL_PRIMARY |
 631                    SCSW_STCTL_SECONDARY |
 632                    SCSW_STCTL_ALERT))) {
 633        ret = -EINPROGRESS;
 634        goto out;
 635    }
 636
 637    if (s->ctrl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
 638        ret = -EBUSY;
 639        goto out;
 640    }
 641
 642    /* Trigger the halt function. */
 643    s->ctrl |= SCSW_FCTL_HALT_FUNC;
 644    s->ctrl &= ~SCSW_FCTL_START_FUNC;
 645    if (((s->ctrl & SCSW_CTRL_MASK_ACTL) ==
 646         (SCSW_ACTL_SUBCH_ACTIVE | SCSW_ACTL_DEVICE_ACTIVE)) &&
 647        ((s->ctrl & SCSW_CTRL_MASK_STCTL) == SCSW_STCTL_INTERMEDIATE)) {
 648        s->ctrl &= ~SCSW_STCTL_STATUS_PEND;
 649    }
 650    s->ctrl |= SCSW_ACTL_HALT_PEND;
 651
 652    do_subchannel_work(sch);
 653    ret = 0;
 654
 655out:
 656    return ret;
 657}
 658
 659static void css_update_chnmon(SubchDev *sch)
 660{
 661    if (!(sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_MME)) {
 662        /* Not active. */
 663        return;
 664    }
 665    /* The counter is conveniently located at the beginning of the struct. */
 666    if (sch->curr_status.pmcw.chars & PMCW_CHARS_MASK_MBFC) {
 667        /* Format 1, per-subchannel area. */
 668        uint32_t count;
 669
 670        count = ldl_phys(sch->curr_status.mba);
 671        count++;
 672        stl_phys(sch->curr_status.mba, count);
 673    } else {
 674        /* Format 0, global area. */
 675        uint32_t offset;
 676        uint16_t count;
 677
 678        offset = sch->curr_status.pmcw.mbi << 5;
 679        count = lduw_phys(channel_subsys->chnmon_area + offset);
 680        count++;
 681        stw_phys(channel_subsys->chnmon_area + offset, count);
 682    }
 683}
 684
 685int css_do_ssch(SubchDev *sch, ORB *orb)
 686{
 687    SCSW *s = &sch->curr_status.scsw;
 688    PMCW *p = &sch->curr_status.pmcw;
 689    int ret;
 690
 691    if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
 692        ret = -ENODEV;
 693        goto out;
 694    }
 695
 696    if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
 697        ret = -EINPROGRESS;
 698        goto out;
 699    }
 700
 701    if (s->ctrl & (SCSW_FCTL_START_FUNC |
 702                   SCSW_FCTL_HALT_FUNC |
 703                   SCSW_FCTL_CLEAR_FUNC)) {
 704        ret = -EBUSY;
 705        goto out;
 706    }
 707
 708    /* If monitoring is active, update counter. */
 709    if (channel_subsys->chnmon_active) {
 710        css_update_chnmon(sch);
 711    }
 712    sch->orb = orb;
 713    sch->channel_prog = orb->cpa;
 714    /* Trigger the start function. */
 715    s->ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND);
 716    s->flags &= ~SCSW_FLAGS_MASK_PNO;
 717
 718    do_subchannel_work(sch);
 719    ret = 0;
 720
 721out:
 722    return ret;
 723}
 724
 725static void copy_irb_to_guest(IRB *dest, const IRB *src)
 726{
 727    int i;
 728
 729    copy_scsw_to_guest(&dest->scsw, &src->scsw);
 730
 731    for (i = 0; i < ARRAY_SIZE(dest->esw); i++) {
 732        dest->esw[i] = cpu_to_be32(src->esw[i]);
 733    }
 734    for (i = 0; i < ARRAY_SIZE(dest->ecw); i++) {
 735        dest->ecw[i] = cpu_to_be32(src->ecw[i]);
 736    }
 737    for (i = 0; i < ARRAY_SIZE(dest->emw); i++) {
 738        dest->emw[i] = cpu_to_be32(src->emw[i]);
 739    }
 740}
 741
 742int css_do_tsch(SubchDev *sch, IRB *target_irb)
 743{
 744    SCSW *s = &sch->curr_status.scsw;
 745    PMCW *p = &sch->curr_status.pmcw;
 746    uint16_t stctl;
 747    uint16_t fctl;
 748    uint16_t actl;
 749    IRB irb;
 750    int ret;
 751
 752    if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
 753        ret = 3;
 754        goto out;
 755    }
 756
 757    stctl = s->ctrl & SCSW_CTRL_MASK_STCTL;
 758    fctl = s->ctrl & SCSW_CTRL_MASK_FCTL;
 759    actl = s->ctrl & SCSW_CTRL_MASK_ACTL;
 760
 761    /* Prepare the irb for the guest. */
 762    memset(&irb, 0, sizeof(IRB));
 763
 764    /* Copy scsw from current status. */
 765    memcpy(&irb.scsw, s, sizeof(SCSW));
 766    if (stctl & SCSW_STCTL_STATUS_PEND) {
 767        if (s->cstat & (SCSW_CSTAT_DATA_CHECK |
 768                        SCSW_CSTAT_CHN_CTRL_CHK |
 769                        SCSW_CSTAT_INTF_CTRL_CHK)) {
 770            irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF;
 771            irb.esw[0] = 0x04804000;
 772        } else {
 773            irb.esw[0] = 0x00800000;
 774        }
 775        /* If a unit check is pending, copy sense data. */
 776        if ((s->dstat & SCSW_DSTAT_UNIT_CHECK) &&
 777            (p->chars & PMCW_CHARS_MASK_CSENSE)) {
 778            irb.scsw.flags |= SCSW_FLAGS_MASK_ESWF | SCSW_FLAGS_MASK_ECTL;
 779            memcpy(irb.ecw, sch->sense_data, sizeof(sch->sense_data));
 780            irb.esw[1] = 0x01000000 | (sizeof(sch->sense_data) << 8);
 781        }
 782    }
 783    /* Store the irb to the guest. */
 784    copy_irb_to_guest(target_irb, &irb);
 785
 786    /* Clear conditions on subchannel, if applicable. */
 787    if (stctl & SCSW_STCTL_STATUS_PEND) {
 788        s->ctrl &= ~SCSW_CTRL_MASK_STCTL;
 789        if ((stctl != (SCSW_STCTL_INTERMEDIATE | SCSW_STCTL_STATUS_PEND)) ||
 790            ((fctl & SCSW_FCTL_HALT_FUNC) &&
 791             (actl & SCSW_ACTL_SUSP))) {
 792            s->ctrl &= ~SCSW_CTRL_MASK_FCTL;
 793        }
 794        if (stctl != (SCSW_STCTL_INTERMEDIATE | SCSW_STCTL_STATUS_PEND)) {
 795            s->flags &= ~SCSW_FLAGS_MASK_PNO;
 796            s->ctrl &= ~(SCSW_ACTL_RESUME_PEND |
 797                         SCSW_ACTL_START_PEND |
 798                         SCSW_ACTL_HALT_PEND |
 799                         SCSW_ACTL_CLEAR_PEND |
 800                         SCSW_ACTL_SUSP);
 801        } else {
 802            if ((actl & SCSW_ACTL_SUSP) &&
 803                (fctl & SCSW_FCTL_START_FUNC)) {
 804                s->flags &= ~SCSW_FLAGS_MASK_PNO;
 805                if (fctl & SCSW_FCTL_HALT_FUNC) {
 806                    s->ctrl &= ~(SCSW_ACTL_RESUME_PEND |
 807                                 SCSW_ACTL_START_PEND |
 808                                 SCSW_ACTL_HALT_PEND |
 809                                 SCSW_ACTL_CLEAR_PEND |
 810                                 SCSW_ACTL_SUSP);
 811                } else {
 812                    s->ctrl &= ~SCSW_ACTL_RESUME_PEND;
 813                }
 814            }
 815        }
 816        /* Clear pending sense data. */
 817        if (p->chars & PMCW_CHARS_MASK_CSENSE) {
 818            memset(sch->sense_data, 0 , sizeof(sch->sense_data));
 819        }
 820    }
 821
 822    ret = ((stctl & SCSW_STCTL_STATUS_PEND) == 0);
 823
 824out:
 825    return ret;
 826}
 827
 828static void copy_crw_to_guest(CRW *dest, const CRW *src)
 829{
 830    dest->flags = cpu_to_be16(src->flags);
 831    dest->rsid = cpu_to_be16(src->rsid);
 832}
 833
 834int css_do_stcrw(CRW *crw)
 835{
 836    CrwContainer *crw_cont;
 837    int ret;
 838
 839    crw_cont = QTAILQ_FIRST(&channel_subsys->pending_crws);
 840    if (crw_cont) {
 841        QTAILQ_REMOVE(&channel_subsys->pending_crws, crw_cont, sibling);
 842        copy_crw_to_guest(crw, &crw_cont->crw);
 843        g_free(crw_cont);
 844        ret = 0;
 845    } else {
 846        /* List was empty, turn crw machine checks on again. */
 847        memset(crw, 0, sizeof(*crw));
 848        channel_subsys->do_crw_mchk = true;
 849        ret = 1;
 850    }
 851
 852    return ret;
 853}
 854
 855int css_do_tpi(IOIntCode *int_code, int lowcore)
 856{
 857    /* No pending interrupts for !KVM. */
 858    return 0;
 859 }
 860
 861int css_collect_chp_desc(int m, uint8_t cssid, uint8_t f_chpid, uint8_t l_chpid,
 862                         int rfmt, void *buf)
 863{
 864    int i, desc_size;
 865    uint32_t words[8];
 866    uint32_t chpid_type_word;
 867    CssImage *css;
 868
 869    if (!m && !cssid) {
 870        css = channel_subsys->css[channel_subsys->default_cssid];
 871    } else {
 872        css = channel_subsys->css[cssid];
 873    }
 874    if (!css) {
 875        return 0;
 876    }
 877    desc_size = 0;
 878    for (i = f_chpid; i <= l_chpid; i++) {
 879        if (css->chpids[i].in_use) {
 880            chpid_type_word = 0x80000000 | (css->chpids[i].type << 8) | i;
 881            if (rfmt == 0) {
 882                words[0] = cpu_to_be32(chpid_type_word);
 883                words[1] = 0;
 884                memcpy(buf + desc_size, words, 8);
 885                desc_size += 8;
 886            } else if (rfmt == 1) {
 887                words[0] = cpu_to_be32(chpid_type_word);
 888                words[1] = 0;
 889                words[2] = 0;
 890                words[3] = 0;
 891                words[4] = 0;
 892                words[5] = 0;
 893                words[6] = 0;
 894                words[7] = 0;
 895                memcpy(buf + desc_size, words, 32);
 896                desc_size += 32;
 897            }
 898        }
 899    }
 900    return desc_size;
 901}
 902
 903void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo)
 904{
 905    /* dct is currently ignored (not really meaningful for our devices) */
 906    /* TODO: Don't ignore mbk. */
 907    if (update && !channel_subsys->chnmon_active) {
 908        /* Enable measuring. */
 909        channel_subsys->chnmon_area = mbo;
 910        channel_subsys->chnmon_active = true;
 911    }
 912    if (!update && channel_subsys->chnmon_active) {
 913        /* Disable measuring. */
 914        channel_subsys->chnmon_area = 0;
 915        channel_subsys->chnmon_active = false;
 916    }
 917}
 918
 919int css_do_rsch(SubchDev *sch)
 920{
 921    SCSW *s = &sch->curr_status.scsw;
 922    PMCW *p = &sch->curr_status.pmcw;
 923    int ret;
 924
 925    if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
 926        ret = -ENODEV;
 927        goto out;
 928    }
 929
 930    if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
 931        ret = -EINPROGRESS;
 932        goto out;
 933    }
 934
 935    if (((s->ctrl & SCSW_CTRL_MASK_FCTL) != SCSW_FCTL_START_FUNC) ||
 936        (s->ctrl & SCSW_ACTL_RESUME_PEND) ||
 937        (!(s->ctrl & SCSW_ACTL_SUSP))) {
 938        ret = -EINVAL;
 939        goto out;
 940    }
 941
 942    /* If monitoring is active, update counter. */
 943    if (channel_subsys->chnmon_active) {
 944        css_update_chnmon(sch);
 945    }
 946
 947    s->ctrl |= SCSW_ACTL_RESUME_PEND;
 948    do_subchannel_work(sch);
 949    ret = 0;
 950
 951out:
 952    return ret;
 953}
 954
 955int css_do_rchp(uint8_t cssid, uint8_t chpid)
 956{
 957    uint8_t real_cssid;
 958
 959    if (cssid > channel_subsys->max_cssid) {
 960        return -EINVAL;
 961    }
 962    if (channel_subsys->max_cssid == 0) {
 963        real_cssid = channel_subsys->default_cssid;
 964    } else {
 965        real_cssid = cssid;
 966    }
 967    if (!channel_subsys->css[real_cssid]) {
 968        return -EINVAL;
 969    }
 970
 971    if (!channel_subsys->css[real_cssid]->chpids[chpid].in_use) {
 972        return -ENODEV;
 973    }
 974
 975    if (!channel_subsys->css[real_cssid]->chpids[chpid].is_virtual) {
 976        fprintf(stderr,
 977                "rchp unsupported for non-virtual chpid %x.%02x!\n",
 978                real_cssid, chpid);
 979        return -ENODEV;
 980    }
 981
 982    /* We don't really use a channel path, so we're done here. */
 983    css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT,
 984                  channel_subsys->max_cssid > 0 ? 1 : 0, chpid);
 985    if (channel_subsys->max_cssid > 0) {
 986        css_queue_crw(CRW_RSC_CHP, CRW_ERC_INIT, 0, real_cssid << 8);
 987    }
 988    return 0;
 989}
 990
 991bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid)
 992{
 993    SubchSet *set;
 994    uint8_t real_cssid;
 995
 996    real_cssid = (!m && (cssid == 0)) ? channel_subsys->default_cssid : cssid;
 997    if (real_cssid > MAX_CSSID || ssid > MAX_SSID ||
 998        !channel_subsys->css[real_cssid] ||
 999        !channel_subsys->css[real_cssid]->sch_set[ssid]) {
1000        return true;
1001    }
1002    set = channel_subsys->css[real_cssid]->sch_set[ssid];
1003    return schid > find_last_bit(set->schids_used,
1004                                 (MAX_SCHID + 1) / sizeof(unsigned long));
1005}
1006
1007static int css_add_virtual_chpid(uint8_t cssid, uint8_t chpid, uint8_t type)
1008{
1009    CssImage *css;
1010
1011    trace_css_chpid_add(cssid, chpid, type);
1012    if (cssid > MAX_CSSID) {
1013        return -EINVAL;
1014    }
1015    css = channel_subsys->css[cssid];
1016    if (!css) {
1017        return -EINVAL;
1018    }
1019    if (css->chpids[chpid].in_use) {
1020        return -EEXIST;
1021    }
1022    css->chpids[chpid].in_use = 1;
1023    css->chpids[chpid].type = type;
1024    css->chpids[chpid].is_virtual = 1;
1025
1026    css_generate_chp_crws(cssid, chpid);
1027
1028    return 0;
1029}
1030
1031void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type)
1032{
1033    PMCW *p = &sch->curr_status.pmcw;
1034    SCSW *s = &sch->curr_status.scsw;
1035    int i;
1036    CssImage *css = channel_subsys->css[sch->cssid];
1037
1038    assert(css != NULL);
1039    memset(p, 0, sizeof(PMCW));
1040    p->flags |= PMCW_FLAGS_MASK_DNV;
1041    p->devno = sch->devno;
1042    /* single path */
1043    p->pim = 0x80;
1044    p->pom = 0xff;
1045    p->pam = 0x80;
1046    p->chpid[0] = chpid;
1047    if (!css->chpids[chpid].in_use) {
1048        css_add_virtual_chpid(sch->cssid, chpid, type);
1049    }
1050
1051    memset(s, 0, sizeof(SCSW));
1052    sch->curr_status.mba = 0;
1053    for (i = 0; i < ARRAY_SIZE(sch->curr_status.mda); i++) {
1054        sch->curr_status.mda[i] = 0;
1055    }
1056}
1057
1058SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, uint16_t schid)
1059{
1060    uint8_t real_cssid;
1061
1062    real_cssid = (!m && (cssid == 0)) ? channel_subsys->default_cssid : cssid;
1063
1064    if (!channel_subsys->css[real_cssid]) {
1065        return NULL;
1066    }
1067
1068    if (!channel_subsys->css[real_cssid]->sch_set[ssid]) {
1069        return NULL;
1070    }
1071
1072    return channel_subsys->css[real_cssid]->sch_set[ssid]->sch[schid];
1073}
1074
1075bool css_subch_visible(SubchDev *sch)
1076{
1077    if (sch->ssid > channel_subsys->max_ssid) {
1078        return false;
1079    }
1080
1081    if (sch->cssid != channel_subsys->default_cssid) {
1082        return (channel_subsys->max_cssid > 0);
1083    }
1084
1085    return true;
1086}
1087
1088bool css_present(uint8_t cssid)
1089{
1090    return (channel_subsys->css[cssid] != NULL);
1091}
1092
1093bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno)
1094{
1095    if (!channel_subsys->css[cssid]) {
1096        return false;
1097    }
1098    if (!channel_subsys->css[cssid]->sch_set[ssid]) {
1099        return false;
1100    }
1101
1102    return !!test_bit(devno,
1103                      channel_subsys->css[cssid]->sch_set[ssid]->devnos_used);
1104}
1105
1106void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
1107                      uint16_t devno, SubchDev *sch)
1108{
1109    CssImage *css;
1110    SubchSet *s_set;
1111
1112    trace_css_assign_subch(sch ? "assign" : "deassign", cssid, ssid, schid,
1113                           devno);
1114    if (!channel_subsys->css[cssid]) {
1115        fprintf(stderr,
1116                "Suspicious call to %s (%x.%x.%04x) for non-existing css!\n",
1117                __func__, cssid, ssid, schid);
1118        return;
1119    }
1120    css = channel_subsys->css[cssid];
1121
1122    if (!css->sch_set[ssid]) {
1123        css->sch_set[ssid] = g_malloc0(sizeof(SubchSet));
1124    }
1125    s_set = css->sch_set[ssid];
1126
1127    s_set->sch[schid] = sch;
1128    if (sch) {
1129        set_bit(schid, s_set->schids_used);
1130        set_bit(devno, s_set->devnos_used);
1131    } else {
1132        clear_bit(schid, s_set->schids_used);
1133        clear_bit(devno, s_set->devnos_used);
1134    }
1135}
1136
1137void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid)
1138{
1139    CrwContainer *crw_cont;
1140
1141    trace_css_crw(rsc, erc, rsid, chain ? "(chained)" : "");
1142    /* TODO: Maybe use a static crw pool? */
1143    crw_cont = g_try_malloc0(sizeof(CrwContainer));
1144    if (!crw_cont) {
1145        channel_subsys->crws_lost = true;
1146        return;
1147    }
1148    crw_cont->crw.flags = (rsc << 8) | erc;
1149    if (chain) {
1150        crw_cont->crw.flags |= CRW_FLAGS_MASK_C;
1151    }
1152    crw_cont->crw.rsid = rsid;
1153    if (channel_subsys->crws_lost) {
1154        crw_cont->crw.flags |= CRW_FLAGS_MASK_R;
1155        channel_subsys->crws_lost = false;
1156    }
1157
1158    QTAILQ_INSERT_TAIL(&channel_subsys->pending_crws, crw_cont, sibling);
1159
1160    if (channel_subsys->do_crw_mchk) {
1161        S390CPU *cpu = s390_cpu_addr2state(0);
1162
1163        channel_subsys->do_crw_mchk = false;
1164        /* Inject crw pending machine check. */
1165        s390_crw_mchk(cpu);
1166    }
1167}
1168
1169void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
1170                           int hotplugged, int add)
1171{
1172    uint8_t guest_cssid;
1173    bool chain_crw;
1174
1175    if (add && !hotplugged) {
1176        return;
1177    }
1178    if (channel_subsys->max_cssid == 0) {
1179        /* Default cssid shows up as 0. */
1180        guest_cssid = (cssid == channel_subsys->default_cssid) ? 0 : cssid;
1181    } else {
1182        /* Show real cssid to the guest. */
1183        guest_cssid = cssid;
1184    }
1185    /*
1186     * Only notify for higher subchannel sets/channel subsystems if the
1187     * guest has enabled it.
1188     */
1189    if ((ssid > channel_subsys->max_ssid) ||
1190        (guest_cssid > channel_subsys->max_cssid) ||
1191        ((channel_subsys->max_cssid == 0) &&
1192         (cssid != channel_subsys->default_cssid))) {
1193        return;
1194    }
1195    chain_crw = (channel_subsys->max_ssid > 0) ||
1196            (channel_subsys->max_cssid > 0);
1197    css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, chain_crw ? 1 : 0, schid);
1198    if (chain_crw) {
1199        css_queue_crw(CRW_RSC_SUBCH, CRW_ERC_IPI, 0,
1200                      (guest_cssid << 8) | (ssid << 4));
1201    }
1202}
1203
1204void css_generate_chp_crws(uint8_t cssid, uint8_t chpid)
1205{
1206    /* TODO */
1207}
1208
1209int css_enable_mcsse(void)
1210{
1211    trace_css_enable_facility("mcsse");
1212    channel_subsys->max_cssid = MAX_CSSID;
1213    return 0;
1214}
1215
1216int css_enable_mss(void)
1217{
1218    trace_css_enable_facility("mss");
1219    channel_subsys->max_ssid = MAX_SSID;
1220    return 0;
1221}
1222
1223static void css_init(void)
1224{
1225    channel_subsys = g_malloc0(sizeof(*channel_subsys));
1226    QTAILQ_INIT(&channel_subsys->pending_crws);
1227    channel_subsys->do_crw_mchk = true;
1228    channel_subsys->crws_lost = false;
1229    channel_subsys->chnmon_active = false;
1230}
1231machine_init(css_init);
1232
1233void css_reset_sch(SubchDev *sch)
1234{
1235    PMCW *p = &sch->curr_status.pmcw;
1236
1237    p->intparm = 0;
1238    p->flags &= ~(PMCW_FLAGS_MASK_ISC | PMCW_FLAGS_MASK_ENA |
1239                  PMCW_FLAGS_MASK_LM | PMCW_FLAGS_MASK_MME |
1240                  PMCW_FLAGS_MASK_MP | PMCW_FLAGS_MASK_TF);
1241    p->flags |= PMCW_FLAGS_MASK_DNV;
1242    p->devno = sch->devno;
1243    p->pim = 0x80;
1244    p->lpm = p->pim;
1245    p->pnom = 0;
1246    p->lpum = 0;
1247    p->mbi = 0;
1248    p->pom = 0xff;
1249    p->pam = 0x80;
1250    p->chars &= ~(PMCW_CHARS_MASK_MBFC | PMCW_CHARS_MASK_XMWME |
1251                  PMCW_CHARS_MASK_CSENSE);
1252
1253    memset(&sch->curr_status.scsw, 0, sizeof(sch->curr_status.scsw));
1254    sch->curr_status.mba = 0;
1255
1256    sch->channel_prog = 0x0;
1257    sch->last_cmd_valid = false;
1258    sch->orb = NULL;
1259}
1260
1261void css_reset(void)
1262{
1263    CrwContainer *crw_cont;
1264
1265    /* Clean up monitoring. */
1266    channel_subsys->chnmon_active = false;
1267    channel_subsys->chnmon_area = 0;
1268
1269    /* Clear pending CRWs. */
1270    while ((crw_cont = QTAILQ_FIRST(&channel_subsys->pending_crws))) {
1271        QTAILQ_REMOVE(&channel_subsys->pending_crws, crw_cont, sibling);
1272        g_free(crw_cont);
1273    }
1274    channel_subsys->do_crw_mchk = true;
1275    channel_subsys->crws_lost = false;
1276
1277    /* Reset maximum ids. */
1278    channel_subsys->max_cssid = 0;
1279    channel_subsys->max_ssid = 0;
1280}
1281