qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 3/3] megasas: LSI Megaraid SAS emulation


From: Stefan Hajnoczi
Subject: Re: [Qemu-devel] [PATCH 3/3] megasas: LSI Megaraid SAS emulation
Date: Sat, 2 Jul 2011 17:14:08 +0100

On Fri, Jul 1, 2011 at 4:35 PM, Hannes Reinecke <address@hidden> wrote:
> +static void megasas_mmio_writel(void *opaque, target_phys_addr_t addr,
> +                                uint32_t val)
> +{
> +    MPTState *s = opaque;
> +    target_phys_addr_t frame_addr;
> +    uint32_t frame_count;
> +    int i;
> +
> +    DPRINTF_REG("writel mmio %lx: %x\n", (unsigned long)addr, val);
> +
> +    switch (addr) {
> +    case MFI_IDB:
> +        if (val & MFI_FWINIT_ABORT) {
> +            /* Abort all pending cmds */
> +            for (i = 0; i <= s->fw_cmds; i++) {
> +                megasas_abort_command(&s->frames[i]);
> +            }
> +        }
> +        if (val & MFI_FWINIT_READY) {
> +            /* move to FW READY */
> +            megasas_soft_reset(s);
> +        }
> +        if (val & MFI_FWINIT_MFIMODE) {
> +            /* discard MFIs */
> +        }
> +        break;
> +    case MFI_OMSK:
> +        s->intr_mask = val;
> +        if (!MEGASAS_INTR_ENABLED(s)) {
> +            qemu_irq_lower(s->dev.irq[0]);
> +        }
> +        break;
> +    case MFI_ODCR0:
> +        /* Update reply queue pointer */
> +        DPRINTF_QUEUE("Update reply queue head %x busy %d\n",
> +                      s->reply_queue_index, s->busy);
> +        stl_phys(s->producer_pa, s->reply_queue_index);
> +        s->doorbell = 0;
> +        qemu_irq_lower(s->dev.irq[0]);
> +        break;
> +    case MFI_IQPH:
> +        s->frame_hi = val;
> +        break;
> +    case MFI_IQPL:
> +    case MFI_IQP:
> +        /* Received MFI frame address */
> +        frame_addr = (val & ~0xFF);
> +        /* Add possible 64 bit offset */
> +        frame_addr |= (uint64_t)s->frame_hi;

Is this missing << 32 before ORing the high bits?

> +static int megasas_scsi_uninit(PCIDevice *d)
> +{
> +    MPTState *s = DO_UPCAST(MPTState, dev, d);
> +
> +    cpu_unregister_io_memory(s->mmio_io_addr);

Need to unregister io_addr and queue_addr.

> +
> +    return 0;
> +}
> +
> +static const struct SCSIBusOps megasas_scsi_ops = {
> +    .transfer_data = megasas_xfer_complete,
> +    .complete = megasas_command_complete,
> +    .cancel = megasas_command_cancel,
> +};
> +
> +static int megasas_scsi_init(PCIDevice *dev)
> +{
> +    MPTState *s = DO_UPCAST(MPTState, dev, dev);
> +    uint8_t *pci_conf;
> +    int i;
> +
> +    pci_conf = s->dev.config;
> +
> +    /* PCI Vendor ID (word) */
> +    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_LSI_LOGIC);
> +    /* PCI device ID (word) */
> +    pci_config_set_device_id(pci_conf,  PCI_DEVICE_ID_LSI_SAS1078);
> +    /* PCI subsystem ID */
> +    pci_set_word(&pci_conf[PCI_SUBSYSTEM_VENDOR_ID], 0x1000);
> +    pci_set_word(&pci_conf[PCI_SUBSYSTEM_ID], 0x1013);
> +    /* PCI base class code */
> +    pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_RAID);


PCIDeviceInfo now has vendor_id, device_id, and other fields.  These
values can be set in the megasas_info definition below.

> +
> +    /* PCI latency timer = 0 */
> +    pci_conf[0x0d] = 0;
> +    /* Interrupt pin 1 */
> +    pci_conf[0x3d] = 0x01;
> +
> +    s->mmio_io_addr = cpu_register_io_memory(megasas_mmio_readfn,
> +                                             megasas_mmio_writefn, s,
> +                                             DEVICE_NATIVE_ENDIAN);
> +    s->io_addr = cpu_register_io_memory(megasas_io_readfn,
> +                                        megasas_io_writefn, s,
> +                                        DEVICE_NATIVE_ENDIAN);
> +    s->queue_addr = cpu_register_io_memory(megasas_queue_readfn,
> +                                           megasas_queue_writefn, s,
> +                                           DEVICE_NATIVE_ENDIAN);

Should these be little-endian?

> +    pci_register_bar((struct PCIDevice *)s, 0, 0x40000,
> +                     PCI_BASE_ADDRESS_SPACE_MEMORY, megasas_mmio_mapfunc);
> +    pci_register_bar((struct PCIDevice *)s, 2, 256,
> +                     PCI_BASE_ADDRESS_SPACE_IO, megasas_io_mapfunc);
> +    pci_register_bar((struct PCIDevice *)s, 3, 0x40000,
> +                     PCI_BASE_ADDRESS_SPACE_MEMORY, megasas_queue_mapfunc);
> +    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) {
> +        s->fw_sge = 128 - MFI_PASS_FRAME_SIZE;
> +    } else {
> +        s->fw_sge = 64 - MFI_PASS_FRAME_SIZE;
> +    }
> +    if (s->fw_cmds > MEGASAS_MAX_FRAMES) {
> +        s->fw_cmds = MEGASAS_MAX_FRAMES;
> +    }
> +    if (s->raid_mode_str) {
> +        if (!strcmp(s->raid_mode_str, "jbod")) {
> +            s->is_jbod = 1;
> +        } else {
> +            s->is_jbod = 0;
> +        }
> +    }
> +    DPRINTF("Using %d sges, %d cmds, %s mode\n",
> +            s->fw_sge, s->fw_cmds, s->is_jbod ? "jbod" : "raid");
> +    s->fw_luns = (MFI_MAX_LD > MAX_SCSI_DEVS) ?
> +        MAX_SCSI_DEVS : MFI_MAX_LD;
> +    s->producer_pa = 0;
> +    s->consumer_pa = 0;
> +    for (i = 0; i < s->fw_cmds; i++) {
> +        s->frames[i].index = i;
> +        s->frames[i].context = -1;
> +        s->frames[i].pa = 0;
> +        s->frames[i].state = s;
> +    }

It is not clear to me that all register state is initialized here.
megasas_soft_reset() seems to touch fw_state and intr_mask but will
not be called until mmio_writel(MFI_IDB, MFI_FWINIT_READY).  Are there
any missing fields that need to be initialized here?

Stefan



reply via email to

[Prev in Thread] Current Thread [Next in Thread]