static int interface_client_monitors_config(QXLInstance *sin,

                                        VDAgentMonitorsConfig *monitors_config)

{

    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);

    QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);

    int i;

    unsigned max_outputs = ARRAY_SIZE(rom->client_monitors_config.heads);



    if (qxl->revision < 4) {

        trace_qxl_client_monitors_config_unsupported_by_device(qxl->id,

                                                               qxl->revision);

        return 0;

    }

    /*

     * Older windows drivers set int_mask to 0 when their ISR is called,

     * then later set it to ~0. So it doesn't relate to the actual interrupts

     * handled. However, they are old, so clearly they don't support this

     * interrupt

     */

    if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 ||

        !(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) {

        trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id,

                                                            qxl->ram->int_mask,

                                                            monitors_config);

        return 0;

    }

    if (!monitors_config) {

        return 1;

    }



#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */

    /* limit number of outputs based on setting limit */

    if (qxl->max_outputs && qxl->max_outputs <= max_outputs) {

        max_outputs = qxl->max_outputs;

    }

#endif



    memset(&rom->client_monitors_config, 0,

           sizeof(rom->client_monitors_config));

    rom->client_monitors_config.count = monitors_config->num_of_monitors;

    /* monitors_config->flags ignored */

    if (rom->client_monitors_config.count >= max_outputs) {

        trace_qxl_client_monitors_config_capped(qxl->id,

                                monitors_config->num_of_monitors,

                                max_outputs);

        rom->client_monitors_config.count = max_outputs;

    }

    for (i = 0 ; i < rom->client_monitors_config.count ; ++i) {

        VDAgentMonConfig *monitor = &monitors_config->monitors[i];

        QXLURect *rect = &rom->client_monitors_config.heads[i];

        /* monitor->depth ignored */

        rect->left = monitor->x;

        rect->top = monitor->y;

        rect->right = monitor->x + monitor->width;

        rect->bottom = monitor->y + monitor->height;

    }

    rom->client_monitors_config_crc = qxl_crc32(

            (const uint8_t *)&rom->client_monitors_config,

            sizeof(rom->client_monitors_config));

    trace_qxl_client_monitors_config_crc(qxl->id,

            sizeof(rom->client_monitors_config),

            rom->client_monitors_config_crc);



    trace_qxl_interrupt_client_monitors_config(qxl->id,

                        rom->client_monitors_config.count,

                        rom->client_monitors_config.heads);

    qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);

    return 1;

}

static int interface_client_monitors_config(QXLInstance *sin,

                                        VDAgentMonitorsConfig *monitors_config)

{

    PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);

    QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);

    int i;

    unsigned max_outputs = ARRAY_SIZE(rom->client_monitors_config.heads);



    if (qxl->revision < 4) {

        trace_qxl_client_monitors_config_unsupported_by_device(qxl->id,

                                                               qxl->revision);

        return 0;

    }

    











    if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 ||

        !(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) {

        trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id,

                                                            qxl->ram->int_mask,

                                                            monitors_config);

        return 0;

    }

    if (!monitors_config) {

        return 1;

    }



#if SPICE_SERVER_VERSION >= 0x000c06 

    

    if (qxl->max_outputs && qxl->max_outputs <= max_outputs) {

        max_outputs = qxl->max_outputs;

    }

#endif



    memset(&rom->client_monitors_config, 0,

           sizeof(rom->client_monitors_config));

    rom->client_monitors_config.count = monitors_config->num_of_monitors;

    

    if (rom->client_monitors_config.count >= max_outputs) {

        trace_qxl_client_monitors_config_capped(qxl->id,

                                monitors_config->num_of_monitors,

                                max_outputs);

        rom->client_monitors_config.count = max_outputs;

    }

    for (i = 0 ; i < rom->client_monitors_config.count ; ++i) {

        VDAgentMonConfig *monitor = &monitors_config->monitors[i];

        QXLURect *rect = &rom->client_monitors_config.heads[i];

        

        rect->left = monitor->x;

        rect->top = monitor->y;

        rect->right = monitor->x + monitor->width;

        rect->bottom = monitor->y + monitor->height;

    }

    rom->client_monitors_config_crc = qxl_crc32(

            (const uint8_t *)&rom->client_monitors_config,

            sizeof(rom->client_monitors_config));

    trace_qxl_client_monitors_config_crc(qxl->id,

            sizeof(rom->client_monitors_config),

            rom->client_monitors_config_crc);



    trace_qxl_interrupt_client_monitors_config(qxl->id,

                        rom->client_monitors_config.count,

                        rom->client_monitors_config.heads);

    qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);

    return 1;

}

static int FUNC_0(QXLInstance *VAR_0,

                                        VDAgentMonitorsConfig *VAR_1)

{

    PCIQXLDevice *qxl = container_of(VAR_0, PCIQXLDevice, ssd.qxl);

    QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar);

    int VAR_2;

    unsigned VAR_3 = ARRAY_SIZE(rom->client_monitors_config.heads);



    if (qxl->revision < 4) {

        trace_qxl_client_monitors_config_unsupported_by_device(qxl->id,

                                                               qxl->revision);

        return 0;

    }

    











    if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 ||

        !(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) {

        trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id,

                                                            qxl->ram->int_mask,

                                                            VAR_1);

        return 0;

    }

    if (!VAR_1) {

        return 1;

    }



#if SPICE_SERVER_VERSION >= 0x000c06 

    

    if (qxl->VAR_3 && qxl->VAR_3 <= VAR_3) {

        VAR_3 = qxl->VAR_3;

    }

#endif



    memset(&rom->client_monitors_config, 0,

           sizeof(rom->client_monitors_config));

    rom->client_monitors_config.count = VAR_1->num_of_monitors;

    

    if (rom->client_monitors_config.count >= VAR_3) {

        trace_qxl_client_monitors_config_capped(qxl->id,

                                VAR_1->num_of_monitors,

                                VAR_3);

        rom->client_monitors_config.count = VAR_3;

    }

    for (VAR_2 = 0 ; VAR_2 < rom->client_monitors_config.count ; ++VAR_2) {

        VDAgentMonConfig *monitor = &VAR_1->monitors[VAR_2];

        QXLURect *rect = &rom->client_monitors_config.heads[VAR_2];

        

        rect->left = monitor->x;

        rect->top = monitor->y;

        rect->right = monitor->x + monitor->width;

        rect->bottom = monitor->y + monitor->height;

    }

    rom->client_monitors_config_crc = qxl_crc32(

            (const uint8_t *)&rom->client_monitors_config,

            sizeof(rom->client_monitors_config));

    trace_qxl_client_monitors_config_crc(qxl->id,

            sizeof(rom->client_monitors_config),

            rom->client_monitors_config_crc);



    trace_qxl_interrupt_client_monitors_config(qxl->id,

                        rom->client_monitors_config.count,

                        rom->client_monitors_config.heads);

    qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG);

    return 1;

}

static int FUNC_0(QXLInstance *VAR_0,
VDAgentMonitorsConfig *VAR_1)
{ PCIQXLDevice *qxl = container_of(VAR_0, PCIQXLDevice, ssd.qxl); QXLRom *rom = memory_region_get_ram_ptr(&qxl->rom_bar); int VAR_2; unsigned VAR_3 = ARRAY_SIZE(rom->client_monitors_config.heads); if (qxl->revision < 4) { trace_qxl_client_monitors_config_unsupported_by_device(qxl->id,
qxl->revision); return 0; } if (qxl->ram->int_mask == 0 || qxl->ram->int_mask == ~0 ||
!(qxl->ram->int_mask & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG)) { trace_qxl_client_monitors_config_unsupported_by_guest(qxl->id,
qxl->ram->int_mask,
VAR_1); return 0; } if (!VAR_1) { return 1; } #if SPICE_SERVER_VERSION >= 0x000c06
if (qxl->VAR_3 && qxl->VAR_3 <= VAR_3) { VAR_3 = qxl->VAR_3; } #endif
memset(&rom->client_monitors_config, 0,
sizeof(rom->client_monitors_config)); rom->client_monitors_config.count = VAR_1->num_of_monitors; if (rom->client_monitors_config.count >= VAR_3) { trace_qxl_client_monitors_config_capped(qxl->id,
VAR_1->num_of_monitors,
VAR_3); rom->client_monitors_config.count = VAR_3; } for (VAR_2 = 0 ; VAR_2 < rom->client_monitors_config.count ; ++VAR_2) { VDAgentMonConfig *monitor = &VAR_1->monitors[VAR_2]; QXLURect *rect = &rom->client_monitors_config.heads[VAR_2]; rect->left = monitor->x; rect->top = monitor->y; rect->right = monitor->x + monitor->width; rect->bottom = monitor->y + monitor->height; } rom->client_monitors_config_crc = qxl_crc32(
(const uint8_t *)&rom->client_monitors_config,
sizeof(rom->client_monitors_config)); trace_qxl_client_monitors_config_crc(qxl->id,
sizeof(rom->client_monitors_config),
rom->client_monitors_config_crc); trace_qxl_interrupt_client_monitors_config(qxl->id,
rom->client_monitors_config.count,
rom->client_monitors_config.heads); qxl_send_events(qxl, QXL_INTERRUPT_CLIENT_MONITORS_CONFIG); return 1; }