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