]> git.proxmox.com Git - qemu.git/blobdiff - hw/megasas.c
softmmu: move include files to include/sysemu/
[qemu.git] / hw / megasas.c
index b99fa9792e78e602947a5343eaf28ec040d472a0..eb191f5e12c033ef2d2a45208de61aaf06deadeb 100644 (file)
  */
 
 #include "hw.h"
-#include "pci.h"
-#include "dma.h"
-#include "msix.h"
-#include "iov.h"
+#include "pci/pci.h"
+#include "sysemu/dma.h"
+#include "pci/msix.h"
+#include "qemu/iov.h"
 #include "scsi.h"
 #include "scsi-defs.h"
-#include "block_int.h"
 #include "trace.h"
 
 #include "mfi.h"
 #define MEGASAS_MAX_SECTORS 0xFFFF      /* No real limit */
 #define MEGASAS_MAX_ARRAYS 128
 
+#define MEGASAS_HBA_SERIAL "QEMU123456"
+#define NAA_LOCALLY_ASSIGNED_ID 0x3ULL
+#define IEEE_COMPANY_LOCALLY_ASSIGNED 0x525400
+
 #define MEGASAS_FLAG_USE_JBOD      0
 #define MEGASAS_MASK_USE_JBOD      (1 << MEGASAS_FLAG_USE_JBOD)
 #define MEGASAS_FLAG_USE_MSIX      1
@@ -55,8 +58,8 @@ typedef struct MegasasCmd {
     uint16_t count;
     uint64_t context;
 
-    target_phys_addr_t pa;
-    target_phys_addr_t pa_size;
+    hwaddr pa;
+    hwaddr pa_size;
     union mfi_frame *frame;
     SCSIRequest *req;
     QEMUSGList qsg;
@@ -89,6 +92,9 @@ typedef struct MegasasState {
     int shutdown_event;
     int boot_event;
 
+    uint64_t sas_addr;
+    char *hba_serial;
+
     uint64_t reply_queue_pa;
     void *reply_queue;
     int reply_queue_len;
@@ -270,7 +276,7 @@ static int megasas_build_sense(MegasasCmd *cmd, uint8_t *sense_ptr,
     uint8_t sense_len)
 {
     uint32_t pa_hi = 0, pa_lo;
-    target_phys_addr_t pa;
+    hwaddr pa;
 
     if (sense_len > cmd->frame->header.sense_len) {
         sense_len = cmd->frame->header.sense_len;
@@ -372,14 +378,16 @@ static uint64_t megasas_fw_time(void)
     return bcd_time;
 }
 
-static uint64_t megasas_gen_sas_addr(uint64_t id)
+/*
+ * Default disk sata address
+ * 0x1221 is the magic number as
+ * present in real hardware,
+ * so use it here, too.
+ */
+static uint64_t megasas_get_sata_addr(uint16_t id)
 {
-    uint64_t addr;
-
-    addr = 0x5001a4aULL << 36;
-    addr |= id & 0xfffffffff;
-
-    return addr;
+    uint64_t addr = (0x1221ULL << 48);
+    return addr & (id << 24);
 }
 
 /*
@@ -395,7 +403,7 @@ static int megasas_next_index(MegasasState *s, int index, int limit)
 }
 
 static MegasasCmd *megasas_lookup_frame(MegasasState *s,
-    target_phys_addr_t frame)
+    hwaddr frame)
 {
     MegasasCmd *cmd = NULL;
     int num = 0, index;
@@ -415,7 +423,7 @@ static MegasasCmd *megasas_lookup_frame(MegasasState *s,
 }
 
 static MegasasCmd *megasas_next_frame(MegasasState *s,
-    target_phys_addr_t frame)
+    hwaddr frame)
 {
     MegasasCmd *cmd = NULL;
     int num = 0, index;
@@ -443,11 +451,11 @@ static MegasasCmd *megasas_next_frame(MegasasState *s,
 }
 
 static MegasasCmd *megasas_enqueue_frame(MegasasState *s,
-    target_phys_addr_t frame, uint64_t context, int count)
+    hwaddr frame, uint64_t context, int count)
 {
     MegasasCmd *cmd = NULL;
     int frame_size = MFI_FRAME_SIZE * 16;
-    target_phys_addr_t frame_size_p = frame_size;
+    hwaddr frame_size_p = frame_size;
 
     cmd = megasas_next_frame(s, frame);
     /* All frames busy */
@@ -544,7 +552,7 @@ static void megasas_reset_frames(MegasasState *s)
 static void megasas_abort_command(MegasasCmd *cmd)
 {
     if (cmd->req) {
-        scsi_req_abort(cmd->req, ABORTED_COMMAND);
+        scsi_req_cancel(cmd->req);
         cmd->req = NULL;
     }
 }
@@ -552,7 +560,7 @@ static void megasas_abort_command(MegasasCmd *cmd)
 static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd)
 {
     uint32_t pa_hi, pa_lo;
-    target_phys_addr_t iq_pa, initq_size;
+    hwaddr iq_pa, initq_size;
     struct mfi_init_qinfo *initq;
     uint32_t flags;
     int ret = MFI_STAT_OK;
@@ -643,7 +651,6 @@ static void megasas_finish_dcmd(MegasasCmd *cmd, uint32_t iov_size)
         }
     }
     cmd->iov_size = 0;
-    return;
 }
 
 static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
@@ -652,10 +659,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
     size_t dcmd_size = sizeof(info);
     BusChild *kid;
     int num_ld_disks = 0;
-
-    QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
-        num_ld_disks++;
-    }
+    uint16_t sdev_id;
 
     memset(&info, 0x0, cmd->iov_size);
     if (cmd->iov_size < dcmd_size) {
@@ -669,14 +673,32 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd)
     info.pci.subvendor = cpu_to_le16(PCI_VENDOR_ID_LSI_LOGIC);
     info.pci.subdevice = cpu_to_le16(0x1013);
 
-    info.host.type = MFI_INFO_HOST_PCIX;
+    /*
+     * 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 = 2;
-    info.device.port_addr[0] = cpu_to_le64(megasas_gen_sas_addr((uint64_t)s));
+    info.device.port_count = 8;
+    QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) {
+        SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child);
+
+        if (num_ld_disks < 8) {
+            sdev_id = ((sdev->id & 0xFF) >> 8) | (sdev->lun & 0xFF);
+            info.device.port_addr[num_ld_disks] =
+                cpu_to_le64(megasas_get_sata_addr(sdev_id));
+        }
+        num_ld_disks++;
+    }
 
     memcpy(info.product_name, "MegaRAID SAS 8708EM2", 20);
-    snprintf(info.serial_number, 32, "QEMU%08lx",
-             (unsigned long)s & 0xFFFFFFFF);
+    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);
@@ -761,7 +783,7 @@ static int megasas_mfc_get_defaults(MegasasState *s, MegasasCmd *cmd)
         return MFI_STAT_INVALID_PARAMETER;
     }
 
-    info.sas_addr = cpu_to_le64(megasas_gen_sas_addr((uint64_t)s));
+    info.sas_addr = cpu_to_le64(s->sas_addr);
     info.stripe_size = 3;
     info.flush_time = 4;
     info.background_rate = 30;
@@ -891,7 +913,7 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd)
         info.addr[num_pd_disks].scsi_dev_type = sdev->type;
         info.addr[num_pd_disks].connect_port_bitmap = 0x1;
         info.addr[num_pd_disks].sas_addr[0] =
-            cpu_to_le64(megasas_gen_sas_addr((uint64_t)sdev));
+            cpu_to_le64(megasas_get_sata_addr(sdev_id));
         num_pd_disks++;
         offset += sizeof(struct mfi_pd_address);
     }
@@ -994,7 +1016,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun,
     info->slot_number = (sdev->id & 0xFF);
     info->path_info.count = 1;
     info->path_info.sas_addr[0] =
-        cpu_to_le64(megasas_gen_sas_addr((uint64_t)sdev));
+        cpu_to_le64(megasas_get_sata_addr(sdev_id));
     info->connected_port_bitmap = 0x1;
     info->device_speed = 1;
     info->link_speed = 1;
@@ -1057,6 +1079,7 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd)
         /* Logical device size is in blocks */
         bdrv_get_geometry(conf->bs, &ld_size);
         info.ld_list[num_ld_disks].ld.v.target_id = sdev->id;
+        info.ld_list[num_ld_disks].ld.v.lun_id = sdev->lun;
         info.ld_list[num_ld_disks].state = MFI_LD_STATE_OPTIMAL;
         info.ld_list[num_ld_disks].size = cpu_to_le64(ld_size);
         num_ld_disks++;
@@ -1273,7 +1296,7 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd)
 
 static int megasas_cache_flush(MegasasState *s, MegasasCmd *cmd)
 {
-    qemu_aio_flush();
+    bdrv_drain_all();
     return MFI_STAT_OK;
 }
 
@@ -1290,35 +1313,16 @@ static int megasas_cluster_reset_ld(MegasasState *s, MegasasCmd *cmd)
 
 static int megasas_dcmd_set_properties(MegasasState *s, MegasasCmd *cmd)
 {
-    uint8_t *dummy = g_malloc(cmd->iov_size);
-
-    dma_buf_write(dummy, cmd->iov_size, &cmd->qsg);
-
-    trace_megasas_dcmd_dump_frame(0,
-            dummy[0x00], dummy[0x01], dummy[0x02], dummy[0x03],
-            dummy[0x04], dummy[0x05], dummy[0x06], dummy[0x07]);
-    trace_megasas_dcmd_dump_frame(1,
-            dummy[0x08], dummy[0x09], dummy[0x0a], dummy[0x0b],
-            dummy[0x0c], dummy[0x0d], dummy[0x0e], dummy[0x0f]);
-    trace_megasas_dcmd_dump_frame(2,
-            dummy[0x10], dummy[0x11], dummy[0x12], dummy[0x13],
-            dummy[0x14], dummy[0x15], dummy[0x16], dummy[0x17]);
-    trace_megasas_dcmd_dump_frame(3,
-            dummy[0x18], dummy[0x19], dummy[0x1a], dummy[0x1b],
-            dummy[0x1c], dummy[0x1d], dummy[0x1e], dummy[0x1f]);
-    trace_megasas_dcmd_dump_frame(4,
-            dummy[0x20], dummy[0x21], dummy[0x22], dummy[0x23],
-            dummy[0x24], dummy[0x25], dummy[0x26], dummy[0x27]);
-    trace_megasas_dcmd_dump_frame(5,
-            dummy[0x28], dummy[0x29], dummy[0x2a], dummy[0x2b],
-            dummy[0x2c], dummy[0x2d], dummy[0x2e], dummy[0x2f]);
-    trace_megasas_dcmd_dump_frame(6,
-            dummy[0x30], dummy[0x31], dummy[0x32], dummy[0x33],
-            dummy[0x34], dummy[0x35], dummy[0x36], dummy[0x37]);
-    trace_megasas_dcmd_dump_frame(7,
-            dummy[0x38], dummy[0x39], dummy[0x3a], dummy[0x3b],
-            dummy[0x3c], dummy[0x3d], dummy[0x3e], dummy[0x3f]);
-    g_free(dummy);
+    struct mfi_ctrl_props info;
+    size_t dcmd_size = sizeof(info);
+
+    if (cmd->iov_size < dcmd_size) {
+        trace_megasas_dcmd_invalid_xfer_len(cmd->index, cmd->iov_size,
+                                            dcmd_size);
+        return MFI_STAT_INVALID_PARAMETER;
+    }
+    dma_buf_write((uint8_t *)&info, cmd->iov_size, &cmd->qsg);
+    trace_megasas_dcmd_unsupported(cmd->index, cmd->iov_size);
     return MFI_STAT_OK;
 }
 
@@ -1767,7 +1771,7 @@ static void megasas_command_cancel(SCSIRequest *req)
 static int megasas_handle_abort(MegasasState *s, MegasasCmd *cmd)
 {
     uint64_t abort_ctx = le64_to_cpu(cmd->frame->abort.abort_context);
-    target_phys_addr_t abort_addr, addr_hi, addr_lo;
+    hwaddr abort_addr, addr_hi, addr_lo;
     MegasasCmd *abort_cmd;
 
     addr_hi = le32_to_cpu(cmd->frame->abort.abort_mfi_addr_hi);
@@ -1857,7 +1861,7 @@ static void megasas_handle_frame(MegasasState *s, uint64_t frame_addr,
     }
 }
 
-static uint64_t megasas_mmio_read(void *opaque, target_phys_addr_t addr,
+static uint64_t megasas_mmio_read(void *opaque, hwaddr addr,
                                   unsigned size)
 {
     MegasasState *s = opaque;
@@ -1893,7 +1897,7 @@ static uint64_t megasas_mmio_read(void *opaque, target_phys_addr_t addr,
     return retval;
 }
 
-static void megasas_mmio_write(void *opaque, target_phys_addr_t addr,
+static void megasas_mmio_write(void *opaque, hwaddr addr,
                                uint64_t val, unsigned size)
 {
     MegasasState *s = opaque;
@@ -1973,13 +1977,13 @@ static const MemoryRegionOps megasas_mmio_ops = {
     }
 };
 
-static uint64_t megasas_port_read(void *opaque, target_phys_addr_t addr,
+static uint64_t megasas_port_read(void *opaque, hwaddr addr,
                                   unsigned size)
 {
     return megasas_mmio_read(opaque, addr & 0xff, size);
 }
 
-static void megasas_port_write(void *opaque, target_phys_addr_t addr,
+static void megasas_port_write(void *opaque, hwaddr addr,
                                uint64_t val, unsigned size)
 {
     megasas_mmio_write(opaque, addr & 0xff, val, size);
@@ -1995,7 +1999,7 @@ static const MemoryRegionOps megasas_port_ops = {
     }
 };
 
-static uint64_t megasas_queue_read(void *opaque, target_phys_addr_t addr,
+static uint64_t megasas_queue_read(void *opaque, hwaddr addr,
                                    unsigned size)
 {
     return 0;
@@ -2059,7 +2063,7 @@ static const VMStateDescription vmstate_megasas = {
     }
 };
 
-static int megasas_scsi_uninit(PCIDevice *d)
+static void megasas_scsi_uninit(PCIDevice *d)
 {
     MegasasState *s = DO_UPCAST(MegasasState, dev, d);
 
@@ -2069,7 +2073,6 @@ static int megasas_scsi_uninit(PCIDevice *d)
     memory_region_destroy(&s->mmio_io);
     memory_region_destroy(&s->port_io);
     memory_region_destroy(&s->queue_io);
-    return 0;
 }
 
 static const struct SCSIBusInfo megasas_scsi_info = {
@@ -2122,6 +2125,16 @@ static int megasas_scsi_init(PCIDevice *dev)
         msix_vector_use(&s->dev, 0);
     }
 
+    if (!s->sas_addr) {
+        s->sas_addr = ((NAA_LOCALLY_ASSIGNED_ID << 24) |
+                       IEEE_COMPANY_LOCALLY_ASSIGNED) << 36;
+        s->sas_addr |= (pci_bus_num(dev->bus) << 16);
+        s->sas_addr |= (PCI_SLOT(dev->devfn) << 8);
+        s->sas_addr |= PCI_FUNC(dev->devfn);
+    }
+    if (!s->hba_serial) {
+       s->hba_serial = g_strdup(MEGASAS_HBA_SERIAL);
+    }
     if (s->fw_sge >= MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE) {
         s->fw_sge = MEGASAS_MAX_SGE - MFI_PASS_FRAME_SIZE;
     } else if (s->fw_sge >= 128 - MFI_PASS_FRAME_SIZE) {
@@ -2156,6 +2169,8 @@ static Property megasas_properties[] = {
                        MEGASAS_DEFAULT_SGE),
     DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds,
                        MEGASAS_DEFAULT_FRAMES),
+    DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial),
+    DEFINE_PROP_HEX64("sas_address", MegasasState, sas_addr, 0),
 #ifdef USE_MSIX
     DEFINE_PROP_BIT("use_msix", MegasasState, flags,
                     MEGASAS_FLAG_USE_MSIX, false),