static int xen_pt_msgctrl_reg_write(XenPCIPassthroughState *s,

                                    XenPTReg *cfg_entry, uint16_t *val,

                                    uint16_t dev_value, uint16_t valid_mask)

{

    XenPTRegInfo *reg = cfg_entry->reg;

    XenPTMSI *msi = s->msi;

    uint16_t writable_mask = 0;

    uint16_t throughable_mask = 0;

    uint16_t raw_val;



    /* Currently no support for multi-vector */

    if (*val & PCI_MSI_FLAGS_QSIZE) {

        XEN_PT_WARN(&s->dev, "Tries to set more than 1 vector ctrl %x\n", *val);

    }



    /* modify emulate register */

    writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;

    cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);

    msi->flags |= cfg_entry->data & ~PCI_MSI_FLAGS_ENABLE;



    /* create value for writing to I/O device register */

    raw_val = *val;

    throughable_mask = ~reg->emu_mask & valid_mask;

    *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);



    /* update MSI */

    if (raw_val & PCI_MSI_FLAGS_ENABLE) {

        /* setup MSI pirq for the first time */

        if (!msi->initialized) {

            /* Init physical one */

            XEN_PT_LOG(&s->dev, "setup MSI\n");

            if (xen_pt_msi_setup(s)) {

                /* We do not broadcast the error to the framework code, so

                 * that MSI errors are contained in MSI emulation code and

                 * QEMU can go on running.

                 * Guest MSI would be actually not working.

                 */

                *val &= ~PCI_MSI_FLAGS_ENABLE;

                XEN_PT_WARN(&s->dev, "Can not map MSI.\n");

                return 0;

            }

            if (xen_pt_msi_update(s)) {

                *val &= ~PCI_MSI_FLAGS_ENABLE;

                XEN_PT_WARN(&s->dev, "Can not bind MSI\n");

                return 0;

            }

            msi->initialized = true;

            msi->mapped = true;

        }

        msi->flags |= PCI_MSI_FLAGS_ENABLE;

    } else {

        msi->flags &= ~PCI_MSI_FLAGS_ENABLE;

    }



    /* pass through MSI_ENABLE bit */

    *val &= ~PCI_MSI_FLAGS_ENABLE;

    *val |= raw_val & PCI_MSI_FLAGS_ENABLE;



    return 0;

}

static int xen_pt_msgctrl_reg_write(XenPCIPassthroughState *s,

                                    XenPTReg *cfg_entry, uint16_t *val,

                                    uint16_t dev_value, uint16_t valid_mask)

{

    XenPTRegInfo *reg = cfg_entry->reg;

    XenPTMSI *msi = s->msi;

    uint16_t writable_mask = 0;

    uint16_t throughable_mask = 0;

    uint16_t raw_val;



    

    if (*val & PCI_MSI_FLAGS_QSIZE) {

        XEN_PT_WARN(&s->dev, "Tries to set more than 1 vector ctrl %x\n", *val);

    }



    

    writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;

    cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);

    msi->flags |= cfg_entry->data & ~PCI_MSI_FLAGS_ENABLE;



    

    raw_val = *val;

    throughable_mask = ~reg->emu_mask & valid_mask;

    *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);



    

    if (raw_val & PCI_MSI_FLAGS_ENABLE) {

        

        if (!msi->initialized) {

            

            XEN_PT_LOG(&s->dev, "setup MSI\n");

            if (xen_pt_msi_setup(s)) {

                









                *val &= ~PCI_MSI_FLAGS_ENABLE;

                XEN_PT_WARN(&s->dev, "Can not map MSI.\n");

                return 0;

            }

            if (xen_pt_msi_update(s)) {

                *val &= ~PCI_MSI_FLAGS_ENABLE;

                XEN_PT_WARN(&s->dev, "Can not bind MSI\n");

                return 0;

            }

            msi->initialized = true;

            msi->mapped = true;

        }

        msi->flags |= PCI_MSI_FLAGS_ENABLE;

    } else {

        msi->flags &= ~PCI_MSI_FLAGS_ENABLE;

    }



    

    *val &= ~PCI_MSI_FLAGS_ENABLE;

    *val |= raw_val & PCI_MSI_FLAGS_ENABLE;



    return 0;

}

    } else {         msi->flags &= ~PCI_MSI_FLAGS_ENABLE;
static int FUNC_0(XenPCIPassthroughState *VAR_0,

                                    XenPTReg *VAR_1, uint16_t *VAR_2,

                                    uint16_t VAR_3, uint16_t VAR_4)

{

    XenPTRegInfo *reg = VAR_1->reg;

    XenPTMSI *msi = VAR_0->msi;

    uint16_t writable_mask = 0;

    uint16_t throughable_mask = 0;

    uint16_t raw_val;



    

    if (*VAR_2 & PCI_MSI_FLAGS_QSIZE) {

        XEN_PT_WARN(&VAR_0->dev, "Tries to set more than 1 vector ctrl %x\n", *VAR_2);

    }



    

    writable_mask = reg->emu_mask & ~reg->ro_mask & VAR_4;

    VAR_1->data = XEN_PT_MERGE_VALUE(*VAR_2, VAR_1->data, writable_mask);

    msi->flags |= VAR_1->data & ~PCI_MSI_FLAGS_ENABLE;



    

    raw_val = *VAR_2;

    throughable_mask = ~reg->emu_mask & VAR_4;

    *VAR_2 = XEN_PT_MERGE_VALUE(*VAR_2, VAR_3, throughable_mask);



    

    if (raw_val & PCI_MSI_FLAGS_ENABLE) {

        

        if (!msi->initialized) {

            

            XEN_PT_LOG(&VAR_0->dev, "setup MSI\n");

            if (xen_pt_msi_setup(VAR_0)) {

                









                *VAR_2 &= ~PCI_MSI_FLAGS_ENABLE;

                XEN_PT_WARN(&VAR_0->dev, "Can not map MSI.\n");

                return 0;

            }

            if (xen_pt_msi_update(VAR_0)) {

                *VAR_2 &= ~PCI_MSI_FLAGS_ENABLE;

                XEN_PT_WARN(&VAR_0->dev, "Can not bind MSI\n");

                return 0;

            }

            msi->initialized = true;

            msi->mapped = true;

        }

        msi->flags |= PCI_MSI_FLAGS_ENABLE;

    } else {

        msi->flags &= ~PCI_MSI_FLAGS_ENABLE;

    }



    

    *VAR_2 &= ~PCI_MSI_FLAGS_ENABLE;

    *VAR_2 |= raw_val & PCI_MSI_FLAGS_ENABLE;



    return 0;

}

static int FUNC_0(XenPCIPassthroughState *VAR_0,
XenPTReg *VAR_1, uint16_t *VAR_2,
uint16_t VAR_3, uint16_t VAR_4)
{ XenPTRegInfo *reg = VAR_1->reg; XenPTMSI *msi = VAR_0->msi; uint16_t writable_mask = 0; uint16_t throughable_mask = 0; uint16_t raw_val; if (*VAR_2 & PCI_MSI_FLAGS_QSIZE) { XEN_PT_WARN(&VAR_0->dev, "Tries to set more than 1 vector ctrl %x\n", *VAR_2); } writable_mask = reg->emu_mask & ~reg->ro_mask & VAR_4; VAR_1->data = XEN_PT_MERGE_VALUE(*VAR_2, VAR_1->data, writable_mask); msi->flags |= VAR_1->data & ~PCI_MSI_FLAGS_ENABLE; raw_val = *VAR_2; throughable_mask = ~reg->emu_mask & VAR_4; *VAR_2 = XEN_PT_MERGE_VALUE(*VAR_2, VAR_3, throughable_mask); if (raw_val & PCI_MSI_FLAGS_ENABLE) { if (!msi->initialized) { XEN_PT_LOG(&VAR_0->dev, "setup MSI\n"); if (xen_pt_msi_setup(VAR_0)) { *VAR_2 &= ~PCI_MSI_FLAGS_ENABLE; XEN_PT_WARN(&VAR_0->dev, "Can not map MSI.\n"); return 0; } if (xen_pt_msi_update(VAR_0)) { *VAR_2 &= ~PCI_MSI_FLAGS_ENABLE; XEN_PT_WARN(&VAR_0->dev, "Can not bind MSI\n"); return 0; } msi->initialized = true; msi->mapped = true; } msi->flags |= PCI_MSI_FLAGS_ENABLE; } else { msi->flags &= ~PCI_MSI_FLAGS_ENABLE; } *VAR_2 &= ~PCI_MSI_FLAGS_ENABLE; *VAR_2 |= raw_val & PCI_MSI_FLAGS_ENABLE; return 0; }