func: static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
  
  {
  
      PCIDevice *pci_dev = PCI_DEVICE(s);
  
      PCIDeviceClass *pci_class = PCI_DEVICE_GET_CLASS(pci_dev);
  
      MegasasBaseClass *base_class = MEGASAS_DEVICE_GET_CLASS(s);
  
      struct mfi_ctrl_info info;
  
      size_t dcmd_size = sizeof(info);
  
      BusChild *kid;
  
      int num_pd_disks = 0;
  
  
  
      memset(&info, 0x0, cmd->iov_size);
  
      if (cmd->iov_size < dcmd_size) {
  
          trace_megasas_dcmd_invalid_xfer_len(cmd->index, cmd->iov_size,
  
                                              dcmd_size);
  
          return MFI_STAT_INVALID_PARAMETER;
  
      }
  
  
  
      info.pci.vendor = cpu_to_le16(pci_class->vendor_id);
  
      info.pci.device = cpu_to_le16(pci_class->device_id);
  
      info.pci.subvendor = cpu_to_le16(pci_class->subsystem_vendor_id);
  
      info.pci.subdevice = cpu_to_le16(pci_class->subsystem_id);
  
  
  
      /*
  
       * For some reason the firmware supports
  
       * only up to 8 device ports.
  
       * Despite supporting a far larger number
  
       * of devices for the physical devices.
  
       * So just display the first 8 devices
  
       * in the device port list, independent
  
       * of how many logical devices are actually
  
       * present.
  
       */
  
      info.host.type = MFI_INFO_HOST_PCIE;
  
      info.device.type = MFI_INFO_DEV_SAS3G;
  
      info.device.port_count = 8;
  
      QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
  
          SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
  
          uint16_t pd_id;
  
  
  
          if (num_pd_disks < 8) {
  
              pd_id = ((sdev->id & 0xFF) << 8) | (sdev->lun & 0xFF);
  
              info.device.port_addr[num_pd_disks] =
  
                  cpu_to_le64(megasas_get_sata_addr(pd_id));
  
          }
  
          num_pd_disks++;
  
      }
  
  
  
      memcpy(info.product_name, base_class->product_name, 24);
  
      snprintf(info.serial_number, 32, "%s", s->hba_serial);
  
      snprintf(info.package_version, 0x60, "%s-QEMU", qemu_hw_version());
  
      memcpy(info.image_component[0].name, "APP", 3);
  
      snprintf(info.image_component[0].version, 10, "%s-QEMU",
  
               base_class->product_version);
  
      memcpy(info.image_component[0].build_date, "Apr  1 2014", 11);
  
      memcpy(info.image_component[0].build_time, "12:34:56", 8);
  
      info.image_component_count = 1;
  
      if (pci_dev->has_rom) {
  
          uint8_t biosver[32];
  
          uint8_t *ptr;
  
  
  
          ptr = memory_region_get_ram_ptr(&pci_dev->rom);
  
          memcpy(biosver, ptr + 0x41, 31);
  
          memcpy(info.image_component[1].name, "BIOS", 4);
  
          memcpy(info.image_component[1].version, biosver,
  
                 strlen((const char *)biosver));
  
          info.image_component_count++;
  
      }
  
      info.current_fw_time = cpu_to_le32(megasas_fw_time());
  
      info.max_arms = 32;
  
      info.max_spans = 8;
  
      info.max_arrays = MEGASAS_MAX_ARRAYS;
  
      info.max_lds = MFI_MAX_LD;
  
      info.max_cmds = cpu_to_le16(s->fw_cmds);
  
      info.max_sg_elements = cpu_to_le16(s->fw_sge);
  
      info.max_request_size = cpu_to_le32(MEGASAS_MAX_SECTORS);
  
      if (!megasas_is_jbod(s))
  
          info.lds_present = cpu_to_le16(num_pd_disks);
  
      info.pd_present = cpu_to_le16(num_pd_disks);
  
      info.pd_disks_present = cpu_to_le16(num_pd_disks);
  
      info.hw_present = cpu_to_le32(MFI_INFO_HW_NVRAM |
  
                                     MFI_INFO_HW_MEM |
  
                                     MFI_INFO_HW_FLASH);
  
      info.memory_size = cpu_to_le16(512);
  
      info.nvram_size = cpu_to_le16(32);
  
      info.flash_size = cpu_to_le16(16);
  
      info.raid_levels = cpu_to_le32(MFI_INFO_RAID_0);
  
      info.adapter_ops = cpu_to_le32(MFI_INFO_AOPS_RBLD_RATE |
  
                                      MFI_INFO_AOPS_SELF_DIAGNOSTIC |
  
                                      MFI_INFO_AOPS_MIXED_ARRAY);
  
      info.ld_ops = cpu_to_le32(MFI_INFO_LDOPS_DISK_CACHE_POLICY |
  
                                 MFI_INFO_LDOPS_ACCESS_POLICY |
  
                                 MFI_INFO_LDOPS_IO_POLICY |
  
                                 MFI_INFO_LDOPS_WRITE_POLICY |
  
                                 MFI_INFO_LDOPS_READ_POLICY);
  
      info.max_strips_per_io = cpu_to_le16(s->fw_sge);
  
      info.stripe_sz_ops.min = 3;
  
      info.stripe_sz_ops.max = ctz32(MEGASAS_MAX_SECTORS + 1);
  
      info.properties.pred_fail_poll_interval = cpu_to_le16(300);
  
      info.properties.intr_throttle_cnt = cpu_to_le16(16);
  
      info.properties.intr_throttle_timeout = cpu_to_le16(50);
  
      info.properties.rebuild_rate = 30;
  
      info.properties.patrol_read_rate = 30;
  
      info.properties.bgi_rate = 30;
  
      info.properties.cc_rate = 30;
  
      info.properties.recon_rate = 30;
  
      info.properties.cache_flush_interval = 4;
  
      info.properties.spinup_drv_cnt = 2;
  
      info.properties.spinup_delay = 6;
  
      info.properties.ecc_bucket_size = 15;
  
      info.properties.ecc_bucket_leak_rate = cpu_to_le16(1440);
  
      info.properties.expose_encl_devices = 1;
  
      info.properties.OnOffProperties = cpu_to_le32(MFI_CTRL_PROP_EnableJBOD);
  
      info.pd_ops = cpu_to_le32(MFI_INFO_PDOPS_FORCE_ONLINE |
  
                                 MFI_INFO_PDOPS_FORCE_OFFLINE);
  
      info.pd_mix_support = cpu_to_le32(MFI_INFO_PDMIX_SAS |
  
                                         MFI_INFO_PDMIX_SATA |
  
                                         MFI_INFO_PDMIX_LD);
  
  
  
      cmd->iov_size -= dma_buf_read((uint8_t *)&info, dcmd_size, &cmd->qsg);
  
      return MFI_STAT_OK;
  
  }
  