From patchwork Wed Apr 16 07:16:59 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hannes Reinecke X-Patchwork-Id: 339443 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 78A3014008E for ; Wed, 16 Apr 2014 17:18:26 +1000 (EST) Received: from localhost ([::1]:53186 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WaK6y-0006gp-DK for incoming@patchwork.ozlabs.org; Wed, 16 Apr 2014 03:18:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45552) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WaK62-0004to-RB for qemu-devel@nongnu.org; Wed, 16 Apr 2014 03:17:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WaK5w-0000EK-J3 for qemu-devel@nongnu.org; Wed, 16 Apr 2014 03:17:26 -0400 Received: from cantor2.suse.de ([195.135.220.15]:59701 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WaK5w-0000EA-93 for qemu-devel@nongnu.org; Wed, 16 Apr 2014 03:17:20 -0400 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id BBC22AC2B; Wed, 16 Apr 2014 07:17:19 +0000 (UTC) From: Hannes Reinecke To: qemu-devel@nongnu.org Date: Wed, 16 Apr 2014 09:16:59 +0200 Message-Id: <1397632623-26353-4-git-send-email-hare@suse.de> X-Mailer: git-send-email 1.8.1.4 In-Reply-To: <1397632623-26353-1-git-send-email-hare@suse.de> References: <1397632623-26353-1-git-send-email-hare@suse.de> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.135.220.15 Cc: Paolo Bonzini , Alexander Graf , Stefan Hajnoczi , Hannes Reinecke Subject: [Qemu-devel] [PATCH 3/7] megasas: add MegaRAID SAS 2108 emulation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The 2108 chip supports MSI and MSI-X, so update the emulation to support both chips. Signed-off-by: Hannes Reinecke --- hw/scsi/megasas.c | 95 ++++++++++++++++++++++++++++++++++++++++++------ hw/scsi/mfi.h | 7 ++++ include/hw/pci/pci_ids.h | 1 + 3 files changed, 91 insertions(+), 12 deletions(-) diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index ae3e9d6..687115e 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -30,7 +30,7 @@ #include "mfi.h" -#define MEGASAS_VERSION "1.71" +#define MEGASAS_VERSION "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 +90,8 @@ typedef struct MegasasState { int intr_mask; int doorbell; int busy; + int diag; + int adp_reset; MegasasCmd *event_cmd; int event_locale; @@ -115,12 +117,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 +689,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 +703,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,7 +732,11 @@ 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); @@ -1890,6 +1903,8 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr, unsigned size) { MegasasState *s = opaque; + PCIDevice *pci_dev = PCI_DEVICE(s); + PCIDeviceClass *pci_class = PCI_DEVICE_GET_CLASS(pci_dev); uint32_t retval = 0; switch (addr) { @@ -1905,7 +1920,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: @@ -1914,6 +1933,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; @@ -1922,6 +1944,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) { @@ -1996,6 +2020,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; @@ -2128,10 +2174,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 */ @@ -2151,14 +2205,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)) { @@ -2260,9 +2314,26 @@ static const TypeInfo megasas_info = { .class_init = megasas_class_init, }; +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->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 cd8355b..c365356 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