func: 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;
  
  }
  