The 2108 chip supports MSI and MSI-X, so update the emulation to support both chips.
Signed-off-by: Hannes Reinecke <h...@suse.de> --- hw/scsi/megasas.c | 118 ++++++++++++++++++++++++++++++++++++++++++----- hw/scsi/mfi.h | 7 +++ include/hw/pci/pci_ids.h | 1 + 3 files changed, 114 insertions(+), 12 deletions(-) diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index a12cd92..a5bfeba 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -31,6 +31,7 @@ #include "mfi.h" #define MEGASAS_VERSION "1.70" +#define MEGASAS_VERSION_GEN2 "1.80" #define MEGASAS_MAX_FRAMES 2048 /* Firmware limit at 65535 */ #define MEGASAS_DEFAULT_FRAMES 1000 /* Windows requires this */ #define MEGASAS_MAX_SGE 128 /* Firmware limit */ @@ -90,6 +91,8 @@ typedef struct MegasasState { int intr_mask; int doorbell; int busy; + int diag; + int adp_reset; MegasasCmd *event_cmd; int event_locale; @@ -115,12 +118,18 @@ typedef struct MegasasState { } MegasasState; #define TYPE_MEGASAS "megasas" +#define TYPE_MEGASAS_GEN2 "megasas-gen2" #define MEGASAS(obj) \ OBJECT_CHECK(MegasasState, (obj), TYPE_MEGASAS) #define MEGASAS_INTR_DISABLED_MASK 0xFFFFFFFF +static bool megasas_is_gen2(PCIDeviceClass *dc) +{ + return dc->device_id == PCI_DEVICE_ID_LSI_SAS0079; +} + static bool megasas_intr_enabled(MegasasState *s) { if ((s->intr_mask & MEGASAS_INTR_DISABLED_MASK) != @@ -681,6 +690,7 @@ static void megasas_finish_dcmd(MegasasCmd *cmd, uint32_t iov_size) 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); struct mfi_ctrl_info info; size_t dcmd_size = sizeof(info); BusChild *kid; @@ -694,10 +704,10 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) return MFI_STAT_INVALID_PARAMETER; } - info.pci.vendor = cpu_to_le16(PCI_VENDOR_ID_LSI_LOGIC); - info.pci.device = cpu_to_le16(PCI_DEVICE_ID_LSI_SAS1078); - info.pci.subvendor = cpu_to_le16(PCI_VENDOR_ID_LSI_LOGIC); - info.pci.subdevice = cpu_to_le16(0x1013); + 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 @@ -723,11 +733,21 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) num_ld_disks++; } - memcpy(info.product_name, "MegaRAID SAS 8708EM2", 20); + if (megasas_is_gen2(pci_class)) { + memcpy(info.product_name, "LSI MegaRAID SAS 9260-8i", 24); + } else { + memcpy(info.product_name, "LSI MegaRAID SAS 8708EM2", 24); + } snprintf(info.serial_number, 32, "%s", s->hba_serial); snprintf(info.package_version, 0x60, "%s-QEMU", QEMU_VERSION); memcpy(info.image_component[0].name, "APP", 3); - memcpy(info.image_component[0].version, MEGASAS_VERSION "-QEMU", 9); + if (megasas_is_gen2(pci_class)) { + memcpy(info.image_component[0].version, + MEGASAS_VERSION_GEN2 "-QEMU", 9); + } else { + memcpy(info.image_component[0].version, + MEGASAS_VERSION "-QEMU", 9); + } memcpy(info.image_component[0].build_date, __DATE__, 11); memcpy(info.image_component[0].build_time, __TIME__, 8); info.image_component_count = 1; @@ -1907,6 +1927,7 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr, unsigned size) { MegasasState *s = opaque; + PCIDeviceClass *pci_class = PCI_DEVICE_GET_CLASS(s); uint32_t retval = 0; switch (addr) { @@ -1922,7 +1943,11 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr, break; case MFI_OSTS: if (megasas_intr_enabled(s) && s->doorbell) { - retval = MFI_1078_RM | 1; + if (megasas_is_gen2(pci_class)) { + retval = MFI_GEN2_RM; + } else { + retval = MFI_1078_RM | 1; + } } break; case MFI_OMSK: @@ -1931,6 +1956,9 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr, case MFI_ODCR0: retval = s->doorbell; break; + case MFI_DIAG: + retval = s->diag; + break; default: trace_megasas_mmio_invalid_readl(addr); break; @@ -1939,6 +1967,8 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr, return retval; } +static int adp_reset_seq[] = {0x00, 0x04, 0x0b, 0x02, 0x07, 0x0d}; + static void megasas_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { @@ -2013,6 +2043,28 @@ static void megasas_mmio_write(void *opaque, hwaddr addr, frame_count = (val >> 1) & 0xF; megasas_handle_frame(s, frame_addr, frame_count); break; + case MFI_SEQ: + /* Magic sequence to start ADP reset */ + if (adp_reset_seq[s->adp_reset] == val) { + s->adp_reset++; + } else { + s->adp_reset = 0; + s->diag = 0; + } + if (s->adp_reset == 6) { + s->diag = MFI_DIAG_WRITE_ENABLE; + } + break; + case MFI_DIAG: + /* ADP reset */ + if ((s->diag & MFI_DIAG_WRITE_ENABLE) && + (val & MFI_DIAG_RESET_ADP)) { + s->diag |= MFI_DIAG_RESET_ADP; + megasas_soft_reset(s); + s->adp_reset = 0; + s->diag = 0; + } + break; default: trace_megasas_mmio_invalid_writel(addr, val); break; @@ -2146,10 +2198,18 @@ static int megasas_scsi_init(PCIDevice *dev) { DeviceState *d = DEVICE(dev); MegasasState *s = MEGASAS(dev); + PCIDeviceClass *c = PCI_DEVICE_GET_CLASS(dev); uint8_t *pci_conf; - int i, bar_type; + int i, bar_type, mmio_bar, ioport_bar; Error *err = NULL; + if (megasas_is_gen2(c)) { + mmio_bar = 1; + ioport_bar = 0; + } else { + mmio_bar = 0; + ioport_bar = 2; + } pci_conf = dev->config; /* PCI latency timer = 0 */ @@ -2169,14 +2229,14 @@ static int megasas_scsi_init(PCIDevice *dev) s->flags &= ~MEGASAS_MASK_USE_MSI; } if (megasas_use_msix(s) && - msix_init(dev, 15, &s->mmio_io, 0, 0x2000, - &s->mmio_io, 0, 0x3800, 0x68)) { + msix_init(dev, 15, &s->mmio_io, mmio_bar, 0x2000, + &s->mmio_io, mmio_bar, 0x3800, 0x68)) { s->flags &= ~MEGASAS_MASK_USE_MSIX; } bar_type = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64; - pci_register_bar(dev, 0, bar_type, &s->mmio_io); - pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->port_io); + pci_register_bar(dev, ioport_bar, PCI_BASE_ADDRESS_SPACE_IO, &s->port_io); + pci_register_bar(dev, mmio_bar, bar_type, &s->mmio_io); pci_register_bar(dev, 3, bar_type, &s->queue_io); if (megasas_use_msix(s)) { @@ -2278,9 +2338,43 @@ static const TypeInfo megasas_info = { .class_init = megasas_class_init, }; +static Property megasas_gen2_properties[] = { + DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge, + MEGASAS_DEFAULT_SGE), + DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds, + MEGASAS_DEFAULT_FRAMES), + DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial), + DEFINE_PROP_UINT64("sas_address", MegasasState, sas_addr, 0), + DEFINE_PROP_BIT("use_msi", MegasasState, flags, + MEGASAS_FLAG_USE_MSI, true), + DEFINE_PROP_BIT("use_msix", MegasasState, flags, + MEGASAS_FLAG_USE_MSIX, true), + DEFINE_PROP_BIT("use_jbod", MegasasState, flags, + MEGASAS_FLAG_USE_JBOD, false), + DEFINE_PROP_END_OF_LIST(), +}; + +static void megasas_gen2_class_init(ObjectClass *oc, void *data) +{ + PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + pc->device_id = PCI_DEVICE_ID_LSI_SAS0079; + pc->subsystem_id = 0x9261; + dc->props = megasas_gen2_properties; + dc->desc = "LSI MegaRAID SAS 2108"; +} + +static TypeInfo megasas_gen2_info = { + .name = TYPE_MEGASAS_GEN2, + .parent = TYPE_MEGASAS, + .class_init = megasas_gen2_class_init, +}; + static void megasas_register_types(void) { type_register_static(&megasas_info); + type_register_static(&megasas_gen2_info); } type_init(megasas_register_types) diff --git a/hw/scsi/mfi.h b/hw/scsi/mfi.h index a3034f6..b344e4a 100644 --- a/hw/scsi/mfi.h +++ b/hw/scsi/mfi.h @@ -60,6 +60,7 @@ #define MFI_ODR0 0x9c /* outbound doorbell register0 */ #define MFI_ODCR0 0xa0 /* outbound doorbell clear register0 */ #define MFI_OSP0 0xb0 /* outbound scratch pad0 */ +#define MFI_OSP1 0xb4 /* outbound scratch pad1 */ #define MFI_IQPL 0xc0 /* Inbound queue port (low bytes) */ #define MFI_IQPH 0xc4 /* Inbound queue port (high bytes) */ #define MFI_DIAG 0xf8 /* Host diag */ @@ -116,6 +117,12 @@ #define MFI_FWINIT_STOP_ADP 0x00000020 /* Move to operational, stop */ #define MFI_FWINIT_ADP_RESET 0x00000040 /* Reset ADP */ +/* + * Control bits for the DIAG register + */ +#define MFI_DIAG_WRITE_ENABLE 0x00000080 +#define MFI_DIAG_RESET_ADP 0x00000004 + /* MFI Commands */ typedef enum { MFI_CMD_INIT = 0x00, diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index e597070..321d622 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -56,6 +56,7 @@ #define PCI_DEVICE_ID_LSI_53C810 0x0001 #define PCI_DEVICE_ID_LSI_53C895A 0x0012 #define PCI_DEVICE_ID_LSI_SAS1078 0x0060 +#define PCI_DEVICE_ID_LSI_SAS0079 0x0079 #define PCI_VENDOR_ID_DEC 0x1011 #define PCI_DEVICE_ID_DEC_21154 0x0026 -- 1.8.1.4