From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:47604) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TBaCi-0003xI-80 for qemu-devel@nongnu.org; Tue, 11 Sep 2012 19:49:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TBaCR-0004kG-QS for qemu-devel@nongnu.org; Tue, 11 Sep 2012 19:49:16 -0400 Received: from mx1.redhat.com ([209.132.183.28]:23354) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TBaCQ-0004jn-QN for qemu-devel@nongnu.org; Tue, 11 Sep 2012 19:48:59 -0400 Date: Wed, 12 Sep 2012 02:50:21 +0300 From: "Michael S. Tsirkin" Message-ID: <20120911235020.GC29044@redhat.com> References: <1347382813-5662-1-git-send-email-Don@CloudSwitch.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1347382813-5662-1-git-send-email-Don@CloudSwitch.com> Subject: Re: [Qemu-devel] [PATCH] hw: Add support for new LSI Logic devices. List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Don Slutz Cc: qemu-devel@nongnu.org On Tue, Sep 11, 2012 at 01:00:13PM -0400, Don Slutz wrote: > Add LSI53C1030, SAS1068, SAS1068e. Based on code from "VirtualBox Open Source Edition". > Based on QEMU MegaRAID SAS 8708EM2. > > This is a common VMware disk controller. I think you mean VMware emulates this controller too, pls say it explicitly in the commit log. > SEABIOS change for booting is in the works. > > Tested with Fedora 16, 17. CentoOS 6. Windows 2003R2 and 2008R2. > > Signed-off-by: Don Slutz Minor comments below. Coding style does not adhere to qemu standards, I guess you know that :) Otherwise, from pci side of things this looks OK. I did not look at the scsi side of things. > --- > default-configs/pci.mak | 1 + > hw/Makefile.objs | 1 + > hw/lsilogic.c | 2743 ++++++++++++++++++++++++++++++++++++++ > hw/lsilogic.h | 3365 +++++++++++++++++++++++++++++++++++++++++++++++ > hw/pci_ids.h | 4 + > trace-events | 26 + > 6 files changed, 6140 insertions(+), 0 deletions(-) > create mode 100644 hw/lsilogic.c > create mode 100644 hw/lsilogic.h > > diff --git a/default-configs/pci.mak b/default-configs/pci.mak > index 69e18f1..ae4873d 100644 > --- a/default-configs/pci.mak > +++ b/default-configs/pci.mak > @@ -11,6 +11,7 @@ CONFIG_PCNET_PCI=y > CONFIG_PCNET_COMMON=y > CONFIG_LSI_SCSI_PCI=y > CONFIG_MEGASAS_SCSI_PCI=y > +CONFIG_LSILOGIC_SCSI_PCI=y > CONFIG_RTL8139_PCI=y > CONFIG_E1000_PCI=y > CONFIG_IDE_CORE=y > diff --git a/hw/Makefile.objs b/hw/Makefile.objs > index 6dfebd2..e5f939c 100644 > --- a/hw/Makefile.objs > +++ b/hw/Makefile.objs > @@ -115,6 +115,7 @@ hw-obj-$(CONFIG_OPENCORES_ETH) += opencores_eth.o > # SCSI layer > hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o > hw-obj-$(CONFIG_MEGASAS_SCSI_PCI) += megasas.o > +hw-obj-$(CONFIG_LSILOGIC_SCSI_PCI) += lsilogic.o > hw-obj-$(CONFIG_ESP) += esp.o > hw-obj-$(CONFIG_ESP_PCI) += esp-pci.o > > diff --git a/hw/lsilogic.c b/hw/lsilogic.c > new file mode 100644 > index 0000000..1c0a54f > --- /dev/null > +++ b/hw/lsilogic.c > @@ -0,0 +1,2743 @@ > +/* > + * QEMU LSILOGIC LSI53C1030 SCSI and SAS1068 Host Bus Adapter emulation > + * Based on the QEMU Megaraid emulator and the VirtualBox LsiLogic > + * LSI53c1030 SCSI controller > + * > + * Copyright (c) 2009-2012 Hannes Reinecke, SUSE Labs > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see . > + */ > + > +/* Id: DevLsiLogicSCSI.cpp 40642 2012-03-26 13:14:08Z vboxsync $ */ > +/** @file > + * VBox storage devices: LsiLogic LSI53c1030 SCSI controller. > + */ > + > +/* > + * Copyright (C) 2006-2009 Oracle Corporation > + * > + * This file is part of VirtualBox Open Source Edition (OSE), as > + * available from http://www.virtualbox.org. This file is free software; > + * you can redistribute it and/or modify it under the terms of the GNU > + * General Public License (GPL) as published by the Free Software > + * Foundation, in version 2 as it comes in the "COPYING" file of the > + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the > + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. > + */ > + > + I suspect you need to rewrite above: probably add all copyrights in 1st header and make it v2 only. > +#include "hw.h" > +#include "pci.h" > +#include "dma.h" > +#include "msix.h" > +#include "iov.h" > +#include "scsi.h" > +#include "scsi-defs.h" > +#include "block_int.h" > +#include "trace.h" > + > +#include "lsilogic.h" > + > +#define RT_ELEMENTS(aArray) (sizeof(aArray) / sizeof((aArray)[0])) Pls replace with ARRAY_SIZE. > + > +#define LSILOGIC_MAX_FRAMES 2048 /* Firmware limit at 65535 */ > + > +#define NAA_LOCALLY_ASSIGNED_ID 0x3ULL > +#define IEEE_COMPANY_LOCALLY_ASSIGNED 0x525400 > + > +#define LSILOGIC_FLAG_USE_MSIX 0 > +#define LSILOGIC_MASK_USE_MSIX (1 << LSILOGIC_FLAG_USE_MSIX) > +#define LSILOGIC_FLAG_USE_QUEUE64 1 > +#define LSILOGIC_MASK_USE_QUEUE64 (1 << LSILOGIC_FLAG_USE_QUEUE64) > +#define LSILOGIC_CMD_BUSY (1 << 0) > + > +typedef struct LsilogicCmd { > + uint32_t index; > + uint16_t flags; > + uint16_t count; > + uint64_t context; > + > + target_phys_addr_t host_msg_frame_pa; > + MptRequestUnion request; > + MptReplyUnion reply; > + SCSIRequest *req; > + QEMUSGList qsg; > + uint32_t sge_cnt; > + void *iov_buf; > + size_t iov_size; > + size_t iov_offset; > + struct LsilogicState *state; > +} LsilogicCmd; > + > +typedef struct Lsilogic_device { > + struct LsilogicState *pLsiLogic; > + > + uint32_t iLUN; > + uint32_t cOutstandingRequests; > + uint32_t *pDrvBase; > +} Lsilogic_device; > + > +typedef struct LsilogicState { > + PCIDevice dev; > + MemoryRegion mmio_io; > + MemoryRegion port_io; > + MemoryRegion diag_io; > + > + MptConfigurationPagesSupported *config_pages; > + > + LSILOGICCTRLTYPE ctrl_type; > + LSILOGICSTATE state; > + LSILOGICWHOINIT who_init; > + uint16_t next_handle; > + uint32_t ports; > + uint32_t flags; > + uint32_t intr_mask; > + uint32_t intr_status; > + uint32_t doorbell; > + uint32_t busy; > + bool event_notification_enabled; > + bool diagnostic_enabled; > + uint32 diagnostic_access_idx; > + /** Maximum number of devices the driver reported he can handle. */ > + uint16_t max_devices; > + /** Maximum number of buses the driver reported he can handle. */ > + uint16_t max_buses; > + > + uint64_t sas_addr; > + > + /* Buffer for messages which are passed through the doorbell > + * using the handshake method. > + */ > + uint32_t drbl_message[(sizeof(MptRequestUnion)+sizeof(uint32_t)-1)/ > + sizeof(uint32_t)]; > + uint16_t drbl_message_index; > + uint16_t drbl_message_size; /** Size of the message in dwords. */ > + > + MptReplyUnion reply_buffer; > + uint16_t next_reply_entry_read; > + uint16_t reply_size; /* in 16bit words. */ > + > + uint16_t IOC_fault_code; /* if we are in the fault state. */ > + /** Current size of reply message frames in the guest. */ > + uint16_t reply_frame_size; > + /** Upper 32 bits of the message frame address to > + locate requests in guest memory. */ > + uint32_t host_mfa_high_addr; > + /** Upper 32 bits of the sense buffer address. */ > + uint32_t sense_buffer_high_addr; > + > + uint32_t reply_queue_entries; > + uint32_t request_queue_entries; > + > + uint32_t *reply_post_queue; > + uint32_t *reply_free_queue; > + uint32_t *request_queue; > + uint32_t reply_free_queue_next_entry_free_write; > + uint32_t reply_free_queue_next_address_read; > + > + uint32_t reply_post_queue_next_entry_free_write; > + uint32_t reply_post_queue_next_address_read; > + > + uint32_t request_queue_next_entry_free_write; > + uint32_t request_queue_next_address_read; > + > + uint32_t next_frame; > + LsilogicCmd * frames[LSILOGIC_MAX_FRAMES]; > + > + SCSIBus bus; > +} LsilogicState; > + > +#define LSILOGIC_INTR_DISABLED_MASK 0xFFFFFFFF > + > +static bool lsilogic_use_msix(LsilogicState *s) > +{ > + return s->flags & LSILOGIC_MASK_USE_MSIX; > +} > + > +static bool lsilogic_is_sas(LsilogicState *s) > +{ > + return true; > +} > + > +static uint16_t lsilogicGetHandle(LsilogicState *s) > +{ > + uint16_t u16Handle = s->next_handle++; > + return u16Handle; > +} > + > +static void lsilogic_soft_reset(LsilogicState *s); > + > +static void lsilogic_update_interrupt(LsilogicState *s) > +{ > + uint32_t uIntSts; > + > + uIntSts = (s->intr_status & ~LSILOGIC_REG_HOST_INTR_STATUS_DOORBELL_STS); > + uIntSts &= ~(s->intr_mask & ~LSILOGIC_REG_HOST_INTR_MASK_IRQ_ROUTING); > + > + if (uIntSts) { > + if (msix_enabled(&s->dev)) { > + trace_lsilogic_msix_raise(0); > + msix_notify(&s->dev, 0); > + } else { > + trace_lsilogic_irq_raise(); > + qemu_irq_raise(s->dev.irq[0]); > + } > + } else if (!msix_enabled(&s->dev)) { > + trace_lsilogic_irq_lower(); > + qemu_irq_lower(s->dev.irq[0]); > + } > +} > + > +static void lsilogic_finish_address_reply(LsilogicState *s, > + MptReplyUnion *reply, bool fForceReplyFifo) > +{ > + /* > + * If we are in a doorbell function we set the reply size now and > + * set the system doorbell status interrupt to notify the guest that > + * we are ready to send the reply. > + */ > + if (s->doorbell && !fForceReplyFifo) { > + /* Set size of the reply in 16bit words. > + The size in the reply is in 32bit dwords. */ > + s->reply_size = reply->Header.u8MessageLength * 2; > + s->next_reply_entry_read = 0; > + s->intr_status |= LSILOGIC_REG_HOST_INTR_STATUS_SYSTEM_DOORBELL; > + lsilogic_update_interrupt(s); > + } else { > + /* Grab a free reply message from the queue. */ > + > + /* Check for a free reply frame and room on the post queue. */ > + if ((s->reply_free_queue_next_address_read == > + s->reply_free_queue_next_entry_free_write)) { > + s->IOC_fault_code = LSILOGIC_IOCSTATUS_INSUFFICIENT_RESOURCES; > + s->state = LSILOGICSTATE_FAULT; > + return; > + } > + uint32_t reply_frame_address_low = > + s->reply_free_queue[s->reply_free_queue_next_address_read]; > + > + uint32_t next_addr = (s->reply_free_queue_next_address_read + 1) % > + s->reply_queue_entries; > + if (next_addr != s->reply_free_queue_next_entry_free_write) { > + s->reply_free_queue_next_address_read = next_addr; > + } > + > + uint64_t reply_message_pa = ((uint64_t)s->host_mfa_high_addr << 32) | > + reply_frame_address_low; > + int reply_copied = (s->reply_frame_size < sizeof(MptReplyUnion)) ? > + s->reply_frame_size : sizeof(MptReplyUnion); > + > + cpu_physical_memory_write((target_phys_addr_t)reply_message_pa, > + (uint8_t *)reply, reply_copied); > + > + /* Write low 32bits of reply frame into post reply queue. */ > + > + /* We have a address reply. Set the 31th bit to indicate that. */ > + s->reply_post_queue[s->reply_post_queue_next_entry_free_write++] = > + (1<<31) | (reply_frame_address_low >> 1); > + s->reply_post_queue_next_entry_free_write %= s->reply_queue_entries; > + > + if (fForceReplyFifo) { > + s->doorbell = false; > + s->intr_status |= LSILOGIC_REG_HOST_INTR_STATUS_SYSTEM_DOORBELL; > + } > + > + /* Set interrupt. */ > + s->intr_status |= LSILOGIC_REG_HOST_INTR_STATUS_REPLY_INTR; > + lsilogic_update_interrupt(s); > + } > +} > + > +static void lsilogic_abort_command(LsilogicCmd *cmd) > +{ > + if (cmd->req) { > + scsi_req_cancel(cmd->req); > + cmd->req = NULL; > + } > +} > + > + > +static QEMUSGList *lsilogic_get_sg_list(SCSIRequest *req) > +{ > + LsilogicCmd *cmd = req->hba_private; > + > + if (cmd->sge_cnt == 0) { > + return NULL; > + } else { > + return &cmd->qsg; > + } > +} > + > +static void lsilogic_xfer_complete(SCSIRequest *req, uint32_t len) > +{ > + LsilogicCmd *cmd = req->hba_private; > + > + trace_lsilogic_io_complete(cmd->index, len); > + if (cmd->sge_cnt != 0) { > + scsi_req_continue(req); > + return; > + } > +} > + > +static void lsilogic_finish_context_reply(LsilogicState *s, > + uint32_t u32MessageContext) > +{ > + assert(!s->doorbell); > + > + /* Write message context ID into reply post queue. */ > + s->reply_post_queue[s->reply_post_queue_next_entry_free_write++] = > + u32MessageContext; > + s->reply_post_queue_next_entry_free_write %= s->reply_queue_entries; > + > + s->intr_status |= LSILOGIC_REG_HOST_INTR_STATUS_REPLY_INTR; > + lsilogic_update_interrupt(s); > +} > + > +static void lsilogic_command_complete(SCSIRequest *req, > + uint32_t status, size_t resid) > +{ > + LsilogicCmd *cmd = req->hba_private; > + uint8_t sense_buf[SCSI_SENSE_BUF_SIZE]; > + uint8_t sense_len; > + > + target_phys_addr_t sense_buffer_pa = > + cmd->request.SCSIIO.u32SenseBufferLowAddress | > + ((uint64_t)cmd->state->sense_buffer_high_addr << 32); > + > + trace_lsilogic_command_complete(cmd->index, status, resid); > + > + if (cmd->sge_cnt) { > + qemu_sglist_destroy(&cmd->qsg); > + } > + > + sense_len = scsi_req_get_sense(cmd->req, sense_buf, > + SCSI_SENSE_BUF_SIZE); > + req->status = status; > + trace_lsilogic_scsi_complete(cmd->index, req->status, > + cmd->iov_size, req->cmd.xfer); > + > + if (sense_len > 0) { > + cpu_physical_memory_write(sense_buffer_pa, sense_buf, > + MIN(cmd->request.SCSIIO.u8SenseBufferLength, sense_len)); > + } > + > + if (req->status != GOOD) { > + /* The SCSI target encountered an error during processing. > + Post a reply. */ > + memset(&cmd->reply, 0, sizeof(MptReplyUnion)); > + cmd->reply.SCSIIOError.u8TargetID = > + cmd->request.SCSIIO.u8TargetID; > + cmd->reply.SCSIIOError.u8Bus = > + cmd->request.SCSIIO.u8Bus; > + cmd->reply.SCSIIOError.u8MessageLength = 8; > + cmd->reply.SCSIIOError.u8Function = > + cmd->request.SCSIIO.u8Function; > + cmd->reply.SCSIIOError.u8CDBLength = > + cmd->request.SCSIIO.u8CDBLength; > + cmd->reply.SCSIIOError.u8SenseBufferLength = > + cmd->request.SCSIIO.u8SenseBufferLength; > + cmd->reply.SCSIIOError.u8MessageFlags = > + cmd->request.SCSIIO.u8MessageFlags; > + cmd->reply.SCSIIOError.u32MessageContext = > + cmd->request.SCSIIO.u32MessageContext; > + cmd->reply.SCSIIOError.u8SCSIStatus = req->status; > + cmd->reply.SCSIIOError.u8SCSIState = > + MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID; > + cmd->reply.SCSIIOError.u16IOCStatus = 0; > + cmd->reply.SCSIIOError.u32IOCLogInfo = 0; > + cmd->reply.SCSIIOError.u32TransferCount = 0; > + cmd->reply.SCSIIOError.u32SenseCount = sense_len; > + cmd->reply.SCSIIOError.u32ResponseInfo = 0; > + > + lsilogic_finish_address_reply(cmd->state, &cmd->reply, true); > + } else { > + lsilogic_finish_context_reply(cmd->state, > + cmd->request.SCSIIO.u32MessageContext); > + } > + > + scsi_req_unref(cmd->req); > + cmd->req = NULL; > + g_free(cmd); > +} > + > +static void lsilogic_command_cancel(SCSIRequest *req) > +{ > + LsilogicCmd *cmd = req->hba_private; > + > + if (cmd) { > + lsilogic_abort_command(cmd); > + } else { > + scsi_req_unref(req); > + } > +} > + > +static void lsilogic_map_sgl(LsilogicState *s, LsilogicCmd *cmd, > + target_phys_addr_t sgl_pa, uint32_t chain_offset) > +{ > + uint32_t iov_count = 0; > + bool do_mapping = false; > + uint32_t pass; > + > + for (pass = 0; pass < 2; pass++) { > + bool end_of_list = false; > + target_phys_addr_t next_sge_pa = sgl_pa; > + target_phys_addr_t seg_start_pa = sgl_pa; > + uint32_t next_chain_offset = chain_offset; > + > + if (do_mapping) { > + cmd->sge_cnt = iov_count; > + qemu_sglist_init(&cmd->qsg, iov_count, pci_dma_context(&s->dev)); > + } > + while (end_of_list == false) { > + bool end_of_seg = false; > + > + while (end_of_seg == false) { > + MptSGEntryUnion sge; > + cpu_physical_memory_read(next_sge_pa, &sge, > + sizeof(MptSGEntryUnion)); > + assert(sge.Simple32.u2ElementType == MPTSGENTRYTYPE_SIMPLE); > + if (sge.Simple32.u24Length == 0 && sge.Simple32.fEndOfList && > + sge.Simple32.fEndOfBuffer) { > + cmd->sge_cnt = 0; > + return; > + } > + if (sge.Simple32.f64BitAddress) { > + next_sge_pa += sizeof(MptSGEntrySimple64); > + } else { > + next_sge_pa += sizeof(MptSGEntrySimple32); > + } > + if (do_mapping) { > + dma_addr_t iov_pa = sge.Simple32.u32DataBufferAddressLow; > + dma_addr_t iov_size = sge.Simple32.u24Length; > + > + if (sge.Simple32.f64BitAddress) { > + iov_pa |= ((uint64_t)sge.Simple64. > + u32DataBufferAddressHigh) << 32; > + } > + > + qemu_sglist_add(&cmd->qsg, iov_pa, iov_size); > + } > + iov_count++; > + if (sge.Simple32.fEndOfList) { > + end_of_seg = true; > + end_of_list = true; > + } else if (sge.Simple32.fLastElement) { > + end_of_seg = true; > + } > + } > + if (next_chain_offset) { > + MptSGEntryChain sgec; > + cpu_physical_memory_read(seg_start_pa + next_chain_offset, > + &sgec, sizeof(MptSGEntryChain)); > + assert(sgec.u2ElementType == MPTSGENTRYTYPE_CHAIN); > + next_sge_pa = sgec.u32SegmentAddressLow; > + if (sgec.f64BitAddress) { > + next_sge_pa |= > + ((uint64_t)sgec.u32SegmentAddressHigh) << 32; > + } > + seg_start_pa = next_sge_pa; > + next_chain_offset = sgec.u8NextChainOffset * sizeof(uint32_t); > + } > + } > + do_mapping = true; > + } > +} > + > +static int lsilogic_process_SCSIIO_Request(LsilogicState *s, LsilogicCmd *cmd) > +{ > + struct SCSIDevice *sdev = NULL; > + > + if (cmd->request.SCSIIO.u8TargetID < s->max_devices && > + cmd->request.SCSIIO.u8Bus == 0) { > + sdev = scsi_device_find(&s->bus, 0, cmd->request.SCSIIO.u8TargetID, > + cmd->request.SCSIIO.au8LUN[1]); > + cmd->iov_size = le32_to_cpu(cmd->request.SCSIIO.u32DataLength); > + trace_lsilogic_handle_scsi("SCSI IO", 0, > + cmd->request.SCSIIO.u8TargetID, > + cmd->request.SCSIIO.au8LUN[1], sdev, cmd->iov_size); > + if (sdev) { > + uint32_t chain_offset = cmd->request.SCSIIO.u8ChainOffset; > + int32_t len; > + bool is_write; > + > + if (chain_offset) { > + chain_offset = chain_offset * sizeof(uint32_t) - > + sizeof(MptSCSIIORequest); > + } > + > + lsilogic_map_sgl(s, cmd, cmd->host_msg_frame_pa + > + sizeof(MptSCSIIORequest), chain_offset); > + is_write = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET( > + cmd->request.SCSIIO.u32Control) == > + MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE ? > + true : false; > + cmd->state = s; > + cmd->req = scsi_req_new(sdev, cmd->index++, > + cmd->request.SCSIIO.au8LUN[1], > + cmd->request.SCSIIO.au8CDB, cmd); > + len = scsi_req_enqueue(cmd->req); > + if (len < 0) { > + len = -len; > + } > + if (len > 0) { > + if (len > cmd->iov_size) { > + if (is_write) { > + trace_lsilogic_iov_write_overflow(cmd->index, len, > + cmd->iov_size); > + } else { > + trace_lsilogic_iov_read_overflow(cmd->index, len, > + cmd->iov_size); > + } > + } > + if (len < cmd->iov_size) { > + if (is_write) { > + trace_lsilogic_iov_write_underflow(cmd->index, len, > + cmd->iov_size); > + } else { > + trace_lsilogic_iov_read_underflow(cmd->index, len, > + cmd->iov_size); > + } > + cmd->iov_size = len; > + } > + scsi_req_continue(cmd->req); > + } > + if (len > 0) { > + if (is_write) { > + trace_lsilogic_scsi_write_start(cmd->index, len); > + } else { > + trace_lsilogic_scsi_read_start(cmd->index, len); > + } > + } else { > + trace_lsilogic_scsi_nodata(cmd->index); > + } > + return 0; > + } else { > + cmd->reply.SCSIIOError.u16IOCStatus = > + MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE; > + } > + } else { > + if (cmd->request.SCSIIO.u8Bus != 0) { > + cmd->reply.SCSIIOError.u16IOCStatus = > + MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_BUS; > + } else { > + cmd->reply.SCSIIOError.u16IOCStatus = > + MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_TARGETID; > + } > + } > + cmd->reply.SCSIIOError.u8TargetID = > + cmd->request.SCSIIO.u8TargetID; > + cmd->reply.SCSIIOError.u8Bus = > + cmd->request.SCSIIO.u8Bus; > + cmd->reply.SCSIIOError.u8MessageLength = > + sizeof(MptSCSIIOErrorReply) / 4; > + cmd->reply.SCSIIOError.u8Function = > + cmd->request.SCSIIO.u8Function; > + cmd->reply.SCSIIOError.u8CDBLength = > + cmd->request.SCSIIO.u8CDBLength; > + cmd->reply.SCSIIOError.u8SenseBufferLength = > + cmd->request.SCSIIO.u8SenseBufferLength; > + cmd->reply.SCSIIOError.u32MessageContext = > + cmd->request.SCSIIO.u32MessageContext; > + cmd->reply.SCSIIOError.u8SCSIStatus = GOOD; > + cmd->reply.SCSIIOError.u8SCSIState = > + MPT_SCSI_IO_ERROR_SCSI_STATE_TERMINATED; > + cmd->reply.SCSIIOError.u32IOCLogInfo = 0; > + cmd->reply.SCSIIOError.u32TransferCount = 0; > + cmd->reply.SCSIIOError.u32SenseCount = 0; > + cmd->reply.SCSIIOError.u32ResponseInfo = 0; > + > + lsilogic_finish_address_reply(s, &cmd->reply, false); > + g_free(cmd); > + > + return 0; > +} > + > +static void lsilogic_process_message(LsilogicState *s, MptMessageHdr *msg, > + MptReplyUnion *reply); > + > +static bool lsilogic_queue_consumer(LsilogicState *s) > +{ > + /* Only process request which arrived before we > + received the notification. */ > + uint32_t uRequestQueueNextEntryWrite = > + s->request_queue_next_entry_free_write; > + > + /* Go through the messages now and process them. */ > + while ((s->state == LSILOGICSTATE_OPERATIONAL) > + && (s->request_queue_next_address_read != > + uRequestQueueNextEntryWrite)) { > + uint32_t u32RequestMessageFrameDesc = > + s->request_queue[s->request_queue_next_address_read]; > + MptRequestUnion request; > + target_phys_addr_t host_msg_frame_pa; > + > + > + host_msg_frame_pa = ((uint64_t)s->host_mfa_high_addr) << 32 | > + (u32RequestMessageFrameDesc & ~0x03); > + > + /* Read the message header from the guest first. */ > + cpu_physical_memory_read(host_msg_frame_pa, &request.Header, > + sizeof(MptMessageHdr)); > + > + /* Determine the size of the request. */ > + uint32_t cbRequest = 0; > + > + switch (request.Header.u8Function) { > + case MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST: > + cbRequest = sizeof(MptSCSIIORequest); > + break; > + case MPT_MESSAGE_HDR_FUNCTION_SCSI_TASK_MGMT: > + cbRequest = sizeof(MptSCSITaskManagementRequest); > + break; > + case MPT_MESSAGE_HDR_FUNCTION_IOC_INIT: > + cbRequest = sizeof(MptIOCInitRequest); > + break; > + case MPT_MESSAGE_HDR_FUNCTION_IOC_FACTS: > + cbRequest = sizeof(MptIOCFactsRequest); > + break; > + case MPT_MESSAGE_HDR_FUNCTION_CONFIG: > + cbRequest = sizeof(MptConfigurationRequest); > + break; > + case MPT_MESSAGE_HDR_FUNCTION_PORT_FACTS: > + cbRequest = sizeof(MptPortFactsRequest); > + break; > + case MPT_MESSAGE_HDR_FUNCTION_PORT_ENABLE: > + cbRequest = sizeof(MptPortEnableRequest); > + break; > + case MPT_MESSAGE_HDR_FUNCTION_EVENT_NOTIFICATION: > + cbRequest = sizeof(MptEventNotificationRequest); > + break; > + case MPT_MESSAGE_HDR_FUNCTION_FW_DOWNLOAD: > + cbRequest = sizeof(MptFWDownloadRequest); > + break; > + case MPT_MESSAGE_HDR_FUNCTION_FW_UPLOAD: > + cbRequest = sizeof(MptFWUploadRequest); > + break; > + case MPT_MESSAGE_HDR_FUNCTION_EVENT_ACK: > + default: > + if (s->state != LSILOGICSTATE_FAULT) { > + s->IOC_fault_code = LSILOGIC_IOCSTATUS_INVALID_FUNCTION; > + s->state = LSILOGICSTATE_FAULT; > + } > + } > + > + if (cbRequest != 0) { > + /* Handle SCSI I/O requests seperately. */ > + if (request.Header.u8Function == > + MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST) { > + LsilogicCmd *cmd = g_malloc0(sizeof(LsilogicCmd)); > + cpu_physical_memory_read(host_msg_frame_pa, > + &cmd->request.Header, cbRequest); > + cmd->host_msg_frame_pa = host_msg_frame_pa; > + lsilogic_process_SCSIIO_Request(s, cmd); > + } else { > + MptReplyUnion Reply; > + cpu_physical_memory_read(host_msg_frame_pa, &request.Header, > + cbRequest); > + lsilogic_process_message(s, &request.Header, &Reply); > + } > + > + } > + s->request_queue_next_address_read++; > + s->request_queue_next_address_read %= s->request_queue_entries; > + } > + > + return true; > +} > + > + > +static int lsilogic_hard_reset(LsilogicState *s); > + > +static int lsilogic_config_unit_page(LsilogicState *pLsiLogic, > + PMptConfigurationPagesSupported pPages, > + uint8_t u8PageNumber, > + PMptConfigurationPageHeader *ppPageHeader, > + uint8_t **ppbPageData, size_t *pcbPage) > +{ > + int rc = 0; > + > + switch (u8PageNumber) { > + case 0: > + *ppPageHeader = &pPages->IOUnitPage0.u.fields.Header; > + *ppbPageData = pPages->IOUnitPage0.u.abPageData; > + *pcbPage = sizeof(pPages->IOUnitPage0); > + break; > + case 1: > + *ppPageHeader = &pPages->IOUnitPage1.u.fields.Header; > + *ppbPageData = pPages->IOUnitPage1.u.abPageData; > + *pcbPage = sizeof(pPages->IOUnitPage1); > + break; > + case 2: > + *ppPageHeader = &pPages->IOUnitPage2.u.fields.Header; > + *ppbPageData = pPages->IOUnitPage2.u.abPageData; > + *pcbPage = sizeof(pPages->IOUnitPage2); > + break; > + case 3: > + *ppPageHeader = &pPages->IOUnitPage3.u.fields.Header; > + *ppbPageData = pPages->IOUnitPage3.u.abPageData; > + *pcbPage = sizeof(pPages->IOUnitPage3); > + break; > + case 4: > + *ppPageHeader = &pPages->IOUnitPage4.u.fields.Header; > + *ppbPageData = pPages->IOUnitPage4.u.abPageData; > + *pcbPage = sizeof(pPages->IOUnitPage4); > + break; > + default: > + rc = -1; > + } > + > + return rc; > +} > + > +static int lsilogic_config_ioc_page(LsilogicState *pLsiLogic, > + PMptConfigurationPagesSupported pPages, > + uint8_t u8PageNumber, > + PMptConfigurationPageHeader *ppPageHeader, > + uint8_t **ppbPageData, size_t *pcbPage) > +{ > + int rc = 0; > + > + switch (u8PageNumber) { > + case 0: > + *ppPageHeader = &pPages->IOCPage0.u.fields.Header; > + *ppbPageData = pPages->IOCPage0.u.abPageData; > + *pcbPage = sizeof(pPages->IOCPage0); > + break; > + case 1: > + *ppPageHeader = &pPages->IOCPage1.u.fields.Header; > + *ppbPageData = pPages->IOCPage1.u.abPageData; > + *pcbPage = sizeof(pPages->IOCPage1); > + break; > + case 2: > + *ppPageHeader = &pPages->IOCPage2.u.fields.Header; > + *ppbPageData = pPages->IOCPage2.u.abPageData; > + *pcbPage = sizeof(pPages->IOCPage2); > + break; > + case 3: > + *ppPageHeader = &pPages->IOCPage3.u.fields.Header; > + *ppbPageData = pPages->IOCPage3.u.abPageData; > + *pcbPage = sizeof(pPages->IOCPage3); > + break; > + case 4: > + *ppPageHeader = &pPages->IOCPage4.u.fields.Header; > + *ppbPageData = pPages->IOCPage4.u.abPageData; > + *pcbPage = sizeof(pPages->IOCPage4); > + break; > + case 6: > + *ppPageHeader = &pPages->IOCPage6.u.fields.Header; > + *ppbPageData = pPages->IOCPage6.u.abPageData; > + *pcbPage = sizeof(pPages->IOCPage6); > + break; > + default: > + rc = -1; > + } > + > + return rc; > +} > + > +static int lsilogic_config_manufacturing_page(LsilogicState *pLsiLogic, > + PMptConfigurationPagesSupported pPages, > + uint8_t u8PageNumber, > + PMptConfigurationPageHeader *ppPageHeader, > + uint8_t **ppbPageData, size_t *pcbPage) > +{ > + int rc = 0; > + > + switch (u8PageNumber) { > + case 0: > + *ppPageHeader = &pPages->ManufacturingPage0.u.fields.Header; > + *ppbPageData = pPages->ManufacturingPage0.u.abPageData; > + *pcbPage = sizeof(pPages->ManufacturingPage0); > + break; > + case 1: > + *ppPageHeader = &pPages->ManufacturingPage1.u.fields.Header; > + *ppbPageData = pPages->ManufacturingPage1.u.abPageData; > + *pcbPage = sizeof(pPages->ManufacturingPage1); > + break; > + case 2: > + *ppPageHeader = &pPages->ManufacturingPage2.u.fields.Header; > + *ppbPageData = pPages->ManufacturingPage2.u.abPageData; > + *pcbPage = sizeof(pPages->ManufacturingPage2); > + break; > + case 3: > + *ppPageHeader = &pPages->ManufacturingPage3.u.fields.Header; > + *ppbPageData = pPages->ManufacturingPage3.u.abPageData; > + *pcbPage = sizeof(pPages->ManufacturingPage3); > + break; > + case 4: > + *ppPageHeader = &pPages->ManufacturingPage4.u.fields.Header; > + *ppbPageData = pPages->ManufacturingPage4.u.abPageData; > + *pcbPage = sizeof(pPages->ManufacturingPage4); > + break; > + case 5: > + *ppPageHeader = &pPages->ManufacturingPage5.u.fields.Header; > + *ppbPageData = pPages->ManufacturingPage5.u.abPageData; > + *pcbPage = sizeof(pPages->ManufacturingPage5); > + break; > + case 6: > + *ppPageHeader = &pPages->ManufacturingPage6.u.fields.Header; > + *ppbPageData = pPages->ManufacturingPage6.u.abPageData; > + *pcbPage = sizeof(pPages->ManufacturingPage6); > + break; > + case 7: > + if (pLsiLogic->ctrl_type == LSILOGICCTRLTYPE_SCSI_SAS) { > + *ppPageHeader = &pPages->u.SasPages.pManufacturingPage7-> > + u.fields.Header; > + *ppbPageData = pPages->u.SasPages.pManufacturingPage7-> > + u.abPageData; > + *pcbPage = pPages->u.SasPages.cbManufacturingPage7; > + } else { > + rc = -1; > + } > + break; > + case 8: > + *ppPageHeader = &pPages->ManufacturingPage8.u.fields.Header; > + *ppbPageData = pPages->ManufacturingPage8.u.abPageData; > + *pcbPage = sizeof(pPages->ManufacturingPage8); > + break; > + case 9: > + *ppPageHeader = &pPages->ManufacturingPage9.u.fields.Header; > + *ppbPageData = pPages->ManufacturingPage9.u.abPageData; > + *pcbPage = sizeof(pPages->ManufacturingPage9); > + break; > + case 10: > + *ppPageHeader = &pPages->ManufacturingPage10.u.fields.Header; > + *ppbPageData = pPages->ManufacturingPage10.u.abPageData; > + *pcbPage = sizeof(pPages->ManufacturingPage10); > + break; > + default: > + rc = -1; > + } > + > + return rc; > +} > + > +static int lsilogic_config_bios_page(LsilogicState *pLsiLogic, > + PMptConfigurationPagesSupported pPages, > + uint8_t u8PageNumber, > + PMptConfigurationPageHeader *ppPageHeader, > + uint8_t **ppbPageData, size_t *pcbPage) > +{ > + int rc = 0; > + > + switch (u8PageNumber) { > + case 1: > + *ppPageHeader = &pPages->BIOSPage1.u.fields.Header; > + *ppbPageData = pPages->BIOSPage1.u.abPageData; > + *pcbPage = sizeof(pPages->BIOSPage1); > + break; > + case 2: > + *ppPageHeader = &pPages->BIOSPage2.u.fields.Header; > + *ppbPageData = pPages->BIOSPage2.u.abPageData; > + *pcbPage = sizeof(pPages->BIOSPage2); > + break; > + case 4: > + *ppPageHeader = &pPages->BIOSPage4.u.fields.Header; > + *ppbPageData = pPages->BIOSPage4.u.abPageData; > + *pcbPage = sizeof(pPages->BIOSPage4); > + break; > + default: > + rc = -1; > + } > + > + return rc; > +} > + > +static int lsilogic_config_scsi_spi_port_page(LsilogicState *pLsiLogic, > + PMptConfigurationPagesSupported pPages, > + uint8_t u8Port, > + uint8_t u8PageNumber, > + PMptConfigurationPageHeader *ppPageHeader, > + uint8_t **ppbPageData, size_t *pcbPage) > +{ > + int rc = 0; > + > + if (u8Port >= RT_ELEMENTS(pPages->u.SpiPages.aPortPages)) { > + return -1; > + } > + > + switch (u8PageNumber) { > + case 0: > + *ppPageHeader = &pPages->u.SpiPages.aPortPages[u8Port]. > + SCSISPIPortPage0.u.fields.Header; > + *ppbPageData = pPages->u.SpiPages.aPortPages[u8Port]. > + SCSISPIPortPage0.u.abPageData; > + *pcbPage = sizeof(pPages->u.SpiPages.aPortPages[u8Port]. > + SCSISPIPortPage0); > + break; > + case 1: > + *ppPageHeader = &pPages->u.SpiPages.aPortPages[u8Port]. > + SCSISPIPortPage1.u.fields.Header; > + *ppbPageData = pPages->u.SpiPages.aPortPages[u8Port]. > + SCSISPIPortPage1.u.abPageData; > + *pcbPage = sizeof(pPages->u.SpiPages.aPortPages[u8Port]. > + SCSISPIPortPage1); > + break; > + case 2: > + *ppPageHeader = &pPages->u.SpiPages.aPortPages[u8Port]. > + SCSISPIPortPage2.u.fields.Header; > + *ppbPageData = pPages->u.SpiPages.aPortPages[u8Port]. > + SCSISPIPortPage2.u.abPageData; > + *pcbPage = sizeof(pPages->u.SpiPages.aPortPages[u8Port] > + .SCSISPIPortPage2); > + break; > + default: > + rc = -1; > + } > + > + return rc; > +} > + > +static int lsilogic_config_scsi_spi_device_page(LsilogicState *pLsiLogic, > + PMptConfigurationPagesSupported pPages, > + uint8_t u8Bus, > + uint8_t u8TargetID, uint8_t u8PageNumber, > + PMptConfigurationPageHeader *ppPageHeader, > + uint8_t **ppbPageData, size_t *pcbPage) > +{ > + int rc = 0; > + > + if (u8Bus >= RT_ELEMENTS(pPages->u.SpiPages.aBuses)) { > + return -1; > + } > + > + if (u8TargetID >= > + RT_ELEMENTS(pPages->u.SpiPages.aBuses[u8Bus].aDevicePages)) { > + return -1; > + } > + > + switch (u8PageNumber) { > + case 0: > + *ppPageHeader = &pPages->u.SpiPages.aBuses[u8Bus]. > + aDevicePages[u8TargetID].SCSISPIDevicePage0.u.fields.Header; > + *ppbPageData = pPages->u.SpiPages.aBuses[u8Bus]. > + aDevicePages[u8TargetID].SCSISPIDevicePage0.u.abPageData; > + *pcbPage = sizeof(pPages->u.SpiPages.aBuses[u8Bus]. > + aDevicePages[u8TargetID].SCSISPIDevicePage0); > + break; > + case 1: > + *ppPageHeader = &pPages->u.SpiPages.aBuses[u8Bus]. > + aDevicePages[u8TargetID].SCSISPIDevicePage1.u.fields.Header; > + *ppbPageData = pPages->u.SpiPages.aBuses[u8Bus]. > + aDevicePages[u8TargetID].SCSISPIDevicePage1.u.abPageData; > + *pcbPage = sizeof(pPages->u.SpiPages.aBuses[u8Bus]. > + aDevicePages[u8TargetID].SCSISPIDevicePage1); > + break; > + case 2: > + *ppPageHeader = &pPages->u.SpiPages.aBuses[u8Bus]. > + aDevicePages[u8TargetID].SCSISPIDevicePage2.u.fields.Header; > + *ppbPageData = pPages->u.SpiPages.aBuses[u8Bus]. > + aDevicePages[u8TargetID].SCSISPIDevicePage2.u.abPageData; > + *pcbPage = sizeof(pPages->u.SpiPages.aBuses[u8Bus]. > + aDevicePages[u8TargetID].SCSISPIDevicePage2); > + break; > + case 3: > + *ppPageHeader = &pPages->u.SpiPages.aBuses[u8Bus]. > + aDevicePages[u8TargetID].SCSISPIDevicePage3.u.fields.Header; > + *ppbPageData = pPages->u.SpiPages.aBuses[u8Bus]. > + aDevicePages[u8TargetID].SCSISPIDevicePage3.u.abPageData; > + *pcbPage = sizeof(pPages->u.SpiPages.aBuses[u8Bus]. > + aDevicePages[u8TargetID].SCSISPIDevicePage3); > + break; > + default: > + rc = -1; > + } > + > + return rc; > +} > + > +static int lsilogic_config_sas_unit(LsilogicState *pLsiLogic, > + PMptConfigurationPagesSupported pPages, > + uint8_t u8PageNumber, > + PMptExtendedConfigurationPageHeader *ppPageHeader, > + uint8_t **ppbPageData, size_t *pcbPage) > +{ > + int rc = 0; > + > + switch (u8PageNumber) { > + case 0: > + *ppPageHeader = &pPages->u.SasPages.pSASIOUnitPage0->u.fields. > + ExtHeader; > + *ppbPageData = pPages->u.SasPages.pSASIOUnitPage0->u.abPageData; > + *pcbPage = pPages->u.SasPages.cbSASIOUnitPage0; > + break; > + case 1: > + *ppPageHeader = &pPages->u.SasPages.pSASIOUnitPage1->u.fields. > + ExtHeader; > + *ppbPageData = pPages->u.SasPages.pSASIOUnitPage1->u.abPageData; > + *pcbPage = pPages->u.SasPages.cbSASIOUnitPage1; > + break; > + case 2: > + *ppPageHeader = &pPages->u.SasPages.SASIOUnitPage2.u.fields.ExtHeader; > + *ppbPageData = pPages->u.SasPages.SASIOUnitPage2.u.abPageData; > + *pcbPage = sizeof(pPages->u.SasPages.SASIOUnitPage2); > + break; > + case 3: > + *ppPageHeader = &pPages->u.SasPages.SASIOUnitPage3.u.fields.ExtHeader; > + *ppbPageData = pPages->u.SasPages.SASIOUnitPage3.u.abPageData; > + *pcbPage = sizeof(pPages->u.SasPages.SASIOUnitPage3); > + break; > + default: > + rc = -1; > + } > + > + return rc; > +} > + > +static int lsilogic_config_sas_phy(LsilogicState *pLsiLogic, > + PMptConfigurationPagesSupported pPages, > + uint8_t u8PageNumber, > + MptConfigurationPageAddress PageAddress, > + PMptExtendedConfigurationPageHeader *ppPageHeader, > + uint8_t **ppbPageData, size_t *pcbPage) > +{ > + int rc = 0; > + uint8_t uAddressForm = > + MPT_CONFIGURATION_PAGE_ADDRESS_GET_SAS_FORM(PageAddress); > + PMptConfigurationPagesSas pPagesSas = &pPages->u.SasPages; > + PMptPHY pPHYPages = NULL; > + > + > + if (uAddressForm == 0) { /* PHY number */ > + uint8_t u8PhyNumber = PageAddress.SASPHY.Form0.u8PhyNumber; > + > + if (u8PhyNumber >= pPagesSas->cPHYs) { > + return -1; > + } > + > + pPHYPages = &pPagesSas->paPHYs[u8PhyNumber]; > + } else if (uAddressForm == 1) { /* Index form */ > + uint16_t u16Index = PageAddress.SASPHY.Form1.u16Index; > + > + if (u16Index >= pPagesSas->cPHYs) { > + return -1; > + } > + > + pPHYPages = &pPagesSas->paPHYs[u16Index]; > + } else { > + rc = -1; /* Correct? */ > + } > + > + if (pPHYPages) { > + switch (u8PageNumber) { > + case 0: > + *ppPageHeader = &pPHYPages->SASPHYPage0.u.fields.ExtHeader; > + *ppbPageData = pPHYPages->SASPHYPage0.u.abPageData; > + *pcbPage = sizeof(pPHYPages->SASPHYPage0); > + break; > + case 1: > + *ppPageHeader = &pPHYPages->SASPHYPage1.u.fields.ExtHeader; > + *ppbPageData = pPHYPages->SASPHYPage1.u.abPageData; > + *pcbPage = sizeof(pPHYPages->SASPHYPage1); > + break; > + default: > + rc = -1; > + } > + } else { > + rc = -1; > + } > + > + return rc; > +} > + > +static int lsilogic_config_sas_device(LsilogicState *pLsiLogic, > + PMptConfigurationPagesSupported pPages, > + uint8_t u8PageNumber, > + MptConfigurationPageAddress PageAddress, > + PMptExtendedConfigurationPageHeader *ppPageHeader, > + uint8_t **ppbPageData, size_t *pcbPage) > +{ > + int rc = 0; > + uint8_t uAddressForm = > + MPT_CONFIGURATION_PAGE_ADDRESS_GET_SAS_FORM(PageAddress); > + PMptConfigurationPagesSas pPagesSas = &pPages->u.SasPages; > + PMptSASDevice pSASDevice = NULL; > + > + if (uAddressForm == 0) { > + uint16_t u16Handle = PageAddress.SASDevice.Form0And2.u16Handle; > + > + pSASDevice = pPagesSas->pSASDeviceHead; > + > + /* Get the first device? */ > + if (u16Handle != 0xffff) { > + /* No, search for the right one. */ > + > + while (pSASDevice > + && pSASDevice->SASDevicePage0.u.fields.u16DevHandle != > + u16Handle) > + pSASDevice = pSASDevice->pNext; > + > + if (pSASDevice) { > + pSASDevice = pSASDevice->pNext; > + } > + } > + } else if (uAddressForm == 1) { > + uint8_t u8TargetID = PageAddress.SASDevice.Form1.u8TargetID; > + uint8_t u8Bus = PageAddress.SASDevice.Form1.u8Bus; > + > + pSASDevice = pPagesSas->pSASDeviceHead; > + > + while (pSASDevice > + && (pSASDevice->SASDevicePage0.u.fields.u8TargetID != > + u8TargetID > + || pSASDevice->SASDevicePage0.u.fields.u8Bus != u8Bus)) > + pSASDevice = pSASDevice->pNext; > + } else if (uAddressForm == 2) { > + uint16_t u16Handle = PageAddress.SASDevice.Form0And2.u16Handle; > + > + pSASDevice = pPagesSas->pSASDeviceHead; > + > + while (pSASDevice > + && pSASDevice->SASDevicePage0.u.fields.u16DevHandle != > + u16Handle) { > + pSASDevice = pSASDevice->pNext; > + } > + } > + > + if (pSASDevice) { > + switch (u8PageNumber) { > + case 0: > + *ppPageHeader = &pSASDevice->SASDevicePage0.u.fields.ExtHeader; > + *ppbPageData = pSASDevice->SASDevicePage0.u.abPageData; > + *pcbPage = sizeof(pSASDevice->SASDevicePage0); > + break; > + case 1: > + *ppPageHeader = &pSASDevice->SASDevicePage1.u.fields.ExtHeader; > + *ppbPageData = pSASDevice->SASDevicePage1.u.abPageData; > + *pcbPage = sizeof(pSASDevice->SASDevicePage1); > + break; > + case 2: > + *ppPageHeader = &pSASDevice->SASDevicePage2.u.fields.ExtHeader; > + *ppbPageData = pSASDevice->SASDevicePage2.u.abPageData; > + *pcbPage = sizeof(pSASDevice->SASDevicePage2); > + break; > + default: > + rc = -1; > + } > + } else { > + rc = -1; > + } > + > + return rc; > +} > + > +static int lsilogic_config_page_get_extended(LsilogicState *pLsiLogic, > + PMptConfigurationRequest pConfigurationReq, > + PMptExtendedConfigurationPageHeader *ppPageHeader, > + uint8_t **ppbPageData, size_t *pcbPage) > +{ > + int rc = 0; > + > + switch (pConfigurationReq->u8ExtPageType) { > + case MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASIOUNIT: > + { > + rc = lsilogic_config_sas_unit(pLsiLogic, > + pLsiLogic->config_pages, > + pConfigurationReq->u8PageNumber, > + ppPageHeader, ppbPageData, pcbPage); > + break; > + } > + case MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASPHYS: > + { > + rc = lsilogic_config_sas_phy(pLsiLogic, > + pLsiLogic->config_pages, > + pConfigurationReq->u8PageNumber, > + pConfigurationReq->PageAddress, > + ppPageHeader, ppbPageData, pcbPage); > + break; > + } > + case MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASDEVICE: > + { > + rc = lsilogic_config_sas_device(pLsiLogic, > + pLsiLogic->config_pages, > + pConfigurationReq->u8PageNumber, > + pConfigurationReq->PageAddress, > + ppPageHeader, ppbPageData, pcbPage); > + break; > + } > + case MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASEXPANDER: > + /* No expanders supported */ > + case MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_ENCLOSURE: > + /* No enclosures supported */ > + default: > + rc = -1; > + } > + > + return rc; > +} > + > + > +static int lsilogic_process_config_req(LsilogicState *s, > + MptConfigurationRequest *config_req, MptConfigurationReply *reply) > +{ > + int rc = 0; > + uint8_t *pbPageData = NULL; > + PMptConfigurationPageHeader pPageHeader = NULL; > + PMptExtendedConfigurationPageHeader pExtPageHeader = NULL; > + size_t cbPage = 0; > + > + > + /* Copy common bits from the request into the reply. */ > + reply->u8MessageLength = 6; /* 6 32bit D-Words. */ > + reply->u8Action = config_req->u8Action; > + reply->u8Function = config_req->u8Function; > + reply->u32MessageContext = config_req->u32MessageContext; > + > + switch (MPT_CONFIGURATION_PAGE_TYPE_GET(config_req->u8PageType)) { > + case MPT_CONFIGURATION_PAGE_TYPE_IO_UNIT: > + { > + rc = lsilogic_config_unit_page(s, s->config_pages, > + config_req->u8PageNumber, > + &pPageHeader, &pbPageData, &cbPage); > + break; > + } > + case MPT_CONFIGURATION_PAGE_TYPE_IOC: > + { > + /* Get the page data. */ > + rc = lsilogic_config_ioc_page(s, s->config_pages, > + config_req->u8PageNumber, > + &pPageHeader, &pbPageData, &cbPage); > + break; > + } > + case MPT_CONFIGURATION_PAGE_TYPE_MANUFACTURING: > + { > + rc = lsilogic_config_manufacturing_page(s, s->config_pages, > + config_req->u8PageNumber, > + &pPageHeader, &pbPageData, &cbPage); > + break; > + } > + case MPT_CONFIGURATION_PAGE_TYPE_SCSI_SPI_PORT: > + { > + rc = lsilogic_config_scsi_spi_port_page(s, s->config_pages, > + config_req->PageAddress.MPIPortNumber.u8PortNumber, > + config_req->u8PageNumber, > + &pPageHeader, &pbPageData, &cbPage); > + break; > + } > + case MPT_CONFIGURATION_PAGE_TYPE_SCSI_SPI_DEVICE: > + { > + rc = lsilogic_config_scsi_spi_device_page(s, s->config_pages, > + config_req->PageAddress.BusAndTargetId.u8Bus, > + config_req->PageAddress.BusAndTargetId.u8TargetID, > + config_req->u8PageNumber, > + &pPageHeader, &pbPageData, &cbPage); > + break; > + } > + case MPT_CONFIGURATION_PAGE_TYPE_BIOS: > + { > + rc = lsilogic_config_bios_page(s, s->config_pages, > + config_req->u8PageNumber, > + &pPageHeader, &pbPageData, &cbPage); > + break; > + } > + case MPT_CONFIGURATION_PAGE_TYPE_EXTENDED: > + { > + rc = lsilogic_config_page_get_extended(s, config_req, > + &pExtPageHeader, &pbPageData, &cbPage); > + break; > + } > + default: > + rc = -1; > + } > + > + if (rc == -1) { > + reply->u8PageType = config_req->u8PageType; > + reply->u8PageNumber = config_req->u8PageNumber; > + reply->u8PageLength = config_req->u8PageLength; > + reply->u8PageVersion = config_req->u8PageVersion; > + reply->u16IOCStatus = MPT_IOCSTATUS_CONFIG_INVALID_PAGE; > + return 0; > + } > + > + if (MPT_CONFIGURATION_PAGE_TYPE_GET(config_req->u8PageType) == > + MPT_CONFIGURATION_PAGE_TYPE_EXTENDED) { > + reply->u8PageType = pExtPageHeader->u8PageType; > + reply->u8PageNumber = pExtPageHeader->u8PageNumber; > + reply->u8PageVersion = pExtPageHeader->u8PageVersion; > + reply->u8ExtPageType = pExtPageHeader->u8ExtPageType; > + reply->u16ExtPageLength = pExtPageHeader->u16ExtPageLength; > + } else { > + reply->u8PageType = pPageHeader->u8PageType; > + reply->u8PageNumber = pPageHeader->u8PageNumber; > + reply->u8PageLength = pPageHeader->u8PageLength; > + reply->u8PageVersion = pPageHeader->u8PageVersion; > + } > + > + /* > + * Don't use the scatter gather handling code as the configuration > + * request always have only one simple element. > + */ > + switch (config_req->u8Action) { > + case MPT_CONFIGURATION_REQUEST_ACTION_DEFAULT: > + /* Nothing to do. We are always using the defaults. */ > + case MPT_CONFIGURATION_REQUEST_ACTION_HEADER: > + { > + /* Already copied above nothing to do. */ > + break; > + } > + case MPT_CONFIGURATION_REQUEST_ACTION_READ_NVRAM: > + case MPT_CONFIGURATION_REQUEST_ACTION_READ_CURRENT: > + case MPT_CONFIGURATION_REQUEST_ACTION_READ_DEFAULT: > + { > + uint32_t cbBuffer = config_req->SimpleSGElement.u24Length; > + if (cbBuffer != 0) { > + uint64_t page_buffer_pa = config_req->SimpleSGElement. > + u32DataBufferAddressLow; > + if (config_req->SimpleSGElement.f64BitAddress) { > + page_buffer_pa |= (uint64_t)config_req->SimpleSGElement. > + u32DataBufferAddressHigh << 32; > + } > + > + cpu_physical_memory_write(page_buffer_pa, pbPageData, MIN(cbBuffer, > + cbPage)); > + } > + break; > + } > + case MPT_CONFIGURATION_REQUEST_ACTION_WRITE_CURRENT: > + case MPT_CONFIGURATION_REQUEST_ACTION_WRITE_NVRAM: > + { > + uint32_t cbBuffer = config_req->SimpleSGElement.u24Length; > + if (cbBuffer != 0) { > + uint64_t page_buffer_pa = config_req->SimpleSGElement. > + u32DataBufferAddressLow; > + if (config_req->SimpleSGElement.f64BitAddress) { > + page_buffer_pa |= (uint64_t)config_req->SimpleSGElement. > + u32DataBufferAddressHigh << 32; > + } > + cpu_physical_memory_read(page_buffer_pa, pbPageData, MIN(cbBuffer, > + cbPage)); > + } > + break; > + } > + default: > + break; > + } > + > + return 0; > +} > + > +static const char *lsilogic_msg_desc[] = { > + "SCSI_IO_REQUEST", > + "SCSI_TASK_MGMT", > + "IOC_INIT", > + "IOC_FACTS", > + "CONFIG", > + "PORT_FACTS", > + "PORT_ENABLE", > + "EVENT_NOTIFICATION", > + "EVENT_ACK", > + "FW_DOWNLOAD", > + "TARGET_CMD_BUFFER_POST", > + "TARGET_ASSIST", > + "TARGET_STATUS_SEND", > + "TARGET_MODE_ABORT", > + "UNDEFINED", > + "UNDEFINED", > + "UNDEFINED", > + "UNDEFINED", > + "FW_UPLOAD" > +}; > + > +static void lsilogic_process_message(LsilogicState *s, MptMessageHdr *msg, > + MptReplyUnion *reply) > +{ > + bool fForceReplyPostFifo = false; > + > + memset(reply, 0, sizeof(MptReplyUnion)); > + > + trace_lsilogic_process_message(lsilogic_msg_desc[msg->u8Function]); > + switch (msg->u8Function) { > + case MPT_MESSAGE_HDR_FUNCTION_SCSI_TASK_MGMT: > + { > + PMptSCSITaskManagementRequest pTaskMgmtReq = > + (PMptSCSITaskManagementRequest)msg; > + > + reply->SCSITaskManagement.u8MessageLength = 6; > + reply->SCSITaskManagement.u8TaskType = > + pTaskMgmtReq->u8TaskType; > + reply->SCSITaskManagement.u32TerminationCount = 0; > + fForceReplyPostFifo = true; > + break; > + } > + > + case MPT_MESSAGE_HDR_FUNCTION_IOC_INIT: > + { > + /* This request sets the I/O contr to the operational state. */ > + PMptIOCInitRequest pIOCInitReq = (PMptIOCInitRequest)msg; > + > + /* Update configuration values. */ > + s->who_init = (LSILOGICWHOINIT)pIOCInitReq->u8WhoInit; > + s->reply_frame_size = pIOCInitReq->u16ReplyFrameSize; > + s->max_buses = pIOCInitReq->u8MaxBuses; > + s->max_devices = pIOCInitReq->u8MaxDevices; > + s->host_mfa_high_addr = pIOCInitReq->u32HostMfaHighAddr; > + s->sense_buffer_high_addr = pIOCInitReq->u32SenseBufferHighAddr; > + > + if (s->state == LSILOGICSTATE_READY) { > + s->state = LSILOGICSTATE_OPERATIONAL; > + } > + > + /* Return reply. */ > + reply->IOCInit.u8MessageLength = 5; > + reply->IOCInit.u8WhoInit = s->who_init; > + reply->IOCInit.u8MaxDevices = s->max_devices; > + reply->IOCInit.u8MaxBuses = s->max_buses; > + break; > + } > + case MPT_MESSAGE_HDR_FUNCTION_IOC_FACTS: > + { > + reply->IOCFacts.u8MessageLength = 15; /* 15 32bit dwords. */ > + > + if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SPI) { > + /* Version from the specification. */ > + reply->IOCFacts.u16MessageVersion = 0x0102; > + } else if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SAS) { > + /* Version from the specification. */ > + reply->IOCFacts.u16MessageVersion = 0x0105; > + } > + > + reply->IOCFacts.u8NumberOfPorts = s->ports; > + /* PCI function number. */ > + reply->IOCFacts.u8IOCNumber = 0; > + reply->IOCFacts.u16IOCExceptions = 0; > + reply->IOCFacts.u8MaxChainDepth = LSILOGICSCSI_MAXIMUM_CHAIN_DEPTH; > + reply->IOCFacts.u8WhoInit = s->who_init; > + /* Block size in 32bit dwords. This is the largest request > + we can get (SCSI I/O). */ > + reply->IOCFacts.u8BlockSize = 12; > + /* Bit 0 is set if the guest must upload the FW prior to using > + the controller. Obviously not needed here. */ > + reply->IOCFacts.u8Flags = 0; > + /* One entry is always free. */ > + reply->IOCFacts.u16ReplyQueueDepth = s->reply_queue_entries - 1; > + reply->IOCFacts.u16RequestFrameSize = 128; > + /* Our own product ID :) */ > + reply->IOCFacts.u16ProductID = 0x2704; > + reply->IOCFacts.u32CurrentHostMFAHighAddr = s->host_mfa_high_addr; > + /* One entry is always free. */ > + reply->IOCFacts.u16GlobalCredits = s->request_queue_entries - 1; > + > + /* Event notifications not enabled. */ > + reply->IOCFacts.u8EventState = 0; > + reply->IOCFacts.u32CurrentSenseBufferHighAddr = > + s->sense_buffer_high_addr; > + reply->IOCFacts.u16CurReplyFrameSize = s->reply_frame_size; > + reply->IOCFacts.u8MaxDevices = s->max_devices; > + reply->IOCFacts.u8MaxBuses = s->max_buses; > + reply->IOCFacts.u32FwImageSize = 0; > + reply->IOCFacts.u32FWVersion = 0x1329200; > + break; > + } > + case MPT_MESSAGE_HDR_FUNCTION_PORT_FACTS: > + { > + PMptPortFactsRequest pPortFactsReq = (PMptPortFactsRequest)msg; > + > + reply->PortFacts.u8MessageLength = 10; > + reply->PortFacts.u8PortNumber = pPortFactsReq->u8PortNumber; > + > + if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SPI) { > + /* This controller only supports one bus with bus number 0. */ > + if (pPortFactsReq->u8PortNumber >= s->ports) { > + reply->PortFacts.u8PortType = 0; /* Not existant. */ > + } else { > + reply->PortFacts.u8PortType = 0x01; /* SCSI Port. */ > + reply->PortFacts.u16MaxDevices = > + LSILOGICSCSI_PCI_SPI_DEVICES_PER_BUS_MAX; > + /* SCSI initiator and LUN supported. */ > + reply->PortFacts.u16ProtocolFlags = (1 << 3) | (1 << 0); > + reply->PortFacts.u16PortSCSIID = 7; /* Default */ > + reply->PortFacts.u16MaxPersistentIDs = 0; > + /* Only applies for target mode which we dont support. */ > + reply->PortFacts.u16MaxPostedCmdBuffers = 0; > + /* Only for the LAN controller. */ > + reply->PortFacts.u16MaxLANBuckets = 0; > + } > + } else if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SAS) { > + if (pPortFactsReq->u8PortNumber >= s->ports) { > + reply->PortFacts.u8PortType = 0; /* Not existant. */ > + } else { > + reply->PortFacts.u8PortType = 0x30; /* SAS Port. */ > + reply->PortFacts.u16MaxDevices = s->ports; > + /* SCSI initiator and LUN supported. */ > + reply->PortFacts.u16ProtocolFlags = (1 << 3) | (1 << 0); > + reply->PortFacts.u16PortSCSIID = s->ports; > + reply->PortFacts.u16MaxPersistentIDs = 0; > + /* Only applies for target mode which we dont support. */ > + reply->PortFacts.u16MaxPostedCmdBuffers = 0; > + /* Only for the LAN controller. */ > + reply->PortFacts.u16MaxLANBuckets = 0; > + } > + } > + break; > + } > + case MPT_MESSAGE_HDR_FUNCTION_PORT_ENABLE: > + { > + /* > + * The port enable request notifies the IOC to make the port > + * available and perform appropriate discovery on the associated > + * link. > + */ > + PMptPortEnableRequest pPortEnableReq = (PMptPortEnableRequest)msg; > + > + reply->PortEnable.u8MessageLength = 5; > + reply->PortEnable.u8PortNumber = pPortEnableReq->u8PortNumber; > + break; > + } > + case MPT_MESSAGE_HDR_FUNCTION_EVENT_NOTIFICATION: > + { > + PMptEventNotificationRequest pEventNotificationReq = > + (PMptEventNotificationRequest)msg; > + > + if (pEventNotificationReq->u8Switch) { > + s->event_notification_enabled = true; > + } else { > + s->event_notification_enabled = false; > + } > + > + reply->EventNotification.u16EventDataLength = 1; /* 32bit Word. */ > + reply->EventNotification.u8MessageLength = 8; > + reply->EventNotification.u8MessageFlags = (1 << 7); > + reply->EventNotification.u8AckRequired = 0; > + reply->EventNotification.u32Event = MPT_EVENT_EVENT_CHANGE; > + reply->EventNotification.u32EventContext = 0; > + reply->EventNotification.u32EventData = > + s->event_notification_enabled ? 1 : 0; > + > + break; > + } > + case MPT_MESSAGE_HDR_FUNCTION_EVENT_ACK: > + { > + break; > + } > + case MPT_MESSAGE_HDR_FUNCTION_CONFIG: > + { > + PMptConfigurationRequest config_req = > + (PMptConfigurationRequest)msg; > + > + lsilogic_process_config_req(s, config_req, &reply->Configuration); > + break; > + } > + case MPT_MESSAGE_HDR_FUNCTION_FW_UPLOAD: > + { > + PMptFWUploadRequest pFWUploadReq = (PMptFWUploadRequest)msg; > + target_phys_addr_t iov_pa = pFWUploadReq->sge.u32DataBufferAddressLow; > + void *ptr; > + > + reply->FWUpload.u8ImageType = pFWUploadReq->u8ImageType; > + reply->FWUpload.u8MessageLength = 6; > + assert(pFWUploadReq->u8ImageType == MPI_FW_UPLOAD_ITYPE_BIOS_FLASH); > + assert(pFWUploadReq->sge.u2ElementType == MPTSGENTRYTYPE_SIMPLE); > + assert(pFWUploadReq->sge.f64BitAddress == 0); > + assert(pFWUploadReq->sge.fEndOfList); > + assert(pFWUploadReq->sge.fLastElement); > + reply->FWUpload.u32ActualImageSize = memory_region_size(&s->dev.rom); > + assert(reply->FWUpload.u32ActualImageSize >= > + pFWUploadReq->TCSge.ImageOffset + pFWUploadReq->sge.u24Length); > + ptr = memory_region_get_ram_ptr(&s->dev.rom); > + cpu_physical_memory_write(iov_pa, (uint8_t *)ptr + > + pFWUploadReq->TCSge.ImageOffset, pFWUploadReq->sge.u24Length); > + qemu_put_ram_ptr(ptr); > + reply->FWUpload.u32ActualImageSize = memory_region_size(&s->dev.rom); > + break; > + } > + case MPT_MESSAGE_HDR_FUNCTION_FW_DOWNLOAD: > + { > + > + reply->FWDownload.u8MessageLength = 5; > + break; > + } > + case MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST: > + /* Should be handled already. */ > + default: > + trace_lsilogic_unhandled_cmd(msg->u8Function, 0); > + } > + > + /* Copy common bits from request message frame to reply. */ > + reply->Header.u8Function = msg->u8Function; > + reply->Header.u32MessageContext = msg->u32MessageContext; > + > + lsilogic_finish_address_reply(s, reply, fForceReplyPostFifo); > +} > + > +static uint64_t lsilogic_mmio_read(void *opaque, target_phys_addr_t addr, > + unsigned size) > +{ > + LsilogicState *s = opaque; > + uint32_t retval = 0; > + > + switch (addr & ~3) { > + case LSILOGIC_REG_DOORBELL: > + retval = LSILOGIC_REG_DOORBELL_SET_STATE(s->state) | > + LSILOGIC_REG_DOORBELL_SET_USED(s->doorbell) | > + LSILOGIC_REG_DOORBELL_SET_WHOINIT(s->who_init); > + /* > + * If there is a doorbell function in progress we pass the > + * return value instead of the status code. We transfer 16bits > + * of the reply during one read. > + */ > + if (s->doorbell) { > + retval |= s->reply_buffer.au16Reply[s->next_reply_entry_read++]; > + } else { > + retval |= s->IOC_fault_code; > + } > + break; > + > + case LSILOGIC_REG_REPLY_QUEUE: > + if (s->reply_post_queue_next_entry_free_write != > + s->reply_post_queue_next_address_read) { > + retval = s->reply_post_queue[ > + s->reply_post_queue_next_address_read++]; > + s->reply_post_queue_next_address_read %= > + s->reply_queue_entries; > + } else { > + /* The reply post queue is empty. Reset interrupt. */ > + retval = 0xffffffff; > + s->intr_status &= ~LSILOGIC_REG_HOST_INTR_STATUS_REPLY_INTR; > + lsilogic_update_interrupt(s); > + } > + break; > + > + case LSILOGIC_REG_HOST_INTR_STATUS: > + retval = s->intr_status; > + break; > + > + case LSILOGIC_REG_HOST_INTR_MASK: > + retval = s->intr_mask; > + break; > + > + case LSILOGIC_REG_HOST_DIAGNOSTIC: > + if (s->diagnostic_enabled) { > + retval = LSILOGIC_REG_HOST_DIAGNOSTIC_DRWE; > + } else { > + retval = 0; > + } > + break; > + > + case LSILOGIC_REG_TEST_BASE_ADDRESS: > + case LSILOGIC_REG_DIAG_RW_DATA: > + case LSILOGIC_REG_DIAG_RW_ADDRESS: > + default: > + trace_lsilogic_mmio_invalid_readl(addr); > + break; > + } > + trace_lsilogic_mmio_readl(addr, retval); > + return retval; > +} > + > +static void lsilogic_mmio_write(void *opaque, target_phys_addr_t addr, > + uint64_t val, unsigned size) > +{ > + static const uint8_t DiagnosticAccess[] = {0x04, 0x0b, 0x02, 0x07, 0x0d}; > + > + LsilogicState *s = opaque; > + > + trace_lsilogic_mmio_writel(addr, val); > + switch (addr) { > + case LSILOGIC_REG_REPLY_QUEUE: > + s->reply_free_queue[s->reply_free_queue_next_entry_free_write++] = val; > + s->reply_free_queue_next_entry_free_write %= s->reply_queue_entries; > + break; > + > + case LSILOGIC_REG_REQUEST_QUEUE: > + s->request_queue[s->request_queue_next_entry_free_write++] = val; > + s->request_queue_next_entry_free_write %= s->request_queue_entries; > + lsilogic_queue_consumer(s); > + break; > + > + case LSILOGIC_REG_DOORBELL: > + if (!s->doorbell) { > + uint32_t uFunction = LSILOGIC_REG_DOORBELL_GET_FUNCTION(val); > + > + switch (uFunction) { > + case LSILOGIC_DOORBELL_FUNCTION_IOC_MSG_UNIT_RESET: > + lsilogic_soft_reset(s); > + break; > + case LSILOGIC_DOORBELL_FUNCTION_IO_UNIT_RESET: > + break; > + case LSILOGIC_DOORBELL_FUNCTION_HANDSHAKE: > + { > + s->drbl_message_size = LSILOGIC_REG_DOORBELL_GET_SIZE(val); > + s->drbl_message_index = 0; > + s->doorbell = true; > + /* Update the interrupt status to notify the guest that > + a doorbell function was started. */ > + s->intr_status |= > + LSILOGIC_REG_HOST_INTR_STATUS_SYSTEM_DOORBELL; > + lsilogic_update_interrupt(s); > + } > + break; > + case LSILOGIC_DOORBELL_FUNCTION_REPLY_FRAME_REMOVAL: > + default: > + trace_lsilogic_mmio_invalid_writel(addr, val); > + break; > + } > + } else { > + /* > + * We are already performing a doorbell function. > + * Get the remaining parameters. > + */ > + s->drbl_message[s->drbl_message_index++] = val; > + if (s->drbl_message_index == s->drbl_message_size) { > + lsilogic_process_message(s, (MptMessageHdr *)s->drbl_message, > + &s->reply_buffer); > + } > + } > + break; > + > + case LSILOGIC_REG_HOST_INTR_STATUS: > + s->intr_status &= ~LSILOGIC_REG_HOST_INTR_STATUS_SYSTEM_DOORBELL; > + if (s->doorbell && s->drbl_message_size == s->drbl_message_index) { > + if (s->next_reply_entry_read == s->reply_size) { > + s->doorbell = false; > + } > + s->intr_status |= LSILOGIC_REG_HOST_INTR_STATUS_SYSTEM_DOORBELL; > + } > + lsilogic_update_interrupt(s); > + break; > + > + case LSILOGIC_REG_HOST_INTR_MASK: > + s->intr_mask = val & LSILOGIC_REG_HOST_INTR_MASK_W_MASK; > + lsilogic_update_interrupt(s); > + break; > + > + case LSILOGIC_REG_WRITE_SEQUENCE: > + /* Any value will cause a reset and disabling access. */ > + if (s->diagnostic_enabled) { > + s->diagnostic_enabled = false; > + s->diagnostic_access_idx = 0; > + } else if ((val & 0xf) == DiagnosticAccess[s->diagnostic_access_idx]) { > + s->diagnostic_access_idx++; > + if (s->diagnostic_access_idx == sizeof(DiagnosticAccess)) { > + /* > + * Key sequence successfully written. Enable access to > + * diagnostic memory and register. > + */ > + s->diagnostic_enabled = true; > + } > + } else { /* Wrong value written - reset to beginning. */ > + s->diagnostic_access_idx = 0; > + } > + break; > + > + break; > + > + case LSILOGIC_REG_HOST_DIAGNOSTIC: > + if (val & LSILOGIC_REG_HOST_DIAGNOSTIC_RESET_ADAPTER) { > + lsilogic_hard_reset(s); > + } > + break; > + default: > + trace_lsilogic_mmio_invalid_writel(addr, val); > + break; > + } > +} > + > +static const MemoryRegionOps lsilogic_mmio_ops = { > + .read = lsilogic_mmio_read, > + .write = lsilogic_mmio_write, > + .endianness = DEVICE_LITTLE_ENDIAN, > + .impl = { > + .min_access_size = 8, > + .max_access_size = 8, > + } > +}; > + > +static uint64_t lsilogic_port_read(void *opaque, target_phys_addr_t addr, > + unsigned size) > +{ > + return lsilogic_mmio_read(opaque, addr & 0xff, size); > +} > + > +static void lsilogic_port_write(void *opaque, target_phys_addr_t addr, > + uint64_t val, unsigned size) > +{ > + lsilogic_mmio_write(opaque, addr & 0xff, val, size); > +} > + > +static const MemoryRegionOps lsilogic_port_ops = { > + .read = lsilogic_port_read, > + .write = lsilogic_port_write, > + .endianness = DEVICE_LITTLE_ENDIAN, > + .impl = { > + .min_access_size = 4, > + .max_access_size = 4, > + } > +}; > + > +static uint64_t lsilogic_diag_read(void *opaque, target_phys_addr_t addr, > + unsigned size) > +{ > + trace_lsilogic_diag_readl(addr, 0); > + return 0; > +} > + > +static void lsilogic_diag_write(void *opaque, target_phys_addr_t addr, > + uint64_t val, unsigned size) > +{ > + trace_lsilogic_diag_writel(addr, val); > +} > + > +static const MemoryRegionOps lsilogic_diag_ops = { > + .read = lsilogic_diag_read, > + .write = lsilogic_diag_write, > + .endianness = DEVICE_LITTLE_ENDIAN, > + .impl = { > + .min_access_size = 8, > + .max_access_size = 8, > + } > +}; > + > +static void lsilogic_soft_reset(LsilogicState *s) > +{ > + int i; > + trace_lsilogic_reset(); > + s->state = LSILOGICSTATE_RESET; > + > + s->intr_status = 0; > + lsilogic_update_interrupt(s); > + > + /* Reset the queues. */ > + s->reply_free_queue_next_entry_free_write = 0; > + s->reply_free_queue_next_address_read = 0; > + s->reply_post_queue_next_entry_free_write = 0; > + s->reply_post_queue_next_address_read = 0; > + s->request_queue_next_entry_free_write = 0; > + s->request_queue_next_address_read = 0; > + for (i = 0; i < LSILOGIC_MAX_FRAMES; i++) { > + LsilogicCmd *cmd = s->frames[i]; > + if (cmd) { > + lsilogic_abort_command(cmd); > + cmd->flags = 0; > + } > + } > + s->next_frame = 0; > + s->state = LSILOGICSTATE_READY; > +} > + > +static void lsilogic_config_pages_free(LsilogicState *s) > +{ > + > + if (s->config_pages) { > + /* Destroy device list if we emulate a SAS controller. */ > + if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SAS) { > + PMptConfigurationPagesSas pSasPages = &s->config_pages->u.SasPages; > + PMptSASDevice pSASDeviceCurr = pSasPages->pSASDeviceHead; > + > + while (pSASDeviceCurr) { > + PMptSASDevice pFree = pSASDeviceCurr; > + > + pSASDeviceCurr = pSASDeviceCurr->pNext; > + g_free(pFree); > + } > + if (pSasPages->paPHYs) { > + g_free(pSasPages->paPHYs); > + } > + if (pSasPages->pManufacturingPage7) { > + g_free(pSasPages->pManufacturingPage7); > + } > + if (pSasPages->pSASIOUnitPage0) { > + g_free(pSasPages->pSASIOUnitPage0); > + } > + if (pSasPages->pSASIOUnitPage1) { > + g_free(pSasPages->pSASIOUnitPage1); > + } > + } > + > + g_free(s->config_pages); > + } > +} > + > +static void lsilogic_init_config_pages_spi(LsilogicState *s) > +{ > + unsigned i; > + PMptConfigurationPagesSpi pPages = &s->config_pages->u.SpiPages; > + > + /* Clear everything first. */ > + memset(pPages, 0, sizeof(PMptConfigurationPagesSpi)); > + > + for (i = 0; i < RT_ELEMENTS(pPages->aPortPages); i++) { > + /* SCSI-SPI port page 0. */ > + pPages->aPortPages[i].SCSISPIPortPage0.u.fields.Header.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY > + | MPT_CONFIGURATION_PAGE_TYPE_SCSI_SPI_PORT; > + pPages->aPortPages[i].SCSISPIPortPage0.u.fields.Header.u8PageNumber = > + 0; > + pPages->aPortPages[i].SCSISPIPortPage0.u.fields.Header.u8PageLength = > + sizeof(MptConfigurationPageSCSISPIPort0) / 4; > + pPages->aPortPages[i].SCSISPIPortPage0.u.fields. > + fInformationUnitTransfersCapable = true; > + pPages->aPortPages[i].SCSISPIPortPage0.u.fields.fDTCapable = true; > + pPages->aPortPages[i].SCSISPIPortPage0.u.fields.fQASCapable = true; > + pPages->aPortPages[i].SCSISPIPortPage0.u.fields. > + u8MinimumSynchronousTransferPeriod = 0; > + pPages->aPortPages[i].SCSISPIPortPage0.u.fields. > + u8MaximumSynchronousOffset = 0xff; > + pPages->aPortPages[i].SCSISPIPortPage0.u.fields.fWide = true; > + pPages->aPortPages[i].SCSISPIPortPage0.u.fields.fAIPCapable = true; > + pPages->aPortPages[i].SCSISPIPortPage0.u.fields.u2SignalingType = > + 0x3; /* Single Ended. */ > + > + /* SCSI-SPI port page 1. */ > + pPages->aPortPages[i].SCSISPIPortPage1.u.fields.Header.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE > + | MPT_CONFIGURATION_PAGE_TYPE_SCSI_SPI_PORT; > + pPages->aPortPages[i].SCSISPIPortPage1.u.fields.Header.u8PageNumber = 1; > + pPages->aPortPages[i].SCSISPIPortPage1.u.fields.Header.u8PageLength = > + sizeof(MptConfigurationPageSCSISPIPort1) / 4; > + pPages->aPortPages[i].SCSISPIPortPage1.u.fields.u8SCSIID = 7; > + pPages->aPortPages[i].SCSISPIPortPage1.u.fields. > + u16PortResponseIDsBitmask = (1 << 7); > + pPages->aPortPages[i].SCSISPIPortPage1.u.fields.u32OnBusTimerValue = 0; > + > + /* SCSI-SPI port page 2. */ > + pPages->aPortPages[i].SCSISPIPortPage2.u.fields.Header.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE > + | MPT_CONFIGURATION_PAGE_TYPE_SCSI_SPI_PORT; > + pPages->aPortPages[i].SCSISPIPortPage2.u.fields. > + Header.u8PageNumber = 2; > + pPages->aPortPages[i].SCSISPIPortPage2.u.fields.Header. > + u8PageLength = sizeof(MptConfigurationPageSCSISPIPort2) / 4; > + pPages->aPortPages[i].SCSISPIPortPage2.u.fields. > + u4HostSCSIID = 7; > + pPages->aPortPages[i].SCSISPIPortPage2.u.fields. > + u2InitializeHBA = 0x3; > + pPages->aPortPages[i].SCSISPIPortPage2.u.fields. > + fTerminationDisabled = true; > + unsigned iDevice; > + > + for (iDevice = 0; iDevice < RT_ELEMENTS(pPages->aPortPages[i]. > + SCSISPIPortPage2.u.fields.aDeviceSettings); iDevice++) { > + pPages->aPortPages[i].SCSISPIPortPage2.u.fields. > + aDeviceSettings[iDevice].fBootChoice = true; > + } > + /* Everything else 0 for now. */ > + } > + > + unsigned uBusCurr; > + for (uBusCurr = 0; uBusCurr < RT_ELEMENTS(pPages->aBuses); uBusCurr++) { > + unsigned uDeviceCurr; > + for (uDeviceCurr = 0; uDeviceCurr < > + RT_ELEMENTS(pPages->aBuses[uBusCurr].aDevicePages); > + uDeviceCurr++) { > + /* SCSI-SPI device page 0. */ > + pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr]. > + SCSISPIDevicePage0.u.fields.Header.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY > + | MPT_CONFIGURATION_PAGE_TYPE_SCSI_SPI_DEVICE; > + pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr]. > + SCSISPIDevicePage0.u.fields.Header.u8PageNumber = 0; > + pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr]. > + SCSISPIDevicePage0.u.fields.Header.u8PageLength = > + sizeof(MptConfigurationPageSCSISPIDevice0) / 4; > + /* Everything else 0 for now. */ > + > + /* SCSI-SPI device page 1. */ > + pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr]. > + SCSISPIDevicePage1.u.fields.Header.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE > + | MPT_CONFIGURATION_PAGE_TYPE_SCSI_SPI_DEVICE; > + pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr]. > + SCSISPIDevicePage1.u.fields.Header.u8PageNumber = 1; > + pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr]. > + SCSISPIDevicePage1.u.fields.Header.u8PageLength = > + sizeof(MptConfigurationPageSCSISPIDevice1) / 4; > + /* Everything else 0 for now. */ > + > + /* SCSI-SPI device page 2. */ > + pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr]. > + SCSISPIDevicePage2.u.fields.Header.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE > + | MPT_CONFIGURATION_PAGE_TYPE_SCSI_SPI_DEVICE; > + pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr]. > + SCSISPIDevicePage2.u.fields.Header.u8PageNumber = 2; > + pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr]. > + SCSISPIDevicePage2.u.fields.Header.u8PageLength = > + sizeof(MptConfigurationPageSCSISPIDevice2) / 4; > + /* Everything else 0 for now. */ > + > + pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr]. > + SCSISPIDevicePage3.u.fields.Header.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY > + | MPT_CONFIGURATION_PAGE_TYPE_SCSI_SPI_DEVICE; > + pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr]. > + SCSISPIDevicePage3.u.fields.Header.u8PageNumber = 3; > + pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr]. > + SCSISPIDevicePage3.u.fields.Header.u8PageLength = > + sizeof(MptConfigurationPageSCSISPIDevice3) / 4; > + /* Everything else 0 for now. */ > + } > + } > +} > + > +static void lsilogic_init_config_pages_sas(LsilogicState *s) > +{ > + PMptConfigurationPagesSas pPages = &s->config_pages->u.SasPages; > + > + /* Manufacturing Page 7 - Connector settings. */ > + pPages->cbManufacturingPage7 = > + LSILOGICSCSI_MANUFACTURING7_GET_SIZE(s->ports); > + PMptConfigurationPageManufacturing7 pManufacturingPage7 = > + (PMptConfigurationPageManufacturing7)g_malloc0( > + pPages->cbManufacturingPage7); > + MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(pManufacturingPage7, 0, 7, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_PERSISTENT_READONLY); > + /* Set size manually. */ > + if (pPages->cbManufacturingPage7 / 4 > 255) { > + pManufacturingPage7->u.fields.Header.u8PageLength = 255; > + } else { > + pManufacturingPage7->u.fields.Header.u8PageLength = > + pPages->cbManufacturingPage7 / 4; > + } > + pManufacturingPage7->u.fields.u8NumPhys = s->ports; > + pPages->pManufacturingPage7 = pManufacturingPage7; > + > + /* SAS I/O unit page 0 - Port specific information. */ > + pPages->cbSASIOUnitPage0 = LSILOGICSCSI_SASIOUNIT0_GET_SIZE(s->ports); > + PMptConfigurationPageSASIOUnit0 pSASPage0 = > + (PMptConfigurationPageSASIOUnit0)g_malloc0(pPages->cbSASIOUnitPage0); > + > + MPT_CONFIG_EXTENDED_PAGE_HEADER_INIT(pSASPage0, pPages->cbSASIOUnitPage0, > + 0, MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY, > + MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASIOUNIT); > + pSASPage0->u.fields.u8NumPhys = s->ports; > + pPages->pSASIOUnitPage0 = pSASPage0; > + > + /* SAS I/O unit page 1 - Port specific settings. */ > + pPages->cbSASIOUnitPage1 = LSILOGICSCSI_SASIOUNIT1_GET_SIZE(s->ports); > + PMptConfigurationPageSASIOUnit1 pSASPage1 = > + (PMptConfigurationPageSASIOUnit1)g_malloc0(pPages->cbSASIOUnitPage1); > + > + MPT_CONFIG_EXTENDED_PAGE_HEADER_INIT(pSASPage1, pPages->cbSASIOUnitPage1, > + 1, MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE, > + MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASIOUNIT); > + pSASPage1->u.fields.u8NumPhys = pSASPage0->u.fields.u8NumPhys; > + pSASPage1->u.fields.u16ControlFlags = 0; > + pSASPage1->u.fields.u16AdditionalControlFlags = 0; > + pPages->pSASIOUnitPage1 = pSASPage1; > + > + /* SAS I/O unit page 2 - Port specific information. */ > + pPages->SASIOUnitPage2.u.fields.ExtHeader.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY > + | MPT_CONFIGURATION_PAGE_TYPE_EXTENDED; > + pPages->SASIOUnitPage2.u.fields.ExtHeader.u8PageNumber = 2; > + pPages->SASIOUnitPage2.u.fields.ExtHeader.u8ExtPageType = > + MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASIOUNIT; > + pPages->SASIOUnitPage2.u.fields.ExtHeader.u16ExtPageLength = > + sizeof(MptConfigurationPageSASIOUnit2) / 4; > + > + /* SAS I/O unit page 3 - Port specific information. */ > + pPages->SASIOUnitPage3.u.fields.ExtHeader.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY > + | MPT_CONFIGURATION_PAGE_TYPE_EXTENDED; > + pPages->SASIOUnitPage3.u.fields.ExtHeader.u8PageNumber = 3; > + pPages->SASIOUnitPage3.u.fields.ExtHeader.u8ExtPageType = > + MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASIOUNIT; > + pPages->SASIOUnitPage3.u.fields.ExtHeader.u16ExtPageLength = > + sizeof(MptConfigurationPageSASIOUnit3) / 4; > + > + pPages->cPHYs = s->ports; > + pPages->paPHYs = (PMptPHY)g_malloc0(pPages->cPHYs * sizeof(MptPHY)); > + > + /* Initialize the PHY configuration */ > + unsigned i; > + for (i = 0; i < s->ports; i++) { > + PMptPHY pPHYPages = &pPages->paPHYs[i]; > + uint16_t u16ControllerHandle = lsilogicGetHandle(s); > + > + pManufacturingPage7->u.fields.aPHY[i].u8Location = > + LSILOGICSCSI_MANUFACTURING7_LOCATION_AUTO; > + > + pSASPage0->u.fields.aPHY[i].u8Port = i; > + pSASPage0->u.fields.aPHY[i].u8PortFlags = 0; > + pSASPage0->u.fields.aPHY[i].u8PhyFlags = 0; > + pSASPage0->u.fields.aPHY[i].u8NegotiatedLinkRate = > + LSILOGICSCSI_SASIOUNIT0_NEGOTIATED_RATE_FAILED; > + pSASPage0->u.fields.aPHY[i].u32ControllerPhyDeviceInfo = > + LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_SET( > + LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_NO); > + pSASPage0->u.fields.aPHY[i].u16ControllerDevHandle = > + u16ControllerHandle; > + pSASPage0->u.fields.aPHY[i].u16AttachedDevHandle = 0; > + pSASPage0->u.fields.aPHY[i].u32DiscoveryStatus = 0; > + > + pSASPage1->u.fields.aPHY[i].u8Port = i; > + pSASPage1->u.fields.aPHY[i].u8PortFlags = 0; > + pSASPage1->u.fields.aPHY[i].u8PhyFlags = 0; > + pSASPage1->u.fields.aPHY[i].u8MaxMinLinkRate = > + LSILOGICSCSI_SASIOUNIT1_LINK_RATE_MIN_SET( > + LSILOGICSCSI_SASIOUNIT1_LINK_RATE_15GB) > + | LSILOGICSCSI_SASIOUNIT1_LINK_RATE_MAX_SET( > + LSILOGICSCSI_SASIOUNIT1_LINK_RATE_30GB); > + pSASPage1->u.fields.aPHY[i].u32ControllerPhyDeviceInfo = > + LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_SET( > + LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_NO); > + > + /* SAS PHY page 0. */ > + pPHYPages->SASPHYPage0.u.fields.ExtHeader.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY > + | MPT_CONFIGURATION_PAGE_TYPE_EXTENDED; > + pPHYPages->SASPHYPage0.u.fields.ExtHeader.u8PageNumber = 0; > + pPHYPages->SASPHYPage0.u.fields.ExtHeader.u8ExtPageType = > + MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASPHYS; > + pPHYPages->SASPHYPage0.u.fields.ExtHeader.u16ExtPageLength = > + sizeof(MptConfigurationPageSASPHY0) / 4; > + pPHYPages->SASPHYPage0.u.fields.u8AttachedPhyIdentifier = i; > + pPHYPages->SASPHYPage0.u.fields.u32AttachedDeviceInfo = > + LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_SET( > + LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_NO); > + pPHYPages->SASPHYPage0.u.fields.u8ProgrammedLinkRate = > + LSILOGICSCSI_SASIOUNIT1_LINK_RATE_MIN_SET( > + LSILOGICSCSI_SASIOUNIT1_LINK_RATE_15GB) > + | LSILOGICSCSI_SASIOUNIT1_LINK_RATE_MAX_SET( > + LSILOGICSCSI_SASIOUNIT1_LINK_RATE_30GB); > + pPHYPages->SASPHYPage0.u.fields.u8HwLinkRate = > + LSILOGICSCSI_SASIOUNIT1_LINK_RATE_MIN_SET( > + LSILOGICSCSI_SASIOUNIT1_LINK_RATE_15GB) > + | LSILOGICSCSI_SASIOUNIT1_LINK_RATE_MAX_SET( > + LSILOGICSCSI_SASIOUNIT1_LINK_RATE_30GB); > + > + /* SAS PHY page 1. */ > + pPHYPages->SASPHYPage1.u.fields.ExtHeader.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY > + | MPT_CONFIGURATION_PAGE_TYPE_EXTENDED; > + pPHYPages->SASPHYPage1.u.fields.ExtHeader.u8PageNumber = 1; > + pPHYPages->SASPHYPage1.u.fields.ExtHeader.u8ExtPageType = > + MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASPHYS; > + pPHYPages->SASPHYPage1.u.fields.ExtHeader.u16ExtPageLength = > + sizeof(MptConfigurationPageSASPHY1) / 4; > + > + /* Settings for present devices. */ > + if (scsi_device_find(&s->bus, 0, i, 0)) { > + uint16_t u16DeviceHandle = lsilogicGetHandle(s); > + SASADDRESS SASAddress; > + PMptSASDevice pSASDevice = > + (PMptSASDevice)g_malloc0(sizeof(MptSASDevice)); > + > + memset(&SASAddress, 0, sizeof(SASADDRESS)); > + SASAddress.u64Address = s->sas_addr; > + > + pSASPage0->u.fields.aPHY[i].u8NegotiatedLinkRate = > + LSILOGICSCSI_SASIOUNIT0_NEGOTIATED_RATE_SET( > + LSILOGICSCSI_SASIOUNIT0_NEGOTIATED_RATE_30GB); > + pSASPage0->u.fields.aPHY[i].u32ControllerPhyDeviceInfo = > + LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_SET( > + LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_END) > + | LSILOGICSCSI_SASIOUNIT0_DEVICE_SSP_TARGET; > + pSASPage0->u.fields.aPHY[i].u16AttachedDevHandle = > + u16DeviceHandle; > + pSASPage1->u.fields.aPHY[i].u32ControllerPhyDeviceInfo = > + LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_SET( > + LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_END) > + | LSILOGICSCSI_SASIOUNIT0_DEVICE_SSP_TARGET; > + pSASPage0->u.fields.aPHY[i].u16ControllerDevHandle = > + u16DeviceHandle; > + > + pPHYPages->SASPHYPage0.u.fields.u32AttachedDeviceInfo = > + LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_SET( > + LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_END); > + pPHYPages->SASPHYPage0.u.fields.SASAddress = > + SASAddress; > + pPHYPages->SASPHYPage0.u.fields.u16OwnerDevHandle = > + u16DeviceHandle; > + pPHYPages->SASPHYPage0.u.fields.u16AttachedDevHandle = > + u16DeviceHandle; > + > + /* SAS device page 0. */ > + pSASDevice->SASDevicePage0.u.fields.ExtHeader.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY > + | MPT_CONFIGURATION_PAGE_TYPE_EXTENDED; > + pSASDevice->SASDevicePage0.u.fields.ExtHeader.u8PageNumber = 0; > + pSASDevice->SASDevicePage0.u.fields.ExtHeader.u8ExtPageType = > + MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASDEVICE; > + pSASDevice->SASDevicePage0.u.fields.ExtHeader.u16ExtPageLength = > + sizeof(MptConfigurationPageSASDevice0) / 4; > + pSASDevice->SASDevicePage0.u.fields.SASAddress = > + SASAddress; > + pSASDevice->SASDevicePage0.u.fields.u16ParentDevHandle = > + u16ControllerHandle; > + pSASDevice->SASDevicePage0.u.fields.u8PhyNum = i; > + pSASDevice->SASDevicePage0.u.fields.u8AccessStatus = > + LSILOGICSCSI_SASDEVICE0_STATUS_NO_ERRORS; > + pSASDevice->SASDevicePage0.u.fields.u16DevHandle = u16DeviceHandle; > + pSASDevice->SASDevicePage0.u.fields.u8TargetID = i; > + pSASDevice->SASDevicePage0.u.fields.u8Bus = 0; > + pSASDevice->SASDevicePage0.u.fields.u32DeviceInfo = > + LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_SET( > + LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_END) > + | LSILOGICSCSI_SASIOUNIT0_DEVICE_SSP_TARGET; > + pSASDevice->SASDevicePage0.u.fields.u16Flags = > + LSILOGICSCSI_SASDEVICE0_FLAGS_DEVICE_PRESENT > + | LSILOGICSCSI_SASDEVICE0_FLAGS_DEVICE_MAPPED_TO_BUS_AND_TARGET_ID > + | LSILOGICSCSI_SASDEVICE0_FLAGS_DEVICE_MAPPING_PERSISTENT; > + pSASDevice->SASDevicePage0.u.fields.u8PhysicalPort = i; > + > + /* SAS device page 1. */ > + pSASDevice->SASDevicePage1.u.fields.ExtHeader.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY > + | MPT_CONFIGURATION_PAGE_TYPE_EXTENDED; > + pSASDevice->SASDevicePage1.u.fields.ExtHeader.u8PageNumber = 1; > + pSASDevice->SASDevicePage1.u.fields.ExtHeader.u8ExtPageType = > + MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASDEVICE; > + pSASDevice->SASDevicePage1.u.fields.ExtHeader.u16ExtPageLength = > + sizeof(MptConfigurationPageSASDevice1) / 4; > + pSASDevice->SASDevicePage1.u.fields.SASAddress = SASAddress; > + pSASDevice->SASDevicePage1.u.fields.u16DevHandle = u16DeviceHandle; > + pSASDevice->SASDevicePage1.u.fields.u8TargetID = i; > + pSASDevice->SASDevicePage1.u.fields.u8Bus = 0; > + > + /* SAS device page 2. */ > + pSASDevice->SASDevicePage2.u.fields.ExtHeader.u8PageType = > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY > + | MPT_CONFIGURATION_PAGE_TYPE_EXTENDED; > + pSASDevice->SASDevicePage2.u.fields.ExtHeader.u8PageNumber = 2; > + pSASDevice->SASDevicePage2.u.fields.ExtHeader.u8ExtPageType = > + MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASDEVICE; > + pSASDevice->SASDevicePage2.u.fields.ExtHeader.u16ExtPageLength = > + sizeof(MptConfigurationPageSASDevice2) / 4; > + pSASDevice->SASDevicePage2.u.fields.SASAddress = > + SASAddress; > + > + /* Link into device list. */ > + if (!pPages->cDevices) { > + pPages->pSASDeviceHead = pSASDevice; > + pPages->pSASDeviceTail = pSASDevice; > + pPages->cDevices = 1; > + } else { > + pSASDevice->pPrev = pPages->pSASDeviceTail; > + pPages->pSASDeviceTail->pNext = pSASDevice; > + pPages->pSASDeviceTail = pSASDevice; > + pPages->cDevices++; > + } > + } > + } > +} > + > +static void lsilogic_init_config_pages(LsilogicState *s) > +{ > + /* Initialize the common pages. */ > + PMptConfigurationPagesSupported pPages = > + (PMptConfigurationPagesSupported)g_malloc0( > + sizeof(MptConfigurationPagesSupported)); > + > + s->config_pages = pPages; > + > + /* Clear everything first. */ > + memset(pPages, 0, sizeof(MptConfigurationPagesSupported)); > + > + /* Manufacturing Page 0. */ > + MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage0, > + MptConfigurationPageManufacturing0, 0, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_PERSISTENT_READONLY); > + strncpy((char *)pPages->ManufacturingPage0.u.fields.abChipName, > + "QEMU MPT Fusion", 16); > + strncpy((char *)pPages->ManufacturingPage0.u.fields.abChipRevision, > + "1.0", 8); > + strncpy((char *)pPages->ManufacturingPage0.u.fields.abBoardName, > + "QEMU MPT Fusion", 16); > + strncpy((char *)pPages->ManufacturingPage0.u.fields.abBoardAssembly, > + "Verizon", 8); > + strncpy((char *)pPages->ManufacturingPage0.u.fields.abBoardTracerNumber, > + "DEADBEEFDEADBEEF", 16); > + > + /* Manufacturing Page 1 - Leave it 0 for now. */ > + MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage1, > + MptConfigurationPageManufacturing1, 1, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_PERSISTENT_READONLY); > + > + /* Manufacturing Page 2. */ > + MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage2, > + MptConfigurationPageManufacturing2, 2, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_PERSISTENT_READONLY); > + > + if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SPI) { > + pPages->ManufacturingPage2.u.fields.u16PCIDeviceID = > + LSILOGICSCSI_PCI_SPI_DEVICE_ID; > + pPages->ManufacturingPage2.u.fields.u8PCIRevisionID = > + LSILOGICSCSI_PCI_SPI_REVISION_ID; > + } else if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SAS) { > + pPages->ManufacturingPage2.u.fields.u16PCIDeviceID = > + LSILOGICSCSI_PCI_SAS_DEVICE_ID; > + pPages->ManufacturingPage2.u.fields.u8PCIRevisionID = > + LSILOGICSCSI_PCI_SAS_REVISION_ID; > + } > + > + /* Manufacturing Page 3. */ > + MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage3, > + MptConfigurationPageManufacturing3, 3, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_PERSISTENT_READONLY); > + > + if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SPI) { > + pPages->ManufacturingPage3.u.fields.u16PCIDeviceID = > + LSILOGICSCSI_PCI_SPI_DEVICE_ID; > + pPages->ManufacturingPage3.u.fields.u8PCIRevisionID = > + LSILOGICSCSI_PCI_SPI_REVISION_ID; > + } else if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SAS) { > + pPages->ManufacturingPage3.u.fields.u16PCIDeviceID = > + LSILOGICSCSI_PCI_SAS_DEVICE_ID; > + pPages->ManufacturingPage3.u.fields.u8PCIRevisionID = > + LSILOGICSCSI_PCI_SAS_REVISION_ID; > + } > + > + /* Manufacturing Page 4 - Leave it 0 for now. */ > + MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage4, > + MptConfigurationPageManufacturing4, 4, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_PERSISTENT_READONLY); > + > + /* Manufacturing Page 5 - WWID settings. */ > + MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage5, > + MptConfigurationPageManufacturing5, 5, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_PERSISTENT_READONLY); > + > + /* Manufacturing Page 6 - Product specific settings. */ > + MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage6, > + MptConfigurationPageManufacturing6, 6, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE); > + > + /* Manufacturing Page 8 - Product specific settings. */ > + MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage8, > + MptConfigurationPageManufacturing8, 8, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE); > + > + /* Manufacturing Page 9 - Product specific settings. */ > + MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage9, > + MptConfigurationPageManufacturing9, 9, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE); > + > + /* Manufacturing Page 10 - Product specific settings. */ > + MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage10, > + MptConfigurationPageManufacturing10, 10, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE); > + > + /* I/O Unit page 0. */ > + MPT_CONFIG_PAGE_HEADER_INIT_IO_UNIT(&pPages->IOUnitPage0, > + MptConfigurationPageIOUnit0, 0, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY); > + pPages->IOUnitPage0.u.fields.u64UniqueIdentifier = 0xcafe; > + > + /* I/O Unit page 1. */ > + MPT_CONFIG_PAGE_HEADER_INIT_IO_UNIT(&pPages->IOUnitPage1, > + MptConfigurationPageIOUnit1, 1, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY); > + pPages->IOUnitPage1.u.fields.fSingleFunction = true; > + pPages->IOUnitPage1.u.fields.fAllPathsMapped = false; > + pPages->IOUnitPage1.u.fields.fIntegratedRAIDDisabled = true; > + pPages->IOUnitPage1.u.fields.f32BitAccessForced = false; > + > + /* I/O Unit page 2. */ > + MPT_CONFIG_PAGE_HEADER_INIT_IO_UNIT(&pPages->IOUnitPage2, > + MptConfigurationPageIOUnit2, 2, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_PERSISTENT); > + pPages->IOUnitPage2.u.fields.fPauseOnError = false; > + pPages->IOUnitPage2.u.fields.fVerboseModeEnabled = false; > + pPages->IOUnitPage2.u.fields.fDisableColorVideo = false; > + pPages->IOUnitPage2.u.fields.fNotHookInt40h = false; > + pPages->IOUnitPage2.u.fields.u32BIOSVersion = 0xdeadbeef; > + pPages->IOUnitPage2.u.fields.aAdapterOrder[0].fAdapterEnabled = true; > + pPages->IOUnitPage2.u.fields.aAdapterOrder[0].fAdapterEmbedded = true; > + pPages->IOUnitPage2.u.fields.aAdapterOrder[0].u8PCIBusNumber = 0; > + pPages->IOUnitPage2.u.fields.aAdapterOrder[0].u8PCIDevFn = s->dev.devfn; > + > + /* I/O Unit page 3. */ > + MPT_CONFIG_PAGE_HEADER_INIT_IO_UNIT(&pPages->IOUnitPage3, > + MptConfigurationPageIOUnit3, 3, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE); > + pPages->IOUnitPage3.u.fields.u8GPIOCount = 0; > + > + /* I/O Unit page 4. */ > + MPT_CONFIG_PAGE_HEADER_INIT_IO_UNIT(&pPages->IOUnitPage4, > + MptConfigurationPageIOUnit4, 4, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE); > + > + /* IOC page 0. */ > + MPT_CONFIG_PAGE_HEADER_INIT_IOC(&pPages->IOCPage0, > + MptConfigurationPageIOC0, 0, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY); > + pPages->IOCPage0.u.fields.u32TotalNVStore = 0; > + pPages->IOCPage0.u.fields.u32FreeNVStore = 0; > + > + if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SPI) { > + pPages->IOCPage0.u.fields.u16VendorId = > + LSILOGICSCSI_PCI_VENDOR_ID; > + pPages->IOCPage0.u.fields.u16DeviceId = > + LSILOGICSCSI_PCI_SPI_DEVICE_ID; > + pPages->IOCPage0.u.fields.u8RevisionId = > + LSILOGICSCSI_PCI_SPI_REVISION_ID; > + pPages->IOCPage0.u.fields.u32ClassCode = > + LSILOGICSCSI_PCI_SPI_CLASS_CODE; > + pPages->IOCPage0.u.fields.u16SubsystemVendorId = > + LSILOGICSCSI_PCI_SPI_SUBSYSTEM_VENDOR_ID; > + pPages->IOCPage0.u.fields.u16SubsystemId = > + LSILOGICSCSI_PCI_SPI_SUBSYSTEM_ID; > + } else if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SAS) { > + pPages->IOCPage0.u.fields.u16VendorId = > + LSILOGICSCSI_PCI_VENDOR_ID; > + pPages->IOCPage0.u.fields.u16DeviceId = > + LSILOGICSCSI_PCI_SAS_DEVICE_ID; > + pPages->IOCPage0.u.fields.u8RevisionId = > + LSILOGICSCSI_PCI_SAS_REVISION_ID; > + pPages->IOCPage0.u.fields.u32ClassCode = > + LSILOGICSCSI_PCI_SAS_CLASS_CODE; > + pPages->IOCPage0.u.fields.u16SubsystemVendorId = > + LSILOGICSCSI_PCI_SAS_SUBSYSTEM_VENDOR_ID; > + pPages->IOCPage0.u.fields.u16SubsystemId = > + LSILOGICSCSI_PCI_SAS_SUBSYSTEM_ID; > + } > + > + /* IOC page 1. */ > + MPT_CONFIG_PAGE_HEADER_INIT_IOC(&pPages->IOCPage1, > + MptConfigurationPageIOC1, 1, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE); > + pPages->IOCPage1.u.fields.fReplyCoalescingEnabled = false; > + pPages->IOCPage1.u.fields.u32CoalescingTimeout = 0; > + pPages->IOCPage1.u.fields.u8CoalescingDepth = 0; > + > + /* IOC page 2. */ > + MPT_CONFIG_PAGE_HEADER_INIT_IOC(&pPages->IOCPage2, > + MptConfigurationPageIOC2, 2, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY); > + /* Everything else here is 0. */ > + > + /* IOC page 3. */ > + MPT_CONFIG_PAGE_HEADER_INIT_IOC(&pPages->IOCPage3, > + MptConfigurationPageIOC3, 3, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY); > + /* Everything else here is 0. */ > + > + /* IOC page 4. */ > + MPT_CONFIG_PAGE_HEADER_INIT_IOC(&pPages->IOCPage4, > + MptConfigurationPageIOC4, 4, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY); > + /* Everything else here is 0. */ > + > + /* IOC page 6. */ > + MPT_CONFIG_PAGE_HEADER_INIT_IOC(&pPages->IOCPage6, > + MptConfigurationPageIOC6, 6, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY); > + /* Everything else here is 0. */ > + > + /* BIOS page 1. */ > + MPT_CONFIG_PAGE_HEADER_INIT_BIOS(&pPages->BIOSPage1, > + MptConfigurationPageBIOS1, 1, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE); > + > + /* BIOS page 2. */ > + MPT_CONFIG_PAGE_HEADER_INIT_BIOS(&pPages->BIOSPage2, > + MptConfigurationPageBIOS2, 2, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE); > + > + /* BIOS page 4. */ > + MPT_CONFIG_PAGE_HEADER_INIT_BIOS(&pPages->BIOSPage4, > + MptConfigurationPageBIOS4, 4, > + MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE); > + > + if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SPI) { > + lsilogic_init_config_pages_spi(s); > + } else if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SAS) { > + lsilogic_init_config_pages_sas(s); > + } > +} > + > + > +static int lsilogic_hard_reset(LsilogicState *s) > +{ > + > + s->intr_mask |= LSILOGIC_REG_HOST_INTR_MASK_DOORBELL | > + LSILOGIC_REG_HOST_INTR_MASK_REPLY; > + lsilogic_soft_reset(s); > + > + /* Set default values. */ > + if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SPI) { > + s->max_devices = LSILOGICSCSI_PCI_SPI_PORTS_MAX * > + LSILOGICSCSI_PCI_SPI_DEVICES_PER_BUS_MAX; > + } else if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SAS) { > + s->max_devices = LSILOGICSCSI_PCI_SAS_PORTS_MAX * > + LSILOGICSCSI_PCI_SAS_DEVICES_PER_PORT_MAX; > + } > + s->max_buses = 1; > + s->reply_frame_size = 128; /* @todo Figure out where it is needed. */ > + s->next_handle = 1; > + > + lsilogic_config_pages_free(s); > + lsilogic_init_config_pages(s); > + > + /* Mark that we finished performing the reset. */ > + s->state = LSILOGICSTATE_READY; > + return 0; > +} > + > +static void lsilogic_scsi_reset(DeviceState *dev) > +{ > + LsilogicState *s = DO_UPCAST(LsilogicState, dev.qdev, dev); > + > + lsilogic_hard_reset(s); > +} > + > +static const VMStateDescription vmstate_lsilogic = { > + .name = "lsilogic", > + .version_id = 0, > + .minimum_version_id = 0, > + .minimum_version_id_old = 0, > + .fields = (VMStateField[]) { > + VMSTATE_PCI_DEVICE(dev, LsilogicState), > + > + VMSTATE_UINT32(intr_mask, LsilogicState), > + VMSTATE_UINT32(doorbell, LsilogicState), > + VMSTATE_END_OF_LIST() > + } > +}; > + > +static void lsilogic_queues_free(LsilogicState *s) > +{ > + assert(s->reply_free_queue); > + > + g_free(s->reply_free_queue); > + > + s->reply_free_queue = NULL; > + s->reply_post_queue = NULL; > + s->request_queue = NULL; > +} > + > +static void lsilogic_scsi_uninit(PCIDevice *d) > +{ > + LsilogicState *s = DO_UPCAST(LsilogicState, dev, d); > + > + lsilogic_queues_free(s); > +#ifdef USE_MSIX > + msix_uninit(&s->dev, &s->mmio_io); > +#endif > + memory_region_destroy(&s->mmio_io); > + memory_region_destroy(&s->port_io); > + memory_region_destroy(&s->diag_io); > +} > + > +static const struct SCSIBusInfo lsilogic_scsi_info = { > + .tcq = true, > + .max_target = LSILOGICSCSI_PCI_SAS_PORTS_MAX, > + .max_lun = 1, > + > + .transfer_data = lsilogic_xfer_complete, > + .get_sg_list = lsilogic_get_sg_list, > + .complete = lsilogic_command_complete, > + .cancel = lsilogic_command_cancel, > +}; > + > +static int lsilogic_queues_alloc(LsilogicState *s) > +{ > + uint32_t cbQueues; > + > + assert(!s->reply_free_queue); > + > + cbQueues = 2*s->reply_queue_entries * sizeof(uint32_t); > + cbQueues += s->request_queue_entries * sizeof(uint32_t); > + > + s->reply_free_queue = g_malloc0(cbQueues); > + > + s->reply_post_queue = s->reply_free_queue + s->reply_queue_entries; > + > + s->request_queue = s->reply_post_queue + s->reply_queue_entries; > + > + return 0; > +} > + > +static int lsilogic_scsi_init(PCIDevice *dev, LSILOGICCTRLTYPE ctrl_type) > +{ > + LsilogicState *s = DO_UPCAST(LsilogicState, dev, dev); > + uint8_t *pci_conf; > + > + s->ctrl_type = ctrl_type; > + > + pci_conf = s->dev.config; > + > + /* PCI latency timer = 0 */ > + pci_conf[PCI_LATENCY_TIMER] = 0; > + /* Interrupt pin 1 */ > + pci_conf[PCI_INTERRUPT_PIN] = 0x01; > + > + if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SPI) { > + memory_region_init_io(&s->mmio_io, &lsilogic_mmio_ops, s, > + "lsilogic-mmio", 0x4000); > + memory_region_init_io(&s->port_io, &lsilogic_port_ops, s, > + "lsilogic-io", 256); > + memory_region_init_io(&s->diag_io, &lsilogic_diag_ops, s, > + "lsilogic-diag", 0x10000); > + } else if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SAS) { > + memory_region_init_io(&s->mmio_io, &lsilogic_mmio_ops, s, > + "lsilogic-mmio", 0x4000); > + memory_region_init_io(&s->port_io, &lsilogic_port_ops, s, > + "lsilogic-io", 256); > + memory_region_init_io(&s->diag_io, &lsilogic_diag_ops, s, > + "lsilogic-diag", 0x10000); > + } Find 10 differences between if and else branches above :) > + > +#ifdef USE_MSIX > + /* MSI-X support is currently broken */ > + if (lsilogic_use_msix(s) && > + msix_init(&s->dev, 15, &s->mmio_io, 0, 0x2000)) { > + s->flags &= ~LSILOGIC_MASK_USE_MSIX; > + } > +#else > + s->flags &= ~LSILOGIC_MASK_USE_MSIX; > +#endif > + > + pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->port_io); > + pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY | > + PCI_BASE_ADDRESS_MEM_TYPE_32, &s->mmio_io); > + pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY | > + PCI_BASE_ADDRESS_MEM_TYPE_32, &s->diag_io); > + > + if (lsilogic_use_msix(s)) { > + 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); > + } > + s->reply_queue_entries = LSILOGICSCSI_REPLY_QUEUE_DEPTH_DEFAULT + 1; > + s->request_queue_entries = LSILOGICSCSI_REQUEST_QUEUE_DEPTH_DEFAULT + 1; > + lsilogic_queues_alloc(s); > + > + trace_lsilogic_init(0, 0, > + lsilogic_use_msix(s) ? "MSI-X" : "INTx", > + lsilogic_is_sas(s) ? "sas" : "scsi"); > + > + if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SPI) { > + s->ports = LSILOGICSCSI_PCI_SPI_PORTS_MAX; > + s->max_devices = s->ports * LSILOGICSCSI_PCI_SPI_DEVICES_PER_BUS_MAX; > + } else if (s->ctrl_type == LSILOGICCTRLTYPE_SCSI_SAS) { > + s->max_devices = s->ports * LSILOGICSCSI_PCI_SAS_DEVICES_PER_PORT_MAX; > + } > + > + scsi_bus_new(&s->bus, &dev->qdev, &lsilogic_scsi_info); > + scsi_bus_legacy_handle_cmdline(&s->bus); > + return 0; > +} > + > +static int lsilogic_scsi_spi_init(PCIDevice *dev) > +{ > + return lsilogic_scsi_init(dev, LSILOGICCTRLTYPE_SCSI_SPI); > +} > + > +static int lsilogic_scsi_sas_init(PCIDevice *dev) > +{ > + return lsilogic_scsi_init(dev, LSILOGICCTRLTYPE_SCSI_SAS); > +} > + > +static Property lsilogicscsi_properties[] = { > +#ifdef USE_MSIX > + DEFINE_PROP_BIT("use_msix", LsilogicState, flags, > + LSILOGIC_FLAG_USE_MSIX, false), > +#endif > + DEFINE_PROP_END_OF_LIST(), > +}; > + > +static Property lsilogicsas_properties[] = { > + DEFINE_PROP_UINT32("ports", LsilogicState, ports, > + LSILOGICSCSI_PCI_SAS_PORTS_DEFAULT), > + DEFINE_PROP_HEX64("sas_address", LsilogicState, sas_addr, 0), > +#ifdef USE_MSIX > + DEFINE_PROP_BIT("use_msix", LsilogicState, flags, > + LSILOGIC_FLAG_USE_MSIX, false), > +#endif > + DEFINE_PROP_END_OF_LIST(), > +}; > + > +static void lsilogicscsi_class_init(ObjectClass *oc, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(oc); > + PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); > + > + pc->init = lsilogic_scsi_spi_init; > + pc->exit = lsilogic_scsi_uninit; > + pc->vendor_id = PCI_VENDOR_ID_LSI_LOGIC; > + pc->device_id = PCI_DEVICE_ID_LSI_53C1030; > + pc->subsystem_vendor_id = PCI_VENDOR_ID_LSI_LOGIC; > + pc->subsystem_id = 0x8000; > + pc->class_id = PCI_CLASS_STORAGE_SCSI; > + dc->props = lsilogicscsi_properties; > + dc->reset = lsilogic_scsi_reset; > + dc->vmsd = &vmstate_lsilogic; > + dc->desc = "LSI SCSI 53C1030"; > +} > + > +static void lsilogicsas_class_init(ObjectClass *oc, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(oc); > + PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); > + > + pc->init = lsilogic_scsi_sas_init; > + pc->exit = lsilogic_scsi_uninit; > + pc->romfile = 0; > + pc->vendor_id = PCI_VENDOR_ID_LSI_LOGIC; > + pc->device_id = PCI_DEVICE_ID_LSI_SAS1068; > + pc->subsystem_vendor_id = PCI_VENDOR_ID_LSI_LOGIC; > + pc->subsystem_id = 0x8000; > + pc->class_id = PCI_CLASS_STORAGE_SCSI; > + dc->props = lsilogicsas_properties; > + dc->reset = lsilogic_scsi_reset; > + dc->vmsd = &vmstate_lsilogic; > + dc->desc = "LSI SAS 1068"; I think it should be more verbose "LSI Logic PCI-X Fusion-MPT SAS Host Bus Adapter" or something? > +} > + > +static void lsilogicsase_class_init(ObjectClass *oc, void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(oc); > + PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); > + > + pc->init = lsilogic_scsi_sas_init; > + pc->exit = lsilogic_scsi_uninit; > + pc->romfile = 0; > + pc->vendor_id = PCI_VENDOR_ID_LSI_LOGIC; > + pc->device_id = PCI_DEVICE_ID_LSI_SAS1068E; > + pc->subsystem_vendor_id = PCI_VENDOR_ID_LSI_LOGIC; > + pc->subsystem_id = 0x8000; > + pc->is_express = 1; > + pc->class_id = PCI_CLASS_STORAGE_SCSI; > + dc->props = lsilogicsas_properties; > + dc->reset = lsilogic_scsi_reset; > + dc->vmsd = &vmstate_lsilogic; > + dc->desc = "LSI SAS 1068E"; > +} > + > +static const TypeInfo lsilogic_info[] = { > + { > + .name = "lsi53c1030", > + .parent = TYPE_PCI_DEVICE, > + .instance_size = sizeof(LsilogicState), > + .class_init = lsilogicscsi_class_init, > + }, { > + .name = "sas1068", > + .parent = TYPE_PCI_DEVICE, > + .instance_size = sizeof(LsilogicState), > + .class_init = lsilogicsas_class_init, > + }, { > + .name = "sas1068e", > + .parent = TYPE_PCI_DEVICE, > + .instance_size = sizeof(LsilogicState), > + .class_init = lsilogicsase_class_init, > + } > +}; > + > +static void lsilogic_register_types(void) > +{ > + unsigned i; > + for (i = 0; i < ARRAY_SIZE(lsilogic_info); i++) { > + type_register(&lsilogic_info[i]); > + } > +} > + > +type_init(lsilogic_register_types) > diff --git a/hw/lsilogic.h b/hw/lsilogic.h > new file mode 100644 > index 0000000..ed2f791 > --- /dev/null > +++ b/hw/lsilogic.h > @@ -0,0 +1,3365 @@ > +/* Id: DevLsiLogicSCSI.h 40640 2012-03-26 12:55:17Z vboxsync $ */ > +/** @file > + * VBox storage devices: LsiLogic LSI53c1030 SCSI controller - Defines and structures. > + */ Can you combine this header into .c file please? And if possible, drop all kind of unused types and dead code from it. > + > +/* > + * Copyright (C) 2006-2009 Oracle Corporation > + * > + * This file is part of VirtualBox Open Source Edition (OSE), as > + * available from http://www.virtualbox.org. This file is free software; > + * you can redistribute it and/or modify it under the terms of the GNU > + * General Public License (GPL) as published by the Free Software > + * Foundation, in version 2 as it comes in the "COPYING" file of the > + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the > + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. > + */ > +#ifndef __DEVLSILOGICSCSI_H__ > +#define __DEVLSILOGICSCSI_H__ > + > + > +#define LSILOGICSCSI_REQUEST_QUEUE_DEPTH_DEFAULT 128 > +#define LSILOGICSCSI_REPLY_QUEUE_DEPTH_DEFAULT 128 > + > +#define LSILOGICSCSI_MAXIMUM_CHAIN_DEPTH 0x22 > + > +#define LSILOGIC_NR_OF_ALLOWED_BIGGER_LISTS 100 > + > +/** Equal for all devices */ > +#define LSILOGICSCSI_PCI_VENDOR_ID (0x1000) > + > +/** SPI SCSI controller (LSI53C1030) */ > +#define LSILOGICSCSI_PCI_SPI_CTRLNAME "LSI53C1030" > +#define LSILOGICSCSI_PCI_SPI_DEVICE_ID (0x0030) > +#define LSILOGICSCSI_PCI_SPI_REVISION_ID (0x00) > +#define LSILOGICSCSI_PCI_SPI_CLASS_CODE (0x01) > +#define LSILOGICSCSI_PCI_SPI_SUBSYSTEM_VENDOR_ID (0x1000) > +#define LSILOGICSCSI_PCI_SPI_SUBSYSTEM_ID (0x8000) > +#define LSILOGICSCSI_PCI_SPI_PORTS_MAX 1 > +#define LSILOGICSCSI_PCI_SPI_BUSES_MAX 1 > +#define LSILOGICSCSI_PCI_SPI_DEVICES_PER_BUS_MAX 16 > +#define LSILOGICSCSI_PCI_SPI_DEVICES_MAX \ > + (LSILOGICSCSI_PCI_SPI_BUSES_MAX*LSILOGICSCSI_PCI_SPI_DEVICES_PER_BUS_MAX) > + > +/** SAS SCSI controller (SAS1068 PCI-X Fusion-MPT SAS) */ > +#define LSILOGICSCSI_PCI_SAS_CTRLNAME "SAS1068" > +#define LSILOGICSCSI_PCI_SAS_DEVICE_ID (0x0054) > +#define LSILOGICSCSI_PCI_SAS_REVISION_ID (0x00) > +#define LSILOGICSCSI_PCI_SAS_CLASS_CODE (0x00) > +#define LSILOGICSCSI_PCI_SAS_SUBSYSTEM_VENDOR_ID (0x1000) > +#define LSILOGICSCSI_PCI_SAS_SUBSYSTEM_ID (0x8000) pci ids are in their standard names, pls use from there. > +#define LSILOGICSCSI_PCI_SAS_PORTS_MAX 256 > +#define LSILOGICSCSI_PCI_SAS_PORTS_DEFAULT 8 > +#define LSILOGICSCSI_PCI_SAS_DEVICES_PER_PORT_MAX 1 > +#define LSILOGICSCSI_PCI_SAS_DEVICES_MAX \ > + (LSILOGICSCSI_PCI_SAS_PORTS_MAX*LSILOGICSCSI_PCI_SAS_DEVICES_PER_PORT_MAX) > + > +/** > + * A SAS address. > + */ > +#pragma pack(1) > +typedef union SASADDRESS { > + /** 64bit view. */ > + uint64_t u64Address; > + /** 32bit view. */ > + uint32_t u32Address[2]; > + /** 16bit view. */ > + uint16_t u16Address[4]; > + /** Byte view. */ > + uint8_t u8Address[8]; > +} SASADDRESS, *PSASADDRESS; > +#pragma pack() > + > +/** > + * Possible device types we support. > + */ > +typedef enum LSILOGICCTRLTYPE { > + /** SPI SCSI controller (PCI dev id 0x0030) */ > + LSILOGICCTRLTYPE_SCSI_SPI = 0, > + /** SAS SCSI controller (PCI dev id 0x0054) */ > + LSILOGICCTRLTYPE_SCSI_SAS = 1, > + /** 32bit hack */ > + LSILOGICCTRLTYPE_32BIT_HACK = 0x7fffffff > +} LSILOGICCTRLTYPE, *PLSILOGICCTRLTYPE; > + > +/** > + * A simple SG element for a 64bit address. > + */ > +#pragma pack(1) > +typedef struct MptSGEntrySimple64 { > + /** Length of the buffer this entry describes. */ > + unsigned u24Length:24; > + /** Flag whether this element is the end of the list. */ > + unsigned fEndOfList:1; > + /** Flag whether the address is 32bit or 64bits wide. */ > + unsigned f64BitAddress:1; > + /** Flag whether this buffer contains data to be transferred or > + is the destination. */ > + unsigned fBufferContainsData:1; > + /** Flag whether this is a local address or a system address. */ > + unsigned fLocalAddress:1; > + /** Element type. */ > + unsigned u2ElementType:2; > + /** Flag whether this is the last element of the buffer. */ > + unsigned fEndOfBuffer:1; > + /** Flag whether this is the last element of the current segment. */ > + unsigned fLastElement:1; > + /** Lower 32bits of the address of the data buffer. */ > + unsigned u32DataBufferAddressLow:32; > + /** Upper 32bits of the address of the data buffer. */ > + unsigned u32DataBufferAddressHigh:32; > +} MptSGEntrySimple64, *PMptSGEntrySimple64; > +#pragma pack() > + > +/** > + * A simple SG element for a 32bit address. > + */ > +#pragma pack(1) > +typedef struct MptSGEntrySimple32 { > + /** Length of the buffer this entry describes. */ > + unsigned u24Length:24; > + /** Flag whether this element is the end of the list. */ > + unsigned fEndOfList:1; > + /** Flag whether the address is 32bit or 64bits wide. */ > + unsigned f64BitAddress:1; > + /** Flag whether this buffer contains data to be transferred > + or is the destination. */ > + unsigned fBufferContainsData:1; > + /** Flag whether this is a local address or a system address. */ > + unsigned fLocalAddress:1; > + /** Element type. */ > + unsigned u2ElementType:2; > + /** Flag whether this is the last element of the buffer. */ > + unsigned fEndOfBuffer:1; > + /** Flag whether this is the last element of the current segment. */ > + unsigned fLastElement:1; > + /** Lower 32bits of the address of the data buffer. */ > + unsigned u32DataBufferAddressLow:32; > +} MptSGEntrySimple32, *PMptSGEntrySimple32; > +#pragma pack() > + > +/** > + * A chain SG element. > + */ > +#pragma pack(1) > +typedef struct MptSGEntryChain { > + /** Size of the segment. */ > + unsigned u16Length:16; > + /** Offset in 32bit words of the next chain element in the segment > + * identified by this element. */ > + unsigned u8NextChainOffset:8; > + /** Reserved. */ > + unsigned fReserved0:1; > + /** Flag whether the address is 32bit or 64bits wide. */ > + unsigned f64BitAddress:1; > + /** Reserved. */ > + unsigned fReserved1:1; > + /** Flag whether this is a local address or a system address. */ > + unsigned fLocalAddress:1; > + /** Element type. */ > + unsigned u2ElementType:2; > + /** Flag whether this is the last element of the buffer. */ > + unsigned u2Reserved2:2; > + /** Lower 32bits of the address of the data buffer. */ > + unsigned u32SegmentAddressLow:32; > + /** Upper 32bits of the address of the data buffer. */ > + unsigned u32SegmentAddressHigh:32; > +} MptSGEntryChain, *PMptSGEntryChain; > +#pragma pack() > + > +typedef union MptSGEntryUnion { > + MptSGEntrySimple64 Simple64; > + MptSGEntrySimple32 Simple32; > + MptSGEntryChain Chain; > +} MptSGEntryUnion, *PMptSGEntryUnion; > + > +/** > + * MPT Fusion message header - Common for all message frames. > + * This is filled in by the guest. > + */ > +#pragma pack(1) > +typedef struct MptMessageHdr { > + /** Function dependent data. */ > + uint16_t u16FunctionDependent; > + /** Chain offset. */ > + uint8_t u8ChainOffset; > + /** The function code. */ > + uint8_t u8Function; > + /** Function dependent data. */ > + uint8_t au8FunctionDependent[3]; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context - Unique ID from the guest unmodified by the device. */ > + uint32_t u32MessageContext; > +} MptMessageHdr, *PMptMessageHdr; > +#pragma pack() > + > +/** Defined function codes found in the message header. */ > +#define MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST (0x00) > +#define MPT_MESSAGE_HDR_FUNCTION_SCSI_TASK_MGMT (0x01) > +#define MPT_MESSAGE_HDR_FUNCTION_IOC_INIT (0x02) > +#define MPT_MESSAGE_HDR_FUNCTION_IOC_FACTS (0x03) > +#define MPT_MESSAGE_HDR_FUNCTION_CONFIG (0x04) > +#define MPT_MESSAGE_HDR_FUNCTION_PORT_FACTS (0x05) > +#define MPT_MESSAGE_HDR_FUNCTION_PORT_ENABLE (0x06) > +#define MPT_MESSAGE_HDR_FUNCTION_EVENT_NOTIFICATION (0x07) > +#define MPT_MESSAGE_HDR_FUNCTION_EVENT_ACK (0x08) > +#define MPT_MESSAGE_HDR_FUNCTION_FW_DOWNLOAD (0x09) > +#define MPT_MESSAGE_HDR_FUNCTION_TARGET_CMD_BUFFER_POST (0x0A) > +#define MPT_MESSAGE_HDR_FUNCTION_TARGET_ASSIST (0x0B) > +#define MPT_MESSAGE_HDR_FUNCTION_TARGET_STATUS_SEND (0x0C) > +#define MPT_MESSAGE_HDR_FUNCTION_TARGET_MODE_ABORT (0x0D) > +#define MPT_MESSAGE_HDR_FUNCTION_FW_UPLOAD (0x12) > + > +#ifdef DEBUG > +/** > + * Function names > + */ > +static const char * const g_apszMPTFunctionNames[] = { > + "SCSI I/O Request", > + "SCSI Task Management", > + "IOC Init", > + "IOC Facts", > + "Config", > + "Port Facts", > + "Port Enable", > + "Event Notification", > + "Event Ack", > + "Firmware Download" > +}; > +#endif > + > +/** > + * Default reply message. > + * Send from the device to the guest upon completion of a request. > + */ > + #pragma pack(1) > +typedef struct MptDefaultReplyMessage { > + /** Function dependent data. */ > + uint16_t u16FunctionDependent; > + /** Length of the message in 32bit DWords. */ > + uint8_t u8MessageLength; > + /** Function which completed. */ > + uint8_t u8Function; > + /** Function dependent. */ > + uint8_t au8FunctionDependent[3]; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context given in the request. */ > + uint32_t u32MessageContext; > + /** Function dependent status code. */ > + uint16_t u16FunctionDependentStatus; > + /** Status of the IOC. */ > + uint16_t u16IOCStatus; > + /** Additional log info. */ > + uint32_t u32IOCLogInfo; > +} MptDefaultReplyMessage, *PMptDefaultReplyMessage; > +#pragma pack() > + > +/** > + * IO controller init request. > + */ > +#pragma pack(1) > +typedef struct MptIOCInitRequest { > + /** Which system send this init request. */ > + uint8_t u8WhoInit; > + /** Reserved */ > + uint8_t u8Reserved; > + /** Chain offset in the SG list. */ > + uint8_t u8ChainOffset; > + /** Function to execute. */ > + uint8_t u8Function; > + /** Flags */ > + uint8_t u8Flags; > + /** Maximum number of devices the driver can handle. */ > + uint8_t u8MaxDevices; > + /** Maximum number of buses the driver can handle. */ > + uint8_t u8MaxBuses; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > + /** Reply frame size. */ > + uint16_t u16ReplyFrameSize; > + /** Reserved */ > + uint16_t u16Reserved; > + /** Upper 32bit part of the 64bit address the message frames are in. > + * That means all frames must be in the same 4GB segment. */ > + uint32_t u32HostMfaHighAddr; > + /** Upper 32bit of the sense buffer. */ > + uint32_t u32SenseBufferHighAddr; > +} MptIOCInitRequest, *PMptIOCInitRequest; > +#pragma pack() > + > +/** > + * IO controller init reply. > + */ > +#pragma pack(1) > +typedef struct MptIOCInitReply { > + /** Which subsystem send this init request. */ > + uint8_t u8WhoInit; > + /** Reserved */ > + uint8_t u8Reserved; > + /** Message length */ > + uint8_t u8MessageLength; > + /** Function. */ > + uint8_t u8Function; > + /** Flags */ > + uint8_t u8Flags; > + /** Maximum number of devices the driver can handle. */ > + uint8_t u8MaxDevices; > + /** Maximum number of busses the driver can handle. */ > + uint8_t u8MaxBuses; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID */ > + uint32_t u32MessageContext; > + /** Reserved */ > + uint16_t u16Reserved; > + /** IO controller status. */ > + uint16_t u16IOCStatus; > + /** IO controller log information. */ > + uint32_t u32IOCLogInfo; > +} MptIOCInitReply, *PMptIOCInitReply; > +#pragma pack() > + > +/** > + * IO controller facts request. > + */ > +#pragma pack(1) > +typedef struct MptIOCFactsRequest { > + /** Reserved. */ > + uint16_t u16Reserved; > + /** Chain offset in SG list. */ > + uint8_t u8ChainOffset; > + /** Function number. */ > + uint8_t u8Function; > + /** Reserved */ > + uint8_t u8Reserved[3]; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > +} MptIOCFactsRequest, *PMptIOCFactsRequest; > +#pragma pack() > + > +/** > + * IO controller facts reply. > + */ > +#pragma pack(1) > +typedef struct MptIOCFactsReply { > + /** Message version. */ > + uint16_t u16MessageVersion; > + /** Message length. */ > + uint8_t u8MessageLength; > + /** Function number. */ > + uint8_t u8Function; > + /** Reserved */ > + uint16_t u16Reserved1; > + /** IO controller number */ > + uint8_t u8IOCNumber; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > + /** IO controller exceptions */ > + uint16_t u16IOCExceptions; > + /** IO controller status. */ > + uint16_t u16IOCStatus; > + /** IO controller log information. */ > + uint32_t u32IOCLogInfo; > + /** Maximum chain depth. */ > + uint8_t u8MaxChainDepth; > + /** The current value of the WhoInit field. */ > + uint8_t u8WhoInit; > + /** Block size. */ > + uint8_t u8BlockSize; > + /** Flags. */ > + uint8_t u8Flags; > + /** Depth of the reply queue. */ > + uint16_t u16ReplyQueueDepth; > + /** Size of a request frame. */ > + uint16_t u16RequestFrameSize; > + /** Reserved */ > + uint16_t u16Reserved2; > + /** Product ID. */ > + uint16_t u16ProductID; > + /** Current value of the high 32bit MFA address. */ > + uint32_t u32CurrentHostMFAHighAddr; > + /** Global credits - Number of entries allocated to queues */ > + uint16_t u16GlobalCredits; > + /** Number of ports on the IO controller */ > + uint8_t u8NumberOfPorts; > + /** Event state. */ > + uint8_t u8EventState; > + /** Current value of the high 32bit sense buffer address. */ > + uint32_t u32CurrentSenseBufferHighAddr; > + /** Current reply frame size. */ > + uint16_t u16CurReplyFrameSize; > + /** Maximum number of devices. */ > + uint8_t u8MaxDevices; > + /** Maximum number of buses. */ > + uint8_t u8MaxBuses; > + /** Size of the firmware image. */ > + uint32_t u32FwImageSize; > + /** Reserved. */ > + uint32_t u32Reserved; > + /** Firmware version */ > + uint32_t u32FWVersion; > +} MptIOCFactsReply, *PMptIOCFactsReply; > +#pragma pack() > + > +/** > + * Port facts request > + */ > +#pragma pack(1) > +typedef struct MptPortFactsRequest { > + /** Reserved */ > + uint16_t u16Reserved1; > + /** Message length. */ > + uint8_t u8MessageLength; > + /** Function number. */ > + uint8_t u8Function; > + /** Reserved */ > + uint16_t u16Reserved2; > + /** Port number to get facts for. */ > + uint8_t u8PortNumber; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > +} MptPortFactsRequest, *PMptPortFactsRequest; > +#pragma pack() > + > +/** > + * Port facts reply. > + */ > +#pragma pack(1) > +typedef struct MptPortFactsReply { > + /** Reserved. */ > + uint16_t u16Reserved1; > + /** Message length. */ > + uint8_t u8MessageLength; > + /** Function number. */ > + uint8_t u8Function; > + /** Reserved */ > + uint16_t u16Reserved2; > + /** Port number the facts are for. */ > + uint8_t u8PortNumber; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > + /** Reserved. */ > + uint16_t u16Reserved3; > + /** IO controller status. */ > + uint16_t u16IOCStatus; > + /** IO controller log information. */ > + uint32_t u32IOCLogInfo; > + /** Reserved */ > + uint8_t u8Reserved; > + /** Port type */ > + uint8_t u8PortType; > + /** Maximum number of devices on this port. */ > + uint16_t u16MaxDevices; > + /** SCSI ID of this port on the attached bus. */ > + uint16_t u16PortSCSIID; > + /** Protocol flags. */ > + uint16_t u16ProtocolFlags; > + /** Maximum number of target command buffers which can be > + posted to this port at a time. */ > + uint16_t u16MaxPostedCmdBuffers; > + /** Maximum number of target IDs that remain persistent > + between power/reset cycles. */ > + uint16_t u16MaxPersistentIDs; > + /** Maximum number of LAN buckets. */ > + uint16_t u16MaxLANBuckets; > + /** Reserved. */ > + uint16_t u16Reserved4; > + /** Reserved. */ > + uint32_t u32Reserved; > +} MptPortFactsReply, *PMptPortFactsReply; > +#pragma pack() > + > +/** > + * Port Enable request. > + */ > +#pragma pack(1) > +typedef struct MptPortEnableRequest { > + /** Reserved. */ > + uint16_t u16Reserved1; > + /** Message length. */ > + uint8_t u8MessageLength; > + /** Function number. */ > + uint8_t u8Function; > + /** Reserved. */ > + uint16_t u16Reserved2; > + /** Port number to enable. */ > + uint8_t u8PortNumber; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > +} MptPortEnableRequest, *PMptPortEnableRequest; > +#pragma pack() > + > +/** > + * Port enable reply. > + */ > +#pragma pack(1) > +typedef struct MptPortEnableReply { > + /** Reserved. */ > + uint16_t u16Reserved1; > + /** Message length. */ > + uint8_t u8MessageLength; > + /** Function number. */ > + uint8_t u8Function; > + /** Reserved */ > + uint16_t u16Reserved2; > + /** Port number which was enabled. */ > + uint8_t u8PortNumber; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > + /** Reserved. */ > + uint16_t u16Reserved3; > + /** IO controller status */ > + uint16_t u16IOCStatus; > + /** IO controller log information. */ > + uint32_t u32IOCLogInfo; > +} MptPortEnableReply, *PMptPortEnableReply; > +#pragma pack() > + > +/** > + * Event notification request. > + */ > +#pragma pack(1) > +typedef struct MptEventNotificationRequest { > + /** Switch - Turns event notification on and off. */ > + uint8_t u8Switch; > + /** Reserved. */ > + uint8_t u8Reserved1; > + /** Chain offset. */ > + uint8_t u8ChainOffset; > + /** Function number. */ > + uint8_t u8Function; > + /** Reserved. */ > + uint8_t u8reserved2[3]; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > +} MptEventNotificationRequest, *PMptEventNotificationRequest; > +#pragma pack() > + > +/** > + * Event notification reply. > + */ > +#pragma pack(1) > +typedef struct MptEventNotificationReply { > + /** Event data length. */ > + uint16_t u16EventDataLength; > + /** Message length. */ > + uint8_t u8MessageLength; > + /** Function number. */ > + uint8_t u8Function; > + /** Reserved. */ > + uint16_t u16Reserved1; > + /** Ack required. */ > + uint8_t u8AckRequired; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > + /** Reserved. */ > + uint16_t u16Reserved2; > + /** IO controller status. */ > + uint16_t u16IOCStatus; > + /** IO controller log information. */ > + uint32_t u32IOCLogInfo; > + /** Notification event. */ > + uint32_t u32Event; > + /** Event context. */ > + uint32_t u32EventContext; > + /** Event data. */ > + uint32_t u32EventData; > +} MptEventNotificationReply, *PMptEventNotificationReply; > +#pragma pack() > + > +#define MPT_EVENT_EVENT_CHANGE (0x0000000a) > + > +/** > + * FW download request. > + */ > +#pragma pack(1) > +typedef struct MptFWDownloadRequest { > + /** Switch - Turns event notification on and off. */ > + uint8_t u8ImageType; > + /** Reserved. */ > + uint8_t u8Reserved1; > + /** Chain offset. */ > + uint8_t u8ChainOffset; > + /** Function number. */ > + uint8_t u8Function; > + /** Reserved. */ > + uint8_t u8Reserved2[3]; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > +} MptFWDownloadRequest, *PMptFWDownloadRequest; > +#pragma pack() > + > +#define MPT_FW_DOWNLOAD_REQUEST_IMAGE_TYPE_RESERVED 0 > +#define MPT_FW_DOWNLOAD_REQUEST_IMAGE_TYPE_FIRMWARE 1 > +#define MPT_FW_DOWNLOAD_REQUEST_IMAGE_TYPE_MPI_BIOS 2 > +#define MPT_FW_DOWNLOAD_REQUEST_IMAGE_TYPE_NVDATA 3 > + > +/** > + * FW download reply. > + */ > +#pragma pack(1) > +typedef struct MptFWDownloadReply { > + /** Reserved. */ > + uint16_t u16Reserved1; > + /** Message length. */ > + uint8_t u8MessageLength; > + /** Function number. */ > + uint8_t u8Function; > + /** Reserved. */ > + uint8_t u8Reserved2[3]; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > + /** Reserved. */ > + uint16_t u16Reserved2; > + /** IO controller status. */ > + uint16_t u16IOCStatus; > + /** IO controller log information. */ > + uint32_t u32IOCLogInfo; > +} MptFWDownloadReply, *PMptFWDownloadReply; > +#pragma pack() > + > +typedef struct MptFwHeader { > + uint32_t ArmBranchInstruction0; /* 00h */ > + uint32_t Signature0; /* 04h */ > + uint32_t Signature1; /* 08h */ > + uint32_t Signature2; /* 0Ch */ > + uint32_t ArmBranchInstruction1; /* 10h */ > + uint32_t ArmBranchInstruction2; /* 14h */ > + uint32_t Reserved; /* 18h */ > + uint32_t Checksum; /* 1Ch */ > + uint16_t VendorId; /* 20h */ > + uint16_t ProductId; /* 22h */ > + uint32_t FWVersion; /* 24h */ > + uint32_t SeqCodeVersion; /* 28h */ > + uint32_t ImageSize; /* 2Ch */ > + uint32_t NextImageHeaderOffset; /* 30h */ > + uint32_t LoadStartAddress; /* 34h */ > + uint32_t IopResetVectorValue; /* 38h */ > + uint32_t IopResetRegAddr; /* 3Ch */ > + uint32_t VersionNameWhat; /* 40h */ > + uint8_t VersionName[32]; /* 44h */ > + uint32_t VendorNameWhat; /* 64h */ > + uint8_t VendorName[32]; /* 68h */ > +} MptFwHeader_t, *pMptFwHeader_t; > + > +typedef struct MptFWUploadTCSGE { > + uint8_t Reserved; /* 00h */ > + uint8_t ContextSize; /* 01h */ > + uint8_t DetailsLength; /* 02h */ > + uint8_t Flags; /* 03h */ > + uint32_t Reserved1; /* 04h */ > + uint32_t ImageOffset; /* 08h */ > + uint32_t ImageSize; /* 0Ch */ > +} MptFWUploadTCSGE_t, *pMptFWUploadTCSGE_t; > + > +#define MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM (0x00) > +#define MPI_FW_UPLOAD_ITYPE_FW_FLASH (0x01) > +#define MPI_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02) > +#define MPI_FW_UPLOAD_ITYPE_NVDATA (0x03) > +#define MPI_FW_UPLOAD_ITYPE_BOOTLOADER (0x04) > +#define MPI_FW_UPLOAD_ITYPE_FW_BACKUP (0x05) > +#define MPI_FW_UPLOAD_ITYPE_MANUFACTURING (0x06) > +#define MPI_FW_UPLOAD_ITYPE_CONFIG_1 (0x07) > +#define MPI_FW_UPLOAD_ITYPE_CONFIG_2 (0x08) > +#define MPI_FW_UPLOAD_ITYPE_MEGARAID (0x09) > +#define MPI_FW_UPLOAD_ITYPE_COMPLETE (0x0A) > +#define MPI_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) > + > +/** > + * FW upload request. > + */ > +#pragma pack(1) > +typedef struct MptFWUploadRequest { > + /** Requested image type. */ > + uint8_t u8ImageType; > + /** Reserved. */ > + uint8_t u8Reserved1; > + /** Chain offset. */ > + uint8_t u8ChainOffset; > + /** Function number. */ > + uint8_t u8Function; > + /** Reserved. */ > + uint8_t u8Reserved2[3]; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > + MptFWUploadTCSGE_t TCSge; > + MptSGEntrySimple32 sge; > +} MptFWUploadRequest, *PMptFWUploadRequest; > +#pragma pack() > + > +/** > + * FW upload reply. > + */ > +#pragma pack(1) > +typedef struct MptFWUploadReply { > + /** Image type. */ > + uint8_t u8ImageType; > + /** Reserved. */ > + uint8_t u8Reserved1; > + /** Message length. */ > + uint8_t u8MessageLength; > + /** Function number. */ > + uint8_t u8Function; > + /** Reserved. */ > + uint8_t u8Reserved2[3]; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > + /** Reserved. */ > + uint16_t u16Reserved2; > + /** IO controller status. */ > + uint16_t u16IOCStatus; > + /** IO controller log information. */ > + uint32_t u32IOCLogInfo; > + /** Uploaded image size. */ > + uint32_t u32ActualImageSize; > +} MptFWUploadReply, *PMptFWUploadReply; > +#pragma pack() > + > +/** > + * SCSI IO Request > + */ > +#pragma pack(1) > +typedef struct MptSCSIIORequest { > + /** Target ID */ > + uint8_t u8TargetID; > + /** Bus number */ > + uint8_t u8Bus; > + /** Chain offset */ > + uint8_t u8ChainOffset; > + /** Function number. */ > + uint8_t u8Function; > + /** CDB length. */ > + uint8_t u8CDBLength; > + /** Sense buffer length. */ > + uint8_t u8SenseBufferLength; > + /** Reserved */ > + uint8_t u8Reserved; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > + /** LUN */ > + uint8_t au8LUN[8]; > + /** Control values. */ > + uint32_t u32Control; > + /** The CDB. */ > + uint8_t au8CDB[16]; > + /** Data length. */ > + uint32_t u32DataLength; > + /** Sense buffer low 32bit address. */ > + uint32_t u32SenseBufferLowAddress; > +} MptSCSIIORequest, *PMptSCSIIORequest; > +#pragma pack() > + > +#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(x) (((x) & 0x3000000) >> 24) > +#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE (0x0) > +#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE (0x1) > +#define MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ (0x2) > + > +/** > + * SCSI IO error reply. > + */ > +#pragma pack(1) > +typedef struct MptSCSIIOErrorReply { > + /** Target ID */ > + uint8_t u8TargetID; > + /** Bus number */ > + uint8_t u8Bus; > + /** Message length. */ > + uint8_t u8MessageLength; > + /** Function number. */ > + uint8_t u8Function; > + /** CDB length */ > + uint8_t u8CDBLength; > + /** Sense buffer length */ > + uint8_t u8SenseBufferLength; > + /** Reserved */ > + uint8_t u8Reserved; > + /** Message flags */ > + uint8_t u8MessageFlags; > + /** Message context ID */ > + uint32_t u32MessageContext; > + /** SCSI status. */ > + uint8_t u8SCSIStatus; > + /** SCSI state */ > + uint8_t u8SCSIState; > + /** IO controller status */ > + uint16_t u16IOCStatus; > + /** IO controller log information */ > + uint32_t u32IOCLogInfo; > + /** Transfer count */ > + uint32_t u32TransferCount; > + /** Sense count */ > + uint32_t u32SenseCount; > + /** Response information */ > + uint32_t u32ResponseInfo; > +} MptSCSIIOErrorReply, *PMptSCSIIOErrorReply; > +#pragma pack() > + > +#define MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID (0x01) > +#define MPT_SCSI_IO_ERROR_SCSI_STATE_TERMINATED (0x08) > + > +/** > + * IOC status codes specific to the SCSI I/O error reply. > + */ > +#define MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_BUS (0x0041) > +#define MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_TARGETID (0x0042) > +#define MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE (0x0043) > + > +/** > + * SCSI task management request. > + */ > +#pragma pack(1) > +typedef struct MptSCSITaskManagementRequest { > + /** Target ID */ > + uint8_t u8TargetID; > + /** Bus number */ > + uint8_t u8Bus; > + /** Chain offset */ > + uint8_t u8ChainOffset; > + /** Function number */ > + uint8_t u8Function; > + /** Reserved */ > + uint8_t u8Reserved1; > + /** Task type */ > + uint8_t u8TaskType; > + /** Reserved */ > + uint8_t u8Reserved2; > + /** Message flags */ > + uint8_t u8MessageFlags; > + /** Message context ID */ > + uint32_t u32MessageContext; > + /** LUN */ > + uint8_t au8LUN[8]; > + /** Reserved */ > + uint8_t auReserved[28]; > + /** Task message context ID. */ > + uint32_t u32TaskMessageContext; > +} MptSCSITaskManagementRequest, *PMptSCSITaskManagementRequest; > +#pragma pack() > + > +/** > + * SCSI task management reply. > + */ > +#pragma pack(1) > +typedef struct MptSCSITaskManagementReply { > + /** Target ID */ > + uint8_t u8TargetID; > + /** Bus number */ > + uint8_t u8Bus; > + /** Message length */ > + uint8_t u8MessageLength; > + /** Function number */ > + uint8_t u8Function; > + /** Reserved */ > + uint8_t u8Reserved1; > + /** Task type */ > + uint8_t u8TaskType; > + /** Reserved */ > + uint8_t u8Reserved2; > + /** Message flags */ > + uint8_t u8MessageFlags; > + /** Message context ID */ > + uint32_t u32MessageContext; > + /** Reserved */ > + uint16_t u16Reserved; > + /** IO controller status */ > + uint16_t u16IOCStatus; > + /** IO controller log information */ > + uint32_t u32IOCLogInfo; > + /** Termination count */ > + uint32_t u32TerminationCount; > +} MptSCSITaskManagementReply, *PMptSCSITaskManagementReply; > +#pragma pack() > + > +/** > + * Page address for SAS expander page types. > + */ > +#pragma pack(1) > +typedef union MptConfigurationPageAddressSASExpander { > + struct { > + uint16_t u16Handle; > + uint16_t u16Reserved; > + } Form0And2; > + struct { > + uint16_t u16Handle; > + uint8_t u8PhyNum; > + uint8_t u8Reserved; > + } Form1; > +} MptConfigurationPageAddressSASExpander, > + *PMptConfigurationPageAddressSASExpander; > +#pragma pack() > + > +/** > + * Page address for SAS device page types. > + */ > +#pragma pack(1) > +typedef union MptConfigurationPageAddressSASDevice { > + struct { > + uint16_t u16Handle; > + uint16_t u16Reserved; > + } Form0And2; > + struct { > + uint8_t u8TargetID; > + uint8_t u8Bus; > + uint8_t u8Reserved; > + } Form1; > +} MptConfigurationPageAddressSASDevice, *PMptConfigurationPageAddressSASDevice; > +#pragma pack() > + > +/** > + * Page address for SAS PHY page types. > + */ > +#pragma pack(1) > +typedef union MptConfigurationPageAddressSASPHY { > + struct { > + uint8_t u8PhyNumber; > + uint8_t u8Reserved[3]; > + } Form0; > + struct { > + uint16_t u16Index; > + uint16_t u16Reserved; > + } Form1; > +} MptConfigurationPageAddressSASPHY, *PMptConfigurationPageAddressSASPHY; > +#pragma pack() > + > +/** > + * Page address for SAS Enclosure page types. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageAddressSASEnclosure { > + uint16_t u16Handle; > + uint16_t u16Reserved; > +} MptConfigurationPageAddressSASEnclosure, > + *PMptConfigurationPageAddressSASEnclosure; > +#pragma pack() > + > +/** > + * Union of all possible address types. > + */ > +#pragma pack(1) > +typedef union MptConfigurationPageAddress { > + /** 32bit view. */ > + uint32_t u32PageAddress; > + struct { > + /** Port number to get the configuration page for. */ > + uint8_t u8PortNumber; > + /** Reserved. */ > + uint8_t u8Reserved[3]; > + } MPIPortNumber; > + struct { > + /** Target ID to get the configuration page for. */ > + uint8_t u8TargetID; > + /** Bus number to get the configuration page for. */ > + uint8_t u8Bus; > + /** Reserved. */ > + uint8_t u8Reserved[2]; > + } BusAndTargetId; > + MptConfigurationPageAddressSASExpander SASExpander; > + MptConfigurationPageAddressSASDevice SASDevice; > + MptConfigurationPageAddressSASPHY SASPHY; > + MptConfigurationPageAddressSASEnclosure SASEnclosure; > +} MptConfigurationPageAddress, *PMptConfigurationPageAddress; > +#pragma pack() > + > +#define MPT_CONFIGURATION_PAGE_ADDRESS_GET_SAS_FORM(x) \ > + (((x).u32PageAddress >> 28) & 0x0f) > + > +/** > + * Configuration request > + */ > +#pragma pack(1) > +typedef struct MptConfigurationRequest { > + /** Action code. */ > + uint8_t u8Action; > + /** Reserved. */ > + uint8_t u8Reserved1; > + /** Chain offset. */ > + uint8_t u8ChainOffset; > + /** Function number. */ > + uint8_t u8Function; > + /** Extended page length. */ > + uint16_t u16ExtPageLength; > + /** Extended page type */ > + uint8_t u8ExtPageType; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > + /** Reserved. */ > + uint8_t u8Reserved2[8]; > + /** Version number of the page. */ > + uint8_t u8PageVersion; > + /** Length of the page in 32bit Dwords. */ > + uint8_t u8PageLength; > + /** Page number to access. */ > + uint8_t u8PageNumber; > + /** Type of the page being accessed. */ > + uint8_t u8PageType; > + /** Page type dependent address. */ > + MptConfigurationPageAddress PageAddress; > + /** Simple SG element describing the buffer. */ > + MptSGEntrySimple64 SimpleSGElement; > + uint32_t reserved[4]; > +} MptConfigurationRequest, *PMptConfigurationRequest; > +#pragma pack() > + > +/** Possible action codes. */ > +#define MPT_CONFIGURATION_REQUEST_ACTION_HEADER (0x00) > +#define MPT_CONFIGURATION_REQUEST_ACTION_READ_CURRENT (0x01) > +#define MPT_CONFIGURATION_REQUEST_ACTION_WRITE_CURRENT (0x02) > +#define MPT_CONFIGURATION_REQUEST_ACTION_DEFAULT (0x03) > +#define MPT_CONFIGURATION_REQUEST_ACTION_WRITE_NVRAM (0x04) > +#define MPT_CONFIGURATION_REQUEST_ACTION_READ_DEFAULT (0x05) > +#define MPT_CONFIGURATION_REQUEST_ACTION_READ_NVRAM (0x06) > + > +/** Page type codes. */ > +#define MPT_CONFIGURATION_REQUEST_PAGE_TYPE_IO_UNIT (0x00) > +#define MPT_CONFIGURATION_REQUEST_PAGE_TYPE_IOC (0x01) > +#define MPT_CONFIGURATION_REQUEST_PAGE_TYPE_BIOS (0x02) > +#define MPT_CONFIGURATION_REQUEST_PAGE_TYPE_SCSI_PORT (0x03) > +#define MPT_CONFIGURATION_REQUEST_PAGE_TYPE_EXTENDED (0x0F) > + > +/** > + * Configuration reply. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationReply { > + /** Action code. */ > + uint8_t u8Action; > + /** Reserved. */ > + uint8_t u8Reserved; > + /** Message length. */ > + uint8_t u8MessageLength; > + /** Function number. */ > + uint8_t u8Function; > + /** Extended page length. */ > + uint16_t u16ExtPageLength; > + /** Extended page type */ > + uint8_t u8ExtPageType; > + /** Message flags. */ > + uint8_t u8MessageFlags; > + /** Message context ID. */ > + uint32_t u32MessageContext; > + /** Reserved. */ > + uint16_t u16Reserved; > + /** I/O controller status. */ > + uint16_t u16IOCStatus; > + /** I/O controller log information. */ > + uint32_t u32IOCLogInfo; > + /** Version number of the page. */ > + uint8_t u8PageVersion; > + /** Length of the page in 32bit Dwords. */ > + uint8_t u8PageLength; > + /** Page number to access. */ > + uint8_t u8PageNumber; > + /** Type of the page being accessed. */ > + uint8_t u8PageType; > +} MptConfigurationReply, *PMptConfigurationReply; > +#pragma pack() > + > +/** Additional I/O controller status codes for the configuration reply. */ > +#define MPT_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) > +#define MPT_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) > +#define MPT_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) > +#define MPT_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) > +#define MPT_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) > +#define MPT_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) > + > +/** > + * Union of all possible request messages. > + */ > +typedef union MptRequestUnion { > + MptMessageHdr Header; > + MptIOCInitRequest IOCInit; > + MptIOCFactsRequest IOCFacts; > + MptPortFactsRequest PortFacts; > + MptPortEnableRequest PortEnable; > + MptEventNotificationRequest EventNotification; > + MptSCSIIORequest SCSIIO; > + MptSCSITaskManagementRequest SCSITaskManagement; > + MptConfigurationRequest Configuration; > + MptFWDownloadRequest FWDownload; > + MptFWUploadRequest FWUpload; > +} MptRequestUnion, *PMptRequestUnion; > + > +/** > + * Union of all possible reply messages. > + */ > +typedef union MptReplyUnion { > + /** 16bit view. */ > + uint16_t au16Reply[30]; > + MptDefaultReplyMessage Header; > + MptIOCInitReply IOCInit; > + MptIOCFactsReply IOCFacts; > + MptPortFactsReply PortFacts; > + MptPortEnableReply PortEnable; > + MptEventNotificationReply EventNotification; > + MptSCSIIOErrorReply SCSIIOError; > + MptSCSITaskManagementReply SCSITaskManagement; > + MptConfigurationReply Configuration; > + MptFWDownloadReply FWDownload; > + MptFWUploadReply FWUpload; > +} MptReplyUnion, *PMptReplyUnion; > + > + > +/** > + * Configuration Page attributes. > + */ > +#define MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY (0x00) > +#define MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE (0x10) > +#define MPT_CONFIGURATION_PAGE_ATTRIBUTE_PERSISTENT (0x20) > +#define MPT_CONFIGURATION_PAGE_ATTRIBUTE_PERSISTENT_READONLY (0x30) > + > +#define MPT_CONFIGURATION_PAGE_ATTRIBUTE_GET(u8PageType) ((u8PageType) & 0xf0) > + > +/** > + * Configuration Page types. > + */ > +#define MPT_CONFIGURATION_PAGE_TYPE_IO_UNIT (0x00) > +#define MPT_CONFIGURATION_PAGE_TYPE_IOC (0x01) > +#define MPT_CONFIGURATION_PAGE_TYPE_BIOS (0x02) > +#define MPT_CONFIGURATION_PAGE_TYPE_SCSI_SPI_PORT (0x03) > +#define MPT_CONFIGURATION_PAGE_TYPE_SCSI_SPI_DEVICE (0x04) > +#define MPT_CONFIGURATION_PAGE_TYPE_MANUFACTURING (0x09) > +#define MPT_CONFIGURATION_PAGE_TYPE_EXTENDED (0x0F) > + > +#define MPT_CONFIGURATION_PAGE_TYPE_GET(u8PageType) ((u8PageType) & 0x0f) > + > +/** > + * Extented page types. > + */ > +#define MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASIOUNIT (0x10) > +#define MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASEXPANDER (0x11) > +#define MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASDEVICE (0x12) > +#define MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASPHYS (0x13) > +#define MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_LOG (0x14) > +#define MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_ENCLOSURE (0x15) > + > +/** > + * Configuration Page header - Common to all pages. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageHeader { > + /** Version of the page. */ > + uint8_t u8PageVersion; > + /** The length of the page in 32bit D-Words. */ > + uint8_t u8PageLength; > + /** Number of the page. */ > + uint8_t u8PageNumber; > + /** Type of the page. */ > + uint8_t u8PageType; > +} MptConfigurationPageHeader, *PMptConfigurationPageHeader; > +#pragma pack() > + > +/** > + * Extended configuration page header - Common to all extended pages. > + */ > +#pragma pack(1) > +typedef struct MptExtendedConfigurationPageHeader { > + /** Version of the page. */ > + uint8_t u8PageVersion; > + /** Reserved. */ > + uint8_t u8Reserved1; > + /** Number of the page. */ > + uint8_t u8PageNumber; > + /** Type of the page. */ > + uint8_t u8PageType; > + /** Extended page length. */ > + uint16_t u16ExtPageLength; > + /** Extended page type. */ > + uint8_t u8ExtPageType; > + /** Reserved */ > + uint8_t u8Reserved2; > +} MptExtendedConfigurationPageHeader, *PMptExtendedConfigurationPageHeader; > +#pragma pack() > + > +/** > + * Manufacturing page 0. - Readonly. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageManufacturing0 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[76]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Name of the chip. */ > + uint8_t abChipName[16]; > + /** Chip revision. */ > + uint8_t abChipRevision[8]; > + /** Board name. */ > + uint8_t abBoardName[16]; > + /** Board assembly. */ > + uint8_t abBoardAssembly[16]; > + /** Board tracer number. */ > + uint8_t abBoardTracerNumber[16]; > + } fields; > + } u; > +} MptConfigurationPageManufacturing0, *PMptConfigurationPageManufacturing0; > +#pragma pack() > + > +/** > + * Manufacturing page 1. - Readonly Persistent. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageManufacturing1 { > + /** Union */ > + union { > + /** Byte view */ > + uint8_t abPageData[260]; > + /** Field view */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** VPD info - don't know what belongs here so all zero. */ > + uint8_t abVPDInfo[256]; > + } fields; > + } u; > +} MptConfigurationPageManufacturing1, *PMptConfigurationPageManufacturing1; > +#pragma pack() > + > +/** > + * Manufacturing page 2. - Readonly. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageManufacturing2 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[8]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** PCI Device ID. */ > + uint16_t u16PCIDeviceID; > + /** PCI Revision ID. */ > + uint8_t u8PCIRevisionID; > + /** Reserved. */ > + uint8_t u8Reserved; > + /** Hardware specific settings... */ > + } fields; > + } u; > +} MptConfigurationPageManufacturing2, *PMptConfigurationPageManufacturing2; > +#pragma pack() > + > +/** > + * Manufacturing page 3. - Readonly. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageManufacturing3 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[8]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** PCI Device ID. */ > + uint16_t u16PCIDeviceID; > + /** PCI Revision ID. */ > + uint8_t u8PCIRevisionID; > + /** Reserved. */ > + uint8_t u8Reserved; > + /** Chip specific settings... */ > + } fields; > + } u; > +} MptConfigurationPageManufacturing3, *PMptConfigurationPageManufacturing3; > +#pragma pack() > + > +/** > + * Manufacturing page 4. - Readonly. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageManufacturing4 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[84]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Reserved. */ > + uint32_t u32Reserved; > + /** InfoOffset0. */ > + uint8_t u8InfoOffset0; > + /** Info size. */ > + uint8_t u8InfoSize0; > + /** InfoOffset1. */ > + uint8_t u8InfoOffset1; > + /** Info size. */ > + uint8_t u8InfoSize1; > + /** Size of the inquiry data. */ > + uint8_t u8InquirySize; > + /** Reserved. */ > + uint8_t abReserved[3]; > + /** Inquiry data. */ > + uint8_t abInquiryData[56]; > + /** IS volume settings. */ > + uint32_t u32ISVolumeSettings; > + /** IME volume settings. */ > + uint32_t u32IMEVolumeSettings; > + /** IM volume settings. */ > + uint32_t u32IMVolumeSettings; > + } fields; > + } u; > +} MptConfigurationPageManufacturing4, *PMptConfigurationPageManufacturing4; > +#pragma pack() > + > +/** > + * Manufacturing page 5 - Readonly. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageManufacturing5 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[88]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Base WWID. */ > + uint64_t u64BaseWWID; > + /** Flags */ > + uint8_t u8Flags; > + /** Number of ForceWWID fields in this page. */ > + uint8_t u8NumForceWWID; > + /** Reserved */ > + uint16_t u16Reserved; > + /** Reserved */ > + uint32_t au32Reserved[2]; > + /** ForceWWID entries Maximum of 8 because the SAS > + controller doesn't has more */ > + uint64_t au64ForceWWID[8]; > + } fields; > + } u; > +} MptConfigurationPageManufacturing5, *PMptConfigurationPageManufacturing5; > +#pragma pack() > + > +/** > + * Manufacturing page 6 - Readonly. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageManufacturing6 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[4]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Product specific data - 0 for now */ > + } fields; > + } u; > +} MptConfigurationPageManufacturing6, *PMptConfigurationPageManufacturing6; > +#pragma pack() > + > +/** > + * Manufacutring page 7 - PHY element. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageManufacturing7PHY { > + /** Pinout */ > + uint32_t u32Pinout; > + /** Connector name */ > + uint8_t szConnector[16]; > + /** Location */ > + uint8_t u8Location; > + /** reserved */ > + uint8_t u8Reserved; > + /** Slot */ > + uint16_t u16Slot; > +} MptConfigurationPageManufacturing7PHY, > + *PMptConfigurationPageManufacturing7PHY; > +#pragma pack() > + > +/** > + * Manufacturing page 7 - Readonly. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageManufacturing7 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Reserved */ > + uint32_t au32Reserved[2]; > + /** Flags */ > + uint32_t u32Flags; > + /** Enclosure name */ > + uint8_t szEnclosureName[16]; > + /** Number of PHYs */ > + uint8_t u8NumPhys; > + /** Reserved */ > + uint8_t au8Reserved[3]; > + /** PHY list for the SAS controller - > + variable depending on the number of ports */ > + MptConfigurationPageManufacturing7PHY aPHY[1]; > + } fields; > + } u; > +} MptConfigurationPageManufacturing7, *PMptConfigurationPageManufacturing7; > +#pragma pack() > + > +#define LSILOGICSCSI_MANUFACTURING7_GET_SIZE(ports) \ > + (sizeof(MptConfigurationPageManufacturing7) + ((ports) - 1) * \ > + sizeof(MptConfigurationPageManufacturing7PHY)) > + > +/** Flags for the flags field */ > +#define LSILOGICSCSI_MANUFACTURING7_FLAGS_USE_PROVIDED_INFORMATION (1<<0) > + > +/** Flags for the pinout field */ > +#define LSILOGICSCSI_MANUFACTURING7_PINOUT_UNKNOWN (1<<0) > +#define LSILOGICSCSI_MANUFACTURING7_PINOUT_SFF8482 (1<<1) > +#define LSILOGICSCSI_MANUFACTURING7_PINOUT_SFF8470_LANE1 (1<<8) > +#define LSILOGICSCSI_MANUFACTURING7_PINOUT_SFF8470_LANE2 (1<<9) > +#define LSILOGICSCSI_MANUFACTURING7_PINOUT_SFF8470_LANE3 (1<<10) > +#define LSILOGICSCSI_MANUFACTURING7_PINOUT_SFF8470_LANE4 (1<<11) > +#define LSILOGICSCSI_MANUFACTURING7_PINOUT_SFF8484_LANE1 (1<<16) > +#define LSILOGICSCSI_MANUFACTURING7_PINOUT_SFF8484_LANE2 (1<<17) > +#define LSILOGICSCSI_MANUFACTURING7_PINOUT_SFF8484_LANE3 (1<<18) > +#define LSILOGICSCSI_MANUFACTURING7_PINOUT_SFF8484_LANE4 (1<<19) > + > +/** Flags for the location field */ > +#define LSILOGICSCSI_MANUFACTURING7_LOCATION_UNKNOWN 0x01 > +#define LSILOGICSCSI_MANUFACTURING7_LOCATION_INTERNAL 0x02 > +#define LSILOGICSCSI_MANUFACTURING7_LOCATION_EXTERNAL 0x04 > +#define LSILOGICSCSI_MANUFACTURING7_LOCATION_SWITCHABLE 0x08 > +#define LSILOGICSCSI_MANUFACTURING7_LOCATION_AUTO 0x10 > +#define LSILOGICSCSI_MANUFACTURING7_LOCATION_NOT_PRESENT 0x20 > +#define LSILOGICSCSI_MANUFACTURING7_LOCATION_NOT_CONNECTED 0x80 > + > +/** > + * Manufacturing page 8 - Readonly. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageManufacturing8 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[4]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Product specific information */ > + } fields; > + } u; > +} MptConfigurationPageManufacturing8, *PMptConfigurationPageManufacturing8; > +#pragma pack() > + > +/** > + * Manufacturing page 9 - Readonly. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageManufacturing9 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[4]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Product specific information */ > + } fields; > + } u; > +} MptConfigurationPageManufacturing9, *PMptConfigurationPageManufacturing9; > +#pragma pack() > + > +/** > + * Manufacturing page 10 - Readonly. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageManufacturing10 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[4]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Product specific information */ > + } fields; > + } u; > +} MptConfigurationPageManufacturing10, *PMptConfigurationPageManufacturing10; > +#pragma pack() > + > +/** > + * IO Unit page 0. - Readonly. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageIOUnit0 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[12]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** A unique identifier. */ > + uint64_t u64UniqueIdentifier; > + } fields; > + } u; > +} MptConfigurationPageIOUnit0, *PMptConfigurationPageIOUnit0; > +#pragma pack() > + > +/** > + * IO Unit page 1. - Read/Write. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageIOUnit1 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[8]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Flag whether this is a single function PCI device. */ > + unsigned fSingleFunction:1; > + /** Flag whether all possible paths to a device are mapped. */ > + unsigned fAllPathsMapped:1; > + /** Reserved. */ > + unsigned u4Reserved:4; > + /** Flag whether all RAID functionality is disabled. */ > + unsigned fIntegratedRAIDDisabled:1; > + /** Flag whether 32bit PCI accesses are forced. */ > + unsigned f32BitAccessForced:1; > + /** Reserved. */ > + unsigned abReserved:24; > + } fields; > + } u; > +} MptConfigurationPageIOUnit1, *PMptConfigurationPageIOUnit1; > +#pragma pack() > + > +/** > + * Adapter Ordering. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageIOUnit2AdapterOrdering { > + /** PCI bus number. */ > + unsigned u8PCIBusNumber:8; > + /** PCI device and function number. */ > + unsigned u8PCIDevFn:8; > + /** Flag whether the adapter is embedded. */ > + unsigned fAdapterEmbedded:1; > + /** Flag whether the adapter is enabled. */ > + unsigned fAdapterEnabled:1; > + /** Reserved. */ > + unsigned u6Reserved:6; > + /** Reserved. */ > + unsigned u8Reserved:8; > +} MptConfigurationPageIOUnit2AdapterOrdering, > + *PMptConfigurationPageIOUnit2AdapterOrdering; > +#pragma pack() > + > +/** > + * IO Unit page 2. - Read/Write. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageIOUnit2 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[28]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Reserved. */ > + unsigned fReserved:1; > + /** Flag whether Pause on error is enabled. */ > + unsigned fPauseOnError:1; > + /** Flag whether verbose mode is enabled. */ > + unsigned fVerboseModeEnabled:1; > + /** Set to disable color video. */ > + unsigned fDisableColorVideo:1; > + /** Flag whether int 40h is hooked. */ > + unsigned fNotHookInt40h:1; > + /** Reserved. */ > + unsigned u3Reserved:3; > + /** Reserved. */ > + unsigned abReserved:24; > + /** BIOS version. */ > + uint32_t u32BIOSVersion; > + /** Adapter ordering. */ > + MptConfigurationPageIOUnit2AdapterOrdering aAdapterOrder[4]; > + } fields; > + } u; > +} MptConfigurationPageIOUnit2, *PMptConfigurationPageIOUnit2; > +#pragma pack() > + > +/* > + * IO Unit page 3. - Read/Write. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageIOUnit3 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[8]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Number of GPIO values. */ > + uint8_t u8GPIOCount; > + /** Reserved. */ > + uint8_t abReserved[3]; > + } fields; > + } u; > +} MptConfigurationPageIOUnit3, *PMptConfigurationPageIOUnit3; > +#pragma pack() > + > +/* > + * IO Unit page 4. - Readonly for everyone except the BIOS. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageIOUnit4 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[20]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Reserved */ > + uint32_t u32Reserved; > + /** SG entry describing the Firmware location. */ > + MptSGEntrySimple64 FWImageSGE; > + } fields; > + } u; > +} MptConfigurationPageIOUnit4, *PMptConfigurationPageIOUnit4; > +#pragma pack() > + > +/** > + * IOC page 0. - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageIOC0 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[28]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Total amount of NV memory in bytes. */ > + uint32_t u32TotalNVStore; > + /** Number of free bytes in the NV store. */ > + uint32_t u32FreeNVStore; > + /** PCI vendor ID. */ > + uint16_t u16VendorId; > + /** PCI device ID. */ > + uint16_t u16DeviceId; > + /** PCI revision ID. */ > + uint8_t u8RevisionId; > + /** Reserved. */ > + uint8_t abReserved[3]; > + /** PCI class code. */ > + uint32_t u32ClassCode; > + /** Subsystem vendor Id. */ > + uint16_t u16SubsystemVendorId; > + /** Subsystem Id. */ > + uint16_t u16SubsystemId; > + } fields; > + } u; > +} MptConfigurationPageIOC0, *PMptConfigurationPageIOC0; > +#pragma pack() > + > +/** > + * IOC page 1. - Read/Write > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageIOC1 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[16]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Flag whether reply coalescing is enabled. */ > + unsigned fReplyCoalescingEnabled:1; > + /** Reserved. */ > + unsigned u31Reserved:31; > + /** Coalescing Timeout in microseconds. */ > + unsigned u32CoalescingTimeout:32; > + /** Coalescing depth. */ > + unsigned u8CoalescingDepth:8; > + /** Reserved. */ > + unsigned u8Reserved0:8; > + unsigned u8Reserved1:8; > + unsigned u8Reserved2:8; > + } fields; > + } u; > +} MptConfigurationPageIOC1, *PMptConfigurationPageIOC1; > +#pragma pack() > + > +/** > + * IOC page 2. - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageIOC2 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[12]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Flag whether striping is supported. */ > + unsigned fStripingSupported:1; > + /** Flag whether enhanced mirroring is supported. */ > + unsigned fEnhancedMirroringSupported:1; > + /** Flag whether mirroring is supported. */ > + unsigned fMirroringSupported:1; > + /** Reserved. */ > + unsigned u26Reserved:26; > + /** Flag whether SES is supported. */ > + unsigned fSESSupported:1; > + /** Flag whether SAF-TE is supported. */ > + unsigned fSAFTESupported:1; > + /** Flag whether cross channel volumes are supported. */ > + unsigned fCrossChannelVolumesSupported:1; > + /** Number of active integrated RAID volumes. */ > + unsigned u8NumActiveVolumes:8; > + /** Maximum number of integrated RAID volumes supported. */ > + unsigned u8MaxVolumes:8; > + /** Number of active integrated RAID physical disks. */ > + unsigned u8NumActivePhysDisks:8; > + /** Maximum number of integrated RAID physical disks supported. */ > + unsigned u8MaxPhysDisks:8; > + /** RAID volumes... - not supported. */ > + } fields; > + } u; > +} MptConfigurationPageIOC2, *PMptConfigurationPageIOC2; > +#pragma pack() > + > +/** > + * IOC page 3. - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageIOC3 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[8]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Number of active integrated RAID physical disks. */ > + uint8_t u8NumPhysDisks; > + /** Reserved. */ > + uint8_t abReserved[3]; > + } fields; > + } u; > +} MptConfigurationPageIOC3, *PMptConfigurationPageIOC3; > +#pragma pack() > + > +/** > + * IOC page 4. - Read/Write > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageIOC4 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[8]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Number of SEP entries in this page. */ > + uint8_t u8ActiveSEP; > + /** Maximum number of SEp entries supported. */ > + uint8_t u8MaxSEP; > + /** Reserved. */ > + uint16_t u16Reserved; > + /** SEP entries... - not supported. */ > + } fields; > + } u; > +} MptConfigurationPageIOC4, *PMptConfigurationPageIOC4; > +#pragma pack() > + > +/** > + * IOC page 6. - Read/Write > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageIOC6 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[60]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + uint32_t u32CapabilitiesFlags; > + uint8_t u8MaxDrivesIS; > + uint8_t u8MaxDrivesIM; > + uint8_t u8MaxDrivesIME; > + uint8_t u8Reserved1; > + uint8_t u8MinDrivesIS; > + uint8_t u8MinDrivesIM; > + uint8_t u8MinDrivesIME; > + uint8_t u8Reserved2; > + uint8_t u8MaxGlobalHotSpares; > + uint8_t u8Reserved3; > + uint16_t u16Reserved4; > + uint32_t u32Reserved5; > + uint32_t u32SupportedStripeSizeMapIS; > + uint32_t u32SupportedStripeSizeMapIME; > + uint32_t u32Reserved6; > + uint8_t u8MetadataSize; > + uint8_t u8Reserved7; > + uint16_t u16Reserved8; > + uint16_t u16MaxBadBlockTableEntries; > + uint16_t u16Reserved9; > + uint16_t u16IRNvsramUsage; > + uint16_t u16Reserved10; > + uint32_t u32IRNvsramVersion; > + uint32_t u32Reserved11; > + } fields; > + } u; > +} MptConfigurationPageIOC6, *PMptConfigurationPageIOC6; > +#pragma pack() > + > +/** > + * BIOS page 1 - Read/write. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageBIOS1 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[48]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** BIOS options */ > + uint32_t u32BiosOptions; > + /** IOC settings */ > + uint32_t u32IOCSettings; > + /** Reserved */ > + uint32_t u32Reserved; > + /** Device settings */ > + uint32_t u32DeviceSettings; > + /** Number of devices */ > + uint16_t u16NumberOfDevices; > + /** Expander spinup */ > + uint8_t u8ExpanderSpinup; > + /** Reserved */ > + uint8_t u8Reserved; > + /** I/O timeout of block devices without removable media */ > + uint16_t u16IOTimeoutBlockDevicesNonRM; > + /** I/O timeout sequential */ > + uint16_t u16IOTimeoutSequential; > + /** I/O timeout other */ > + uint16_t u16IOTimeoutOther; > + /** I/O timeout of block devices with removable media */ > + uint16_t u16IOTimeoutBlockDevicesRM; > + } fields; > + } u; > +} MptConfigurationPageBIOS1, *PMptConfigurationPageBIOS1; > +#pragma pack() > + > +#define LSILOGICSCSI_BIOS1_BIOSOPTIONS_BIOS_DISABLE (1<<0) > +#define LSILOGICSCSI_BIOS1_BIOSOPTIONS_SCAN_FROM_HIGH_TO_LOW (1<<1) > +#define LSILOGICSCSI_BIOS1_BIOSOPTIONS_BIOS_EXTENDED_SAS_SUPPORT (1<<8) > +#define LSILOGICSCSI_BIOS1_BIOSOPTIONS_BIOS_EXTENDED_FC_SUPPORT (1<<9) > +#define LSILOGICSCSI_BIOS1_BIOSOPTIONS_BIOS_EXTENDED_SPI_SUPPORT (1<<10) > + > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_ALTERNATE_CHS (1<<3) > + > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_ADAPTER_SUPPORT_SET(x) ((x) << 4) > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_ADAPTER_SUPPORT_DISABLED 0x00 > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_ADAPTER_SUPPORT_BIOS_ONLY 0x01 > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_ADAPTER_SUPPORT_OS_ONLY 0x02 > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_ADAPTER_SUPPORT_BOT 0x03 > + > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_REMOVABLE_MEDIA_SET(x) ((x) << 6) > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_REMOVABLE_MEDIA_NO_INT13H 0x00 > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_REMOVABLE_BOOT_MEDIA_INT13H 0x01 > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_REMOVABLE_MEDIA_INT13H 0x02 > + > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_SPINUP_DELAY_SET(x) \ > + ((x & 0xF) << 8) > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_SPINUP_DELAY_GET(x) \ > + ((x >> 8) & 0x0F) > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_MAX_TARGET_SPINUP_SET(x) \ > + ((x & 0xF) << 12) > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_MAX_TARGET_SPINUP_GET(x) \ > + ((x >> 12) & 0x0F) > + > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_BOOT_PREFERENCE_SET(x) \ > + (((x) & 0x3) << 16) > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_BOOT_PREFERENCE_ENCLOSURE 0x0 > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_BOOT_PREFERENCE_SAS_ADDRESS 0x1 > + > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_DIRECT_ATTACH_SPINUP_MODE_ALL (1<<18) > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_AUTO_PORT_ENABLE (1<<19) > + > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_PORT_ENABLE_REPLY_DELAY_SET(x) \ > + (((x) & 0xF) << 20) > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_PORT_ENABLE_REPLY_DELAY_GET(x) \ > + ((x >> 20) & 0x0F) > + > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_PORT_ENABLE_SPINUP_DELAY_SET(x) \ > + (((x) & 0xF) << 24) > +#define LSILOGICSCSI_BIOS1_IOCSETTINGS_PORT_ENABLE_SPINUP_DELAY_GET(x) \ > + ((x >> 24) & 0x0F) > + > +#define LSILOGICSCSI_BIOS1_DEVSETTINGS_DISABLE_LUN_SCANS (1<<0) > +#define LSILOGICSCSI_BIOS1_DEVSETTINGS_DISABLE_LUN_SCANS_NON_REMOVABLE_DEVS \ > + (1<<1) > +#define LSILOGICSCSI_BIOS1_DEVSETTINGS_DISABLE_LUN_SCANS_REMOVABLE_DEVS (1<<2) > +#define LSILOGICSCSI_BIOS1_DEVSETTINGS_DISABLE_LUN_SCANS2 (1<<3) > +#define LSILOGICSCSI_BIOS1_DEVSETTINGS_DISABLE_SMART_POLLING (1<<4) > + > +#define LSILOGICSCSI_BIOS1_EXPANDERSPINUP_SPINUP_DELAY_SET(x) ((x) & 0x0F) > +#define LSILOGICSCSI_BIOS1_EXPANDERSPINUP_SPINUP_DELAY_GET(x) ((x) & 0x0F) > +#define LSILOGICSCSI_BIOS1_EXPANDERSPINUP_MAX_SPINUP_DELAY_SET(x) \ > + (((x) & 0x0F) << 4) > +#define LSILOGICSCSI_BIOS1_EXPANDERSPINUP_MAX_SPINUP_DELAY_GET(x) \ > + ((x >> 4) & 0x0F) > + > +/** > + * BIOS page 2 - Read/write. > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageBIOS2 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[384]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Reserved */ > + uint32_t au32Reserved[6]; > + /** Format of the boot device field. */ > + uint8_t u8BootDeviceForm; > + /** Previous format of the boot device field. */ > + uint8_t u8PrevBootDeviceForm; > + /** Reserved */ > + uint16_t u16Reserved; > + /** Boot device fields - dependent on the format */ > + union { > + /** Device for AdapterNumber:Bus:Target:LUN */ > + struct { > + /** Target ID */ > + uint8_t u8TargetID; > + /** Bus */ > + uint8_t u8Bus; > + /** Adapter Number */ > + uint8_t u8AdapterNumber; > + /** Reserved */ > + uint8_t u8Reserved; > + /** Reserved */ > + uint32_t au32Reserved[3]; > + /** LUN */ > + uint32_t aLUN[5]; > + /** Reserved */ > + uint32_t au32Reserved2[56]; > + } AdapterNumberBusTargetLUN; > + /** Device for PCIAddress:Bus:Target:LUN */ > + struct { > + /** Target ID */ > + uint8_t u8TargetID; > + /** Bus */ > + uint8_t u8Bus; > + /** Adapter Number */ > + uint16_t u16PCIAddress; > + /** Reserved */ > + uint32_t au32Reserved[3]; > + /** LUN */ > + uint32_t aLUN[5]; > + /** Reserved */ > + uint32_t au32Reserved2[56]; > + } PCIAddressBusTargetLUN; > + /** Device for PCISlotNo:Bus:Target:LUN */ > + struct { > + /** Target ID */ > + uint8_t u8TargetID; > + /** Bus */ > + uint8_t u8Bus; > + /** PCI Slot Number */ > + uint8_t u16PCISlotNo; > + /** Reserved */ > + uint32_t au32Reserved[3]; > + /** LUN */ > + uint32_t aLUN[5]; > + /** Reserved */ > + uint32_t au32Reserved2[56]; > + } PCIAddressBusSlotLUN; > + /** Device for FC channel world wide name */ > + struct { > + /** World wide port name low */ > + uint32_t u32WorldWidePortNameLow; > + /** World wide port name high */ > + uint32_t u32WorldWidePortNameHigh; > + /** Reserved */ > + uint32_t au32Reserved[3]; > + /** LUN */ > + uint32_t aLUN[5]; > + /** Reserved */ > + uint32_t au32Reserved2[56]; > + } FCWorldWideName; > + /** Device for FC channel world wide name */ > + struct { > + /** SAS address */ > + SASADDRESS SASAddress; > + /** Reserved */ > + uint32_t au32Reserved[3]; > + /** LUN */ > + uint32_t aLUN[5]; > + /** Reserved */ > + uint32_t au32Reserved2[56]; > + } SASWorldWideName; > + /** Device for Enclosure/Slot */ > + struct { > + /** Enclosure logical ID */ > + uint64_t u64EnclosureLogicalID; > + /** Reserved */ > + uint32_t au32Reserved[3]; > + /** LUN */ > + uint32_t aLUN[5]; > + /** Reserved */ > + uint32_t au32Reserved2[56]; > + } EnclosureSlot; > + } BootDevice; > + } fields; > + } u; > +} MptConfigurationPageBIOS2, *PMptConfigurationPageBIOS2; > +#pragma pack() > + > +#define LSILOGICSCSI_BIOS2_BOOT_DEVICE_FORM_SET(x) ((x) & 0x0F) > +#define LSILOGICSCSI_BIOS2_BOOT_DEVICE_FORM_FIRST 0x0 > +#define LSILOGICSCSI_BIOS2_BOOT_DEVICE_FORM_ADAPTER_BUS_TARGET_LUN 0x1 > +#define LSILOGICSCSI_BIOS2_BOOT_DEVICE_FORM_PCIADDR_BUS_TARGET_LUN 0x2 > +#define LSILOGICSCSI_BIOS2_BOOT_DEVICE_FORM_PCISLOT_BUS_TARGET_LUN 0x3 > +#define LSILOGICSCSI_BIOS2_BOOT_DEVICE_FORM_FC_WWN 0x4 > +#define LSILOGICSCSI_BIOS2_BOOT_DEVICE_FORM_SAS_WWN 0x5 > +#define LSILOGICSCSI_BIOS2_BOOT_DEVICE_FORM_ENCLOSURE_SLOT 0x6 > + > +/** > + * BIOS page 4 - Read/Write (Where is 3? - not defined in the spec) > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageBIOS4 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[12]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Reassignment Base WWID */ > + uint64_t u64ReassignmentBaseWWID; > + } fields; > + } u; > +} MptConfigurationPageBIOS4, *PMptConfigurationPageBIOS4; > +#pragma pack() > + > +/** > + * SCSI-SPI port page 0. - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSCSISPIPort0 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[12]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /* Flag whether this port is information unit transfers capable. */ > + unsigned fInformationUnitTransfersCapable:1; > + /* Flag whether the port is DT (Dual Transfer) capable. */ > + unsigned fDTCapable:1; > + /* Flag whether the port is QAS capable. */ > + unsigned fQASCapable:1; > + /* Reserved. */ > + unsigned u5Reserved1:5; > + /* Minimum Synchronous transfer period. */ > + unsigned u8MinimumSynchronousTransferPeriod:8; > + /* Maximum synchronous offset. */ > + unsigned u8MaximumSynchronousOffset:8; > + /** Reserved. */ > + unsigned u5Reserved2:5; > + /* Flag whether indicating the width of the bus - > + 0 narrow and 1 for wide. */ > + unsigned fWide:1; > + /* Reserved */ > + unsigned fReserved:1; > + /* Flag whether the port is AIP capable. */ > + unsigned fAIPCapable:1; > + /* Signaling Type. */ > + unsigned u2SignalingType:2; > + /* Reserved. */ > + unsigned u30Reserved:30; > + } fields; > + } u; > +} MptConfigurationPageSCSISPIPort0, *PMptConfigurationPageSCSISPIPort0; > +#pragma pack() > + > +/** > + * SCSI-SPI port page 1. - Read/Write > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSCSISPIPort1 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[12]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** The SCSI ID of the port. */ > + uint8_t u8SCSIID; > + /** Reserved. */ > + uint8_t u8Reserved; > + /** Port response IDs Bit mask field. */ > + uint16_t u16PortResponseIDsBitmask; > + /** Value for the on BUS timer. */ > + uint32_t u32OnBusTimerValue; > + } fields; > + } u; > +} MptConfigurationPageSCSISPIPort1, *PMptConfigurationPageSCSISPIPort1; > +#pragma pack() > + > +/** > + * Device settings for one device. > + */ > +#pragma pack(1) > +typedef struct MptDeviceSettings { > + /** Timeout for I/O in seconds. */ > + unsigned u8Timeout:8; > + /** Minimum synchronous factor. */ > + unsigned u8SyncFactor:8; > + /** Flag whether disconnect is enabled. */ > + unsigned fDisconnectEnable:1; > + /** Flag whether Scan ID is enabled. */ > + unsigned fScanIDEnable:1; > + /** Flag whether Scan LUNs is enabled. */ > + unsigned fScanLUNEnable:1; > + /** Flag whether tagged queuing is enabled. */ > + unsigned fTaggedQueuingEnabled:1; > + /** Flag whether wide is enabled. */ > + unsigned fWideDisable:1; > + /** Flag whether this device is bootable. */ > + unsigned fBootChoice:1; > + /** Reserved. */ > + unsigned u10Reserved:10; > +} MptDeviceSettings, *PMptDeviceSettings; > +#pragma pack() > + > +/** > + * SCSI-SPI port page 2. - Read/Write for the BIOS > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSCSISPIPort2 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[76]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Flag indicating the bus scan order. */ > + unsigned fBusScanOrderHighToLow:1; > + /** Reserved. */ > + unsigned fReserved:1; > + /** Flag whether SCSI Bus resets are avoided. */ > + unsigned fAvoidSCSIBusResets:1; > + /** Flag whether alternate CHS is used. */ > + unsigned fAlternateCHS:1; > + /** Flag whether termination is disabled. */ > + unsigned fTerminationDisabled:1; > + /** Reserved. */ > + unsigned u27Reserved:27; > + /** Host SCSI ID. */ > + unsigned u4HostSCSIID:4; > + /** Initialize HBA. */ > + unsigned u2InitializeHBA:2; > + /** Removeable media setting. */ > + unsigned u2RemovableMediaSetting:2; > + /** Spinup delay. */ > + unsigned u4SpinupDelay:4; > + /** Negotiating settings. */ > + unsigned u2NegotitatingSettings:2; > + /** Reserved. */ > + unsigned u18Reserved:18; > + /** Device Settings. */ > + MptDeviceSettings aDeviceSettings[16]; > + } fields; > + } u; > +} MptConfigurationPageSCSISPIPort2, *PMptConfigurationPageSCSISPIPort2; > +#pragma pack() > + > +/** > + * SCSI-SPI device page 0. - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSCSISPIDevice0 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[12]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Negotiated Parameters. */ > + /** Information Units enabled. */ > + unsigned fInformationUnitsEnabled:1; > + /** Dual Transfers Enabled. */ > + unsigned fDTEnabled:1; > + /** QAS enabled. */ > + unsigned fQASEnabled:1; > + /** Reserved. */ > + unsigned u5Reserved1:5; > + /** Synchronous Transfer period. */ > + unsigned u8NegotiatedSynchronousTransferPeriod:8; > + /** Synchronous offset. */ > + unsigned u8NegotiatedSynchronousOffset:8; > + /** Reserved. */ > + unsigned u5Reserved2:5; > + /** Width - 0 for narrow and 1 for wide. */ > + unsigned fWide:1; > + /** Reserved. */ > + unsigned fReserved:1; > + /** AIP enabled. */ > + unsigned fAIPEnabled:1; > + /** Flag whether negotiation occurred. */ > + unsigned fNegotationOccured:1; > + /** Flag whether a SDTR message was rejected. */ > + unsigned fSDTRRejected:1; > + /** Flag whether a WDTR message was rejected. */ > + unsigned fWDTRRejected:1; > + /** Flag whether a PPR message was rejected. */ > + unsigned fPPRRejected:1; > + /** Reserved. */ > + unsigned u28Reserved:28; > + } fields; > + } u; > +} MptConfigurationPageSCSISPIDevice0, *PMptConfigurationPageSCSISPIDevice0; > +#pragma pack() > + > +/** > + * SCSI-SPI device page 1. - Read/Write > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSCSISPIDevice1 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[16]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Requested Parameters. */ > + /** Information Units enable. */ > + bool fInformationUnitsEnable:1; > + /** Dual Transfers Enable. */ > + bool fDTEnable:1; > + /** QAS enable. */ > + bool fQASEnable:1; > + /** Reserved. */ > + unsigned u5Reserved1:5; > + /** Synchronous Transfer period. */ > + unsigned u8NegotiatedSynchronousTransferPeriod:8; > + /** Synchronous offset. */ > + unsigned u8NegotiatedSynchronousOffset:8; > + /** Reserved. */ > + unsigned u5Reserved2:5; > + /** Width - 0 for narrow and 1 for wide. */ > + bool fWide:1; > + /** Reserved. */ > + bool fReserved1:1; > + /** AIP enable. */ > + bool fAIPEnable:1; > + /** Reserved. */ > + bool fReserved2:1; > + /** WDTR disallowed. */ > + bool fWDTRDisallowed:1; > + /** SDTR disallowed. */ > + bool fSDTRDisallowed:1; > + /** Reserved. */ > + unsigned u29Reserved:29; > + } fields; > + } u; > +} MptConfigurationPageSCSISPIDevice1, *PMptConfigurationPageSCSISPIDevice1; > +#pragma pack() > + > +/** > + * SCSI-SPI device page 2. - Read/Write > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSCSISPIDevice2 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[16]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Reserved. */ > + unsigned u4Reserved:4; > + /** ISI enable. */ > + unsigned fISIEnable:1; > + /** Secondary driver enable. */ > + unsigned fSecondaryDriverEnable:1; > + /** Reserved. */ > + unsigned fReserved:1; > + /** Slew create controller. */ > + unsigned u3SlewRateControler:3; > + /** Primary drive strength controller. */ > + unsigned u3PrimaryDriveStrengthControl:3; > + /** Secondary drive strength controller. */ > + unsigned u3SecondaryDriveStrengthControl:3; > + /** Reserved. */ > + unsigned u12Reserved:12; > + /** XCLKH_ST. */ > + unsigned fXCLKH_ST:1; > + /** XCLKS_ST. */ > + unsigned fXCLKS_ST:1; > + /** XCLKH_DT. */ > + unsigned fXCLKH_DT:1; > + /** XCLKS_DT. */ > + unsigned fXCLKS_DT:1; > + /** Parity pipe select. */ > + unsigned u2ParityPipeSelect:2; > + /** Reserved. */ > + unsigned u30Reserved:30; > + /** Data bit pipeline select. */ > + unsigned u32DataPipelineSelect:32; > + } fields; > + } u; > +} MptConfigurationPageSCSISPIDevice2, *PMptConfigurationPageSCSISPIDevice2; > +#pragma pack() > + > +/** > + * SCSI-SPI device page 3 (Revision G). - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSCSISPIDevice3 { > + /** Union. */ > + union { > + /** Byte view. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptConfigurationPageHeader Header; > + /** Number of times the IOC rejected a message because > + it doesn't support the operation. */ > + uint16_t u16MsgRejectCount; > + /** Number of times the SCSI bus entered an invalid > + operation state. */ > + uint16_t u16PhaseErrorCount; > + /** Number of parity errors. */ > + uint16_t u16ParityCount; > + /** Reserved. */ > + uint16_t u16Reserved; > + } fields; > + } u; > +} MptConfigurationPageSCSISPIDevice3, *PMptConfigurationPageSCSISPIDevice3; > +#pragma pack() > + > +/** > + * PHY entry for the SAS I/O unit page 0 > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASIOUnit0PHY { > + /** Port number */ > + uint8_t u8Port; > + /** Port flags */ > + uint8_t u8PortFlags; > + /** Phy flags */ > + uint8_t u8PhyFlags; > + /** negotiated link rate */ > + uint8_t u8NegotiatedLinkRate; > + /** Controller phy device info */ > + uint32_t u32ControllerPhyDeviceInfo; > + /** Attached device handle */ > + uint16_t u16AttachedDevHandle; > + /** Controller device handle */ > + uint16_t u16ControllerDevHandle; > + /** Discovery status */ > + uint32_t u32DiscoveryStatus; > +} MptConfigurationPageSASIOUnit0PHY, *PMptConfigurationPageSASIOUnit0PHY; > +#pragma pack() > + > +/** > + * SAS I/O Unit page 0 - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASIOUnit0 { > + /** Union. */ > + union { > + /** Byte view - variable. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptExtendedConfigurationPageHeader ExtHeader; > + /** Nvdata version default */ > + uint16_t u16NvdataVersionDefault; > + /** Nvdata version persistent */ > + uint16_t u16NvdataVersionPersistent; > + /** Number of physical ports */ > + uint8_t u8NumPhys; > + /** Reserved */ > + uint8_t au8Reserved[3]; > + /** Content for each physical port - > + variable depending on the amount of ports. */ > + MptConfigurationPageSASIOUnit0PHY aPHY[1]; > + } fields; > + } u; > +} MptConfigurationPageSASIOUnit0, *PMptConfigurationPageSASIOUnit0; > +#pragma pack() > + > +#define LSILOGICSCSI_SASIOUNIT0_GET_SIZE(ports) \ > + (sizeof(MptConfigurationPageSASIOUnit0) + ((ports) - 1) * \ > + sizeof(MptConfigurationPageSASIOUnit0PHY)) > + > +#define LSILOGICSCSI_SASIOUNIT0_PORT_CONFIGURATION_AUTO (1<<0) > +#define LSILOGICSCSI_SASIOUNIT0_PORT_TARGET_IOC (1<<2) > +#define LSILOGICSCSI_SASIOUNIT0_PORT_DISCOVERY_IN_STATUS (1<<3) > + > +#define LSILOGICSCSI_SASIOUNIT0_PHY_RX_INVERTED (1<<0) > +#define LSILOGICSCSI_SASIOUNIT0_PHY_TX_INVERTED (1<<1) > +#define LSILOGICSCSI_SASIOUNIT0_PHY_DISABLED (1<<2) > + > +#define LSILOGICSCSI_SASIOUNIT0_NEGOTIATED_RATE_SET(x) ((x) & 0x0F) > +#define LSILOGICSCSI_SASIOUNIT0_NEGOTIATED_RATE_GET(x) ((x) & 0x0F) > +#define LSILOGICSCSI_SASIOUNIT0_NEGOTIATED_RATE_UNKNOWN 0x00 > +#define LSILOGICSCSI_SASIOUNIT0_NEGOTIATED_RATE_DISABLED 0x01 > +#define LSILOGICSCSI_SASIOUNIT0_NEGOTIATED_RATE_FAILED 0x02 > +#define LSILOGICSCSI_SASIOUNIT0_NEGOTIATED_RATE_SATA_OOB 0x03 > +#define LSILOGICSCSI_SASIOUNIT0_NEGOTIATED_RATE_15GB 0x08 > +#define LSILOGICSCSI_SASIOUNIT0_NEGOTIATED_RATE_30GB 0x09 > + > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_SET(x) ((x) & 0x3) > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_NO 0x0 > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_END 0x1 > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_EDGE_EXPANDER 0x2 > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_FANOUT_EXPANDER 0x3 > + > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_SATA_HOST (1<<3) > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_SMP_INITIATOR (1<<4) > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_STP_INITIATOR (1<<5) > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_SSP_INITIATOR (1<<6) > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_SATA (1<<7) > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_SMP_TARGET (1<<8) > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_STP_TARGET (1<<9) > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_SSP_TARGET (1<<10) > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_DIRECT_ATTACHED (1<<11) > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_LSI (1<<12) > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_ATAPI_DEVICE (1<<13) > +#define LSILOGICSCSI_SASIOUNIT0_DEVICE_SEP_DEVICE (1<<14) > + > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_LOOP (1<<0) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_UNADDRESSABLE (1<<1) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_SAME_SAS_ADDR (1<<2) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_EXPANDER_ERROR (1<<3) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_SMP_TIMEOUT (1<<4) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_EXP_ROUTE_OOE (1<<5) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_EXP_ROUTE_IDX (1<<6) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_SMP_FUNC_FAILED (1<<7) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_SMP_CRC_ERROR (1<<8) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_SUBTRSCTIVE_LNK (1<<9) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_TBL_LNK (1<<10) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_UNSUPPORTED_DEV (1<<11) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_MAX_SATA_TGTS (1<<12) > +#define LSILOGICSCSI_SASIOUNIT0_DISCOVERY_STATUS_MULT_CTRLS (1<<13) > + > +/** > + * PHY entry for the SAS I/O unit page 1 > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASIOUnit1PHY { > + /** Port number */ > + uint8_t u8Port; > + /** Port flags */ > + uint8_t u8PortFlags; > + /** Phy flags */ > + uint8_t u8PhyFlags; > + /** Max link rate */ > + uint8_t u8MaxMinLinkRate; > + /** Controller phy device info */ > + uint32_t u32ControllerPhyDeviceInfo; > + /** Maximum target port connect time */ > + uint16_t u16MaxTargetPortConnectTime; > + /** Reserved */ > + uint16_t u16Reserved; > +} MptConfigurationPageSASIOUnit1PHY, *PMptConfigurationPageSASIOUnit1PHY; > +#pragma pack() > + > +/** > + * SAS I/O Unit page 1 - Read/Write > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASIOUnit1 { > + /** Union. */ > + union { > + /** Byte view - variable. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptExtendedConfigurationPageHeader ExtHeader; > + /** Control flags */ > + uint16_t u16ControlFlags; > + /** maximum number of SATA targets */ > + uint16_t u16MaxNumSATATargets; > + /** additional control flags */ > + uint16_t u16AdditionalControlFlags; > + /** Reserved */ > + uint16_t u16Reserved; > + /** Number of PHYs */ > + uint8_t u8NumPhys; > + /** maximum SATA queue depth */ > + uint8_t u8SATAMaxQDepth; > + /** Delay for reporting missing devices. */ > + uint8_t u8ReportDeviceMissingDelay; > + /** I/O device missing delay */ > + uint8_t u8IODeviceMissingDelay; > + /** Content for each physical port - > + variable depending on the number of ports */ > + MptConfigurationPageSASIOUnit1PHY aPHY[1]; > + } fields; > + } u; > +} MptConfigurationPageSASIOUnit1, *PMptConfigurationPageSASIOUnit1; > +#pragma pack() > + > +#define LSILOGICSCSI_SASIOUNIT1_GET_SIZE(ports) \ > + (sizeof(MptConfigurationPageSASIOUnit1) + ((ports) - 1) * \ > + sizeof(MptConfigurationPageSASIOUnit1PHY)) > + > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_CLEAR_SATA_AFFILIATION (1<<0) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_FIRST_LEVEL_DISCOVERY_ONLY (1<<1) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_SUBTRACTIVE_LNK_ILLEGAL (1<<2) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_IOC_ENABLE_HIGH_PHY (1<<3) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED (1<<4) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED (1<<5) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED (1<<6) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_SATA_LBA48_REQUIRED (1<<7) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_SATA_INIT_POSTPONED (1<<8) > + > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_DEVICE_SUPPORT_SET(x) \ > + (((x) & 0x3) << 9) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_DEVICE_SUPPORT_GET(x) \ > + (((x) >> 9) & 0x3) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_DEVICE_SUPPORT_SAS_AND_SATA 0x00 > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_DEVICE_SUPPORT_SAS 0x01 > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_DEVICE_SUPPORT_SATA 0x02 > + > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_SATA_EXP_ADDR (1<<11) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_SATA_SETTINGS_PRESERV_REQUIRED (1<<12) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_SATA_LIMIT_RATE_15GB (1<<13) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_SATA_LIMIT_RATE_30GB (1<<14) > +#define LSILOGICSCSI_SASIOUNIT1_CONTROL_SAS_SELF_TEST_ENABLED (1<<15) > + > +#define LSILOGICSCSI_SASIOUNIT1_ADDITIONAL_CONTROL_TBL_LNKS_ALLOW (1<<0) > +#define LSILOGICSCSI_SASIOUNIT1_ADDITIONAL_CONTROL_SATA_RST_NO_AFFIL (1<<1) > +#define LSILOGICSCSI_SASIOUNIT1_ADDITIONAL_CONTROL_SATA_RST_SELF_AFFIL (1<<2) > +#define LSILOGICSCSI_SASIOUNIT1_ADDITIONAL_CONTROL_SATA_RST_OTHER_AFFIL (1<<3) > +#define LSILOGICSCSI_SASIOUNIT1_ADDITIONAL_CONTROL_SATA_RST_PORT_EN_ONLY (1<<4) > +#define LSILOGICSCSI_SASIOUNIT1_ADDITIONAL_CONTROL_HIDE_NON_ZERO_PHYS (1<<5) > +#define LSILOGICSCSI_SASIOUNIT1_ADDITIONAL_CONTROL_SATA_ASYNC_NOTIF (1<<6) > +#define LSILOGICSCSI_SASIOUNIT1_ADDITIONAL_CONTROL_MULT_PORTS_ILL_SAME_DOMAIN \ > + (1<<7) > + > +#define LSILOGICSCSI_SASIOUNIT1_MISSING_DEVICE_DELAY_UNITS_16_SEC (1<<7) > +#define LSILOGICSCSI_SASIOUNIT1_MISSING_DEVICE_DELAY_SET(x) ((x) & 0x7F) > +#define LSILOGICSCSI_SASIOUNIT1_MISSING_DEVICE_DELAY_GET(x) ((x) & 0x7F) > + > +#define LSILOGICSCSI_SASIOUNIT1_PORT_CONFIGURATION_AUTO (1<<0) > +#define LSILOGICSCSI_SASIOUNIT1_PORT_CONFIGURATION_IOC1 (1<<2) > + > +#define LSILOGICSCSI_SASIOUNIT1_PHY_RX_INVERT (1<<0) > +#define LSILOGICSCSI_SASIOUNIT1_PHY_TX_INVERT (1<<1) > +#define LSILOGICSCSI_SASIOUNIT1_PHY_DISABLE (1<<2) > + > +#define LSILOGICSCSI_SASIOUNIT1_LINK_RATE_MIN_SET(x) ((x) & 0xF) > +#define LSILOGICSCSI_SASIOUNIT1_LINK_RATE_MIN_GET(x) ((x) & 0xF) > +#define LSILOGICSCSI_SASIOUNIT1_LINK_RATE_MAX_SET(x) (((x) & 0xF)<<4) > +#define LSILOGICSCSI_SASIOUNIT1_LINK_RATE_MAX_GET(x) ((x >> 4) & 0xF) > +#define LSILOGICSCSI_SASIOUNIT1_LINK_RATE_15GB 0x8 > +#define LSILOGICSCSI_SASIOUNIT1_LINK_RATE_30GB 0x9 > + > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_TYPE_SET(x) ((x) & 0x3) > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_TYPE_GET(x) ((x) & 0x3) > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_TYPE_NO 0x0 > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_TYPE_END 0x1 > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_TYPE_EDGE_EXPANDER 0x2 > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_TYPE_FANOUT_EXPANDER 0x3 > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_SMP_INITIATOR (1<<4) > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_STP_INITIATOR (1<<5) > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_SSP_INITIATOR (1<<6) > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_SMP_TARGET (1<<8) > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_STP_TARGET (1<<9) > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_SSP_TARGET (1<<10) > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_DIRECT_ATTACHED (1<<11) > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_LSI (1<<12) > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_ATAPI (1<<13) > +#define LSILOGICSCSI_SASIOUNIT1_CTL_PHY_DEVICE_SEP (1<<14) > + > +/** > + * SAS I/O unit page 2 - Read/Write > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASIOUnit2 { > + /** Union. */ > + union { > + /** Byte view - variable. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptExtendedConfigurationPageHeader ExtHeader; > + /** Device numbers per enclosure */ > + uint8_t u8NumDevsPerEnclosure; > + /** Boot device wait time */ > + uint8_t u8BootDeviceWaitTime; > + /** Reserved */ > + uint16_t u16Reserved; > + /** Maximum number of persistent Bus and target ID mappings */ > + uint16_t u16MaxPersistentIDs; > + /** Number of persistent IDs used */ > + uint16_t u16NumPersistentIDsUsed; > + /** Status */ > + uint8_t u8Status; > + /** Flags */ > + uint8_t u8Flags; > + /** Maximum number of physical mapped IDs */ > + uint16_t u16MaxNumPhysicalMappedIDs; > + } fields; > + } u; > +} MptConfigurationPageSASIOUnit2, *PMptConfigurationPageSASIOUnit2; > +#pragma pack() > + > +#define LSILOGICSCSI_SASIOUNIT2_STATUS_PERSISTENT_MAP_TBL_FULL (1<<0) > +#define LSILOGICSCSI_SASIOUNIT2_STATUS_PERSISTENT_MAP_DISABLED (1<<1) > +#define LSILOGICSCSI_SASIOUNIT2_STATUS_PERSISTENT_ENC_DEV_UNMAPPED (1<<2) > +#define LSILOGICSCSI_SASIOUNIT2_STATUS_PERSISTENT_DEV_LIMIT_EXCEEDED (1<<3) > + > +#define LSILOGICSCSI_SASIOUNIT2_FLAGS_PERSISTENT_MAP_DISABLE (1<<0) > +#define LSILOGICSCSI_SASIOUNIT2_FLAGS_PERSISTENT_PHYS_MAP_MODE_SET(x) \ > + ((x & 0x7) << 1) > +#define LSILOGICSCSI_SASIOUNIT2_FLAGS_PERSISTENT_PHYS_MAP_MODE_GET(x) \ > + ((x >> 1) & 0x7) > +#define LSILOGICSCSI_SASIOUNIT2_FLAGS_PERSISTENT_PHYS_MAP_MODE_NO 0x0 > +#define LSILOGICSCSI_SASIOUNIT2_FLAGS_PERSISTENT_PHYS_MAP_MODE_DIRECT_ATTACHED\ > + 0x1 > +#define LSILOGICSCSI_SASIOUNIT2_FLAGS_PERSISTENT_PHYS_MAP_MODE_ENC 0x2 > +#define LSILOGICSCSI_SASIOUNIT2_FLAGS_PERSISTENT_PHYS_MAP_MODE_HOST 0x7 > +#define LSILOGICSCSI_SASIOUNIT2_FLAGS_RESERVE_TARGET_ID_ZERO (1<<4) > +#define LSILOGICSCSI_SASIOUNIT2_FLAGS_START_SLOT_NUMBER_ONE (1<<5) > + > +/** > + * SAS I/O unit page 3 - Read/Write > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASIOUnit3 { > + /** Union. */ > + union { > + /** Byte view - variable. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptExtendedConfigurationPageHeader ExtHeader; > + /** Reserved */ > + uint32_t u32Reserved; > + uint32_t u32MaxInvalidDwordCount; > + uint32_t u32InvalidDwordCountTime; > + uint32_t u32MaxRunningDisparityErrorCount; > + uint32_t u32RunningDisparityErrorTime; > + uint32_t u32MaxLossDwordSynchCount; > + uint32_t u32LossDwordSynchCountTime; > + uint32_t u32MaxPhysResetProblemCount; > + uint32_t u32PhyResetProblemTime; > + } fields; > + } u; > +} MptConfigurationPageSASIOUnit3, *PMptConfigurationPageSASIOUnit3; > +#pragma pack() > + > +/** > + * SAS PHY page 0 - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASPHY0 { > + /** Union. */ > + union { > + /** Byte view - variable. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptExtendedConfigurationPageHeader ExtHeader; > + /** Owner dev handle. */ > + uint16_t u16OwnerDevHandle; > + /** Reserved */ > + uint16_t u16Reserved0; > + /** SAS address */ > + SASADDRESS SASAddress; > + /** Attached device handle */ > + uint16_t u16AttachedDevHandle; > + /** Attached phy identifier */ > + uint8_t u8AttachedPhyIdentifier; > + /** Reserved */ > + uint8_t u8Reserved1; > + /** Attached device information */ > + uint32_t u32AttachedDeviceInfo; > + /** Programmed link rate */ > + uint8_t u8ProgrammedLinkRate; > + /** Hardware link rate */ > + uint8_t u8HwLinkRate; > + /** Change count */ > + uint8_t u8ChangeCount; > + /** Flags */ > + uint8_t u8Flags; > + /** Phy information */ > + uint32_t u32PhyInfo; > + } fields; > + } u; > +} MptConfigurationPageSASPHY0, *PMptConfigurationPageSASPHY0; > +#pragma pack() > + > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_SET(x) ((x) & 0x3) > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_GET(x) ((x) & 0x3) > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_NO 0x0 > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_END 0x1 > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_EDGE_EXPANDER 0x2 > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_FANOUT_EXPANDER 0x3 > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_SMP_INITIATOR (1<<4) > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_STP_INITIATOR (1<<5) > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_SSP_INITIATOR (1<<6) > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_SMP_TARGET (1<<8) > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_STP_TARGET (1<<9) > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_SSP_TARGET (1<<10) > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_DIRECT_ATTACHED (1<<11) > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_LSI (1<<12) > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_ATAPI (1<<13) > +#define LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_SEP (1<<14) > + > +/** > + * SAS PHY page 1 - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASPHY1 { > + /** Union. */ > + union { > + /** Byte view - variable. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptExtendedConfigurationPageHeader ExtHeader; > + /** Reserved */ > + uint32_t u32Reserved0; > + uint32_t u32InvalidDwordCound; > + uint32_t u32RunningDisparityErrorCount; > + uint32_t u32LossDwordSynchCount; > + uint32_t u32PhyResetProblemCount; > + } fields; > + } u; > +} MptConfigurationPageSASPHY1, *PMptConfigurationPageSASPHY1; > +#pragma pack() > + > +/** > + * SAS Device page 0 - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASDevice0 { > + /** Union. */ > + union { > + /** Byte view - variable. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptExtendedConfigurationPageHeader ExtHeader; > + /** Slot number */ > + uint16_t u16Slot; > + /** Enclosure handle. */ > + uint16_t u16EnclosureHandle; > + /** SAS address */ > + SASADDRESS SASAddress; > + /** Parent device handle */ > + uint16_t u16ParentDevHandle; > + /** Phy number */ > + uint8_t u8PhyNum; > + /** Access status */ > + uint8_t u8AccessStatus; > + /** Device handle */ > + uint16_t u16DevHandle; > + /** Target ID */ > + uint8_t u8TargetID; > + /** Bus */ > + uint8_t u8Bus; > + /** Device info */ > + uint32_t u32DeviceInfo; > + /** Flags */ > + uint16_t u16Flags; > + /** Physical port */ > + uint8_t u8PhysicalPort; > + /** Reserved */ > + uint8_t u8Reserved0; > + } fields; > + } u; > +} MptConfigurationPageSASDevice0, *PMptConfigurationPageSASDevice0; > +#pragma pack() > + > +#define LSILOGICSCSI_SASDEVICE0_STATUS_NO_ERRORS (0x00) > + > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_TYPE_SET(x) ((x) & 0x3) > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_TYPE_GET(x) ((x) & 0x3) > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_TYPE_NO 0x0 > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_TYPE_END 0x1 > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_TYPE_EDGE_EXPANDER 0x2 > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_TYPE_FANOUT_EXPANDER 0x3 > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_SMP_INITIATOR (1<<4) > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_STP_INITIATOR (1<<5) > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_SSP_INITIATOR (1<<6) > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_SMP_TARGET (1<<8) > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_STP_TARGET (1<<9) > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_SSP_TARGET (1<<10) > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_DIRECT_ATTACHED (1<<11) > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_LSI (1<<12) > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_ATAPI (1<<13) > +#define LSILOGICSCSI_SASDEVICE0_DEV_INFO_DEVICE_SEP (1<<14) > + > +#define LSILOGICSCSI_SASDEVICE0_FLAGS_DEVICE_PRESENT (1<<0) > +#define LSILOGICSCSI_SASDEVICE0_FLAGS_DEVICE_MAPPED_TO_BUS_AND_TARGET_ID \ > + (1<<(1)) > +#define LSILOGICSCSI_SASDEVICE0_FLAGS_DEVICE_MAPPING_PERSISTENT \ > + (1<<(2)) > + > +/** > + * SAS Device page 1 - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASDevice1 { > + /** Union. */ > + union { > + /** Byte view - variable. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptExtendedConfigurationPageHeader ExtHeader; > + /** Reserved */ > + uint32_t u32Reserved0; > + /** SAS address */ > + SASADDRESS SASAddress; > + /** Reserved */ > + uint32_t u32Reserved; > + /** Device handle */ > + uint16_t u16DevHandle; > + /** Target ID */ > + uint8_t u8TargetID; > + /** Bus */ > + uint8_t u8Bus; > + /** Initial REgister device FIS */ > + uint32_t au32InitialRegDeviceFIS[5]; > + } fields; > + } u; > +} MptConfigurationPageSASDevice1, *PMptConfigurationPageSASDevice1; > +#pragma pack() > + > +/** > + * SAS Device page 2 - Read/Write persistent > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASDevice2 { > + /** Union. */ > + union { > + /** Byte view - variable. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptExtendedConfigurationPageHeader ExtHeader; > + /** Physical identifier */ > + SASADDRESS SASAddress; > + /** Enclosure mapping */ > + uint32_t u32EnclosureMapping; > + } fields; > + } u; > +} MptConfigurationPageSASDevice2, *PMptConfigurationPageSASDevice2; > +#pragma pack() > + > +/** > + * A device entitiy containing all pages. > + */ > +typedef struct MptSASDevice { > + /** Pointer to the next device if any. */ > + struct MptSASDevice *pNext; > + /** Pointer to the previous device if any. */ > + struct MptSASDevice *pPrev; > + > + MptConfigurationPageSASDevice0 SASDevicePage0; > + MptConfigurationPageSASDevice1 SASDevicePage1; > + MptConfigurationPageSASDevice2 SASDevicePage2; > +} MptSASDevice, *PMptSASDevice; > + > +/** > + * SAS Expander page 0 - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASExpander0 { > + /** Union. */ > + union { > + /** Byte view - variable. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptExtendedConfigurationPageHeader ExtHeader; > + /** Physical port */ > + uint8_t u8PhysicalPort; > + /** Reserved */ > + uint8_t u8Reserved0; > + /** Enclosure handle */ > + uint16_t u16EnclosureHandle; > + /** SAS address */ > + SASADDRESS SASAddress; > + /** Discovery status */ > + uint32_t u32DiscoveryStatus; > + /** Device handle. */ > + uint16_t u16DevHandle; > + /** Parent device handle */ > + uint16_t u16ParentDevHandle; > + /** Expander change count */ > + uint16_t u16ExpanderChangeCount; > + /** Expander route indexes */ > + uint16_t u16ExpanderRouteIndexes; > + /** Number of PHys in this expander */ > + uint8_t u8NumPhys; > + /** SAS level */ > + uint8_t u8SASLevel; > + /** Flags */ > + uint8_t u8Flags; > + /** Reserved */ > + uint8_t u8Reserved1; > + } fields; > + } u; > +} MptConfigurationPageSASExpander0, *PMptConfigurationPageSASExpander0; > +#pragma pack() > + > +/** > + * SAS Expander page 1 - Readonly > + */ > +#pragma pack(1) > +typedef struct MptConfigurationPageSASExpander1 { > + /** Union. */ > + union { > + /** Byte view - variable. */ > + uint8_t abPageData[1]; > + /** Field view. */ > + struct { > + /** The omnipresent header. */ > + MptExtendedConfigurationPageHeader ExtHeader; > + /** Physical port */ > + uint8_t u8PhysicalPort; > + /** Reserved */ > + uint8_t u8Reserved0[3]; > + /** Number of PHYs */ > + uint8_t u8NumPhys; > + /** Number of the Phy the information in this page is for. */ > + uint8_t u8Phy; > + /** Number of routing table entries */ > + uint16_t u16NumTableEntriesProgrammed; > + /** Programmed link rate */ > + uint8_t u8ProgrammedLinkRate; > + /** Hardware link rate */ > + uint8_t u8HwLinkRate; > + /** Attached device handle */ > + uint16_t u16AttachedDevHandle; > + /** Phy information */ > + uint32_t u32PhyInfo; > + /** Attached device information */ > + uint32_t u32AttachedDeviceInfo; > + /** Owner device handle. */ > + uint16_t u16OwnerDevHandle; > + /** Change count */ > + uint8_t u8ChangeCount; > + /** Negotiated link rate */ > + uint8_t u8NegotiatedLinkRate; > + /** Phy identifier */ > + uint8_t u8PhyIdentifier; > + /** Attached phy identifier */ > + uint8_t u8AttachedPhyIdentifier; > + /** Reserved */ > + uint8_t u8Reserved1; > + /** Discovery information */ > + uint8_t u8DiscoveryInfo; > + /** Reserved */ > + uint32_t u32Reserved; > + } fields; > + } u; > +} MptConfigurationPageSASExpander1, *PMptConfigurationPageSASExpander1; > +#pragma pack() > + > +/** > + * Structure of all supported pages for the SCSI SPI controller. > + * Used to load the device state from older versions. > + */ > +typedef struct MptConfigurationPagesSupported_SSM_V2 { > + MptConfigurationPageManufacturing0 ManufacturingPage0; > + MptConfigurationPageManufacturing1 ManufacturingPage1; > + MptConfigurationPageManufacturing2 ManufacturingPage2; > + MptConfigurationPageManufacturing3 ManufacturingPage3; > + MptConfigurationPageManufacturing4 ManufacturingPage4; > + MptConfigurationPageIOUnit0 IOUnitPage0; > + MptConfigurationPageIOUnit1 IOUnitPage1; > + MptConfigurationPageIOUnit2 IOUnitPage2; > + MptConfigurationPageIOUnit3 IOUnitPage3; > + MptConfigurationPageIOC0 IOCPage0; > + MptConfigurationPageIOC1 IOCPage1; > + MptConfigurationPageIOC2 IOCPage2; > + MptConfigurationPageIOC3 IOCPage3; > + MptConfigurationPageIOC4 IOCPage4; > + MptConfigurationPageIOC6 IOCPage6; > + struct { > + MptConfigurationPageSCSISPIPort0 SCSISPIPortPage0; > + MptConfigurationPageSCSISPIPort1 SCSISPIPortPage1; > + MptConfigurationPageSCSISPIPort2 SCSISPIPortPage2; > + } aPortPages[1]; /* Currently only one port supported. */ > + struct { > + struct { > + MptConfigurationPageSCSISPIDevice0 SCSISPIDevicePage0; > + MptConfigurationPageSCSISPIDevice1 SCSISPIDevicePage1; > + MptConfigurationPageSCSISPIDevice2 SCSISPIDevicePage2; > + MptConfigurationPageSCSISPIDevice3 SCSISPIDevicePage3; > + } aDevicePages[LSILOGICSCSI_PCI_SPI_DEVICES_MAX]; > + } aBuses[1]; /* Only one bus at the moment. */ > +} MptConfigurationPagesSupported_SSM_V2, > + *PMptConfigurationPagesSupported_SSM_V2; > + > +typedef struct MptConfigurationPagesSpi { > + struct { > + MptConfigurationPageSCSISPIPort0 SCSISPIPortPage0; > + MptConfigurationPageSCSISPIPort1 SCSISPIPortPage1; > + MptConfigurationPageSCSISPIPort2 SCSISPIPortPage2; > + } aPortPages[1]; /* Currently only one port supported. */ > + struct { > + struct { > + MptConfigurationPageSCSISPIDevice0 SCSISPIDevicePage0; > + MptConfigurationPageSCSISPIDevice1 SCSISPIDevicePage1; > + MptConfigurationPageSCSISPIDevice2 SCSISPIDevicePage2; > + MptConfigurationPageSCSISPIDevice3 SCSISPIDevicePage3; > + } aDevicePages[LSILOGICSCSI_PCI_SPI_DEVICES_MAX]; > + } aBuses[1]; /* Only one bus at the moment. */ > +} MptConfigurationPagesSpi, *PMptConfigurationPagesSpi; > + > +typedef struct MptPHY { > + MptConfigurationPageSASPHY0 SASPHYPage0; > + MptConfigurationPageSASPHY1 SASPHYPage1; > +} MptPHY, *PMptPHY; > + > +#pragma pack(1) > +typedef struct MptConfigurationPagesSas { > + /** Size of the manufacturing page 7 */ > + uint32_t cbManufacturingPage7; > + /** Pointer to the manufacturing page 7 */ > + PMptConfigurationPageManufacturing7 pManufacturingPage7; > + /** Size of the I/O unit page 0 */ > + uint32_t cbSASIOUnitPage0; > + /** Pointer to the I/O unit page 0 */ > + PMptConfigurationPageSASIOUnit0 pSASIOUnitPage0; > + /** Size of the I/O unit page 1 */ > + uint32_t cbSASIOUnitPage1; > + /** Pointer to the I/O unit page 1 */ > + PMptConfigurationPageSASIOUnit1 pSASIOUnitPage1; > + /** I/O unit page 2 */ > + MptConfigurationPageSASIOUnit2 SASIOUnitPage2; > + /** I/O unit page 3 */ > + MptConfigurationPageSASIOUnit3 SASIOUnitPage3; > + > + /** Number of PHYs in the array. */ > + uint32_t cPHYs; > + /** Pointer to an array of per PHYS pages. */ > + PMptPHY paPHYs; > + > + /** Number of devices detected. */ > + uint32_t cDevices; > + /** Pointer to the first SAS device. */ > + PMptSASDevice pSASDeviceHead; > + /** Pointer to the last SAS device. */ > + PMptSASDevice pSASDeviceTail; > +} MptConfigurationPagesSas, *PMptConfigurationPagesSas; > +#pragma pack() > + > +/** > + * Structure of all supported pages for both controllers. > + */ > +typedef struct MptConfigurationPagesSupported { > + MptConfigurationPageManufacturing0 ManufacturingPage0; > + MptConfigurationPageManufacturing1 ManufacturingPage1; > + MptConfigurationPageManufacturing2 ManufacturingPage2; > + MptConfigurationPageManufacturing3 ManufacturingPage3; > + MptConfigurationPageManufacturing4 ManufacturingPage4; > + MptConfigurationPageManufacturing5 ManufacturingPage5; > + MptConfigurationPageManufacturing6 ManufacturingPage6; > + MptConfigurationPageManufacturing8 ManufacturingPage8; > + MptConfigurationPageManufacturing9 ManufacturingPage9; > + MptConfigurationPageManufacturing10 ManufacturingPage10; > + MptConfigurationPageIOUnit0 IOUnitPage0; > + MptConfigurationPageIOUnit1 IOUnitPage1; > + MptConfigurationPageIOUnit2 IOUnitPage2; > + MptConfigurationPageIOUnit3 IOUnitPage3; > + MptConfigurationPageIOUnit4 IOUnitPage4; > + MptConfigurationPageIOC0 IOCPage0; > + MptConfigurationPageIOC1 IOCPage1; > + MptConfigurationPageIOC2 IOCPage2; > + MptConfigurationPageIOC3 IOCPage3; > + MptConfigurationPageIOC4 IOCPage4; > + MptConfigurationPageIOC6 IOCPage6; > + /* BIOS page 0 is not described */ > + MptConfigurationPageBIOS1 BIOSPage1; > + MptConfigurationPageBIOS2 BIOSPage2; > + /* BIOS page 3 is not described */ > + MptConfigurationPageBIOS4 BIOSPage4; > + > + /** Controller dependent data. */ > + union { > + MptConfigurationPagesSpi SpiPages; > + MptConfigurationPagesSas SasPages; > + } u; > +} MptConfigurationPagesSupported, *PMptConfigurationPagesSupported; > + > +/** > + * Initializes a page header. > + */ > +#define MPT_CONFIG_PAGE_HEADER_INIT(pg, type, nr, flags) \ > + (pg)->u.fields.Header.u8PageType = flags; \ > + (pg)->u.fields.Header.u8PageNumber = nr; \ > + (pg)->u.fields.Header.u8PageLength = sizeof(type) / 4 > + > +#define MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(pg, type, nr, flags) \ > + MPT_CONFIG_PAGE_HEADER_INIT(pg, type, nr, flags | \ > + MPT_CONFIGURATION_PAGE_TYPE_MANUFACTURING) > + > +#define MPT_CONFIG_PAGE_HEADER_INIT_IO_UNIT(pg, type, nr, flags) \ > + MPT_CONFIG_PAGE_HEADER_INIT(pg, type, nr, flags | \ > + MPT_CONFIGURATION_PAGE_TYPE_IO_UNIT) > + > +#define MPT_CONFIG_PAGE_HEADER_INIT_IOC(pg, type, nr, flags) \ > + MPT_CONFIG_PAGE_HEADER_INIT(pg, type, nr, flags | \ > + MPT_CONFIGURATION_PAGE_TYPE_IOC) > + > +#define MPT_CONFIG_PAGE_HEADER_INIT_BIOS(pg, type, nr, flags) \ > + MPT_CONFIG_PAGE_HEADER_INIT(pg, type, nr, flags | \ > + MPT_CONFIGURATION_PAGE_TYPE_BIOS) > + > +/** > + * Initializes a extended page header. > + */ > +#define MPT_CONFIG_EXTENDED_PAGE_HEADER_INIT(pg, cb, nr, flags, exttype) \ > + (pg)->u.fields.ExtHeader.u8PageType = flags | \ > + MPT_CONFIGURATION_PAGE_TYPE_EXTENDED; \ > + (pg)->u.fields.ExtHeader.u8PageNumber = nr; \ > + (pg)->u.fields.ExtHeader.u8ExtPageType = exttype; \ > + (pg)->u.fields.ExtHeader.u16ExtPageLength = cb / 4 > + > +/** > + * Possible SG element types. > + */ > +enum MPTSGENTRYTYPE { > + MPTSGENTRYTYPE_TRANSACTION_CONTEXT = 0x00, > + MPTSGENTRYTYPE_SIMPLE = 0x01, > + MPTSGENTRYTYPE_CHAIN = 0x03 > +}; > + > +/** > + * Register interface. > + */ > + > +/** > + * Defined states that the SCSI controller can have. > + */ > +typedef enum LSILOGICSTATE { > + /** Reset state. */ > + LSILOGICSTATE_RESET = 0x00, > + /** Ready state. */ > + LSILOGICSTATE_READY = 0x01, > + /** Operational state. */ > + LSILOGICSTATE_OPERATIONAL = 0x02, > + /** Fault state. */ > + LSILOGICSTATE_FAULT = 0x04, > + /** 32bit size hack */ > + LSILOGICSTATE_32BIT_HACK = 0x7fffffff > +} LSILOGICSTATE; > + > +/** > + * Which entity needs to initialize the controller > + * to get into the operational state. > + */ > +typedef enum LSILOGICWHOINIT { > + /** Not initialized. */ > + LSILOGICWHOINIT_NOT_INITIALIZED = 0x00, > + /** System BIOS. */ > + LSILOGICWHOINIT_SYSTEM_BIOS = 0x01, > + /** ROM Bios. */ > + LSILOGICWHOINIT_ROM_BIOS = 0x02, > + /** PCI Peer. */ > + LSILOGICWHOINIT_PCI_PEER = 0x03, > + /** Host driver. */ > + LSILOGICWHOINIT_HOST_DRIVER = 0x04, > + /** Manufacturing. */ > + LSILOGICWHOINIT_MANUFACTURING = 0x05, > + /** 32bit size hack. */ > + LSILOGICWHOINIT_32BIT_HACK = 0x7fffffff > +} LSILOGICWHOINIT; > + > + > +/** > + * IOC status codes. > + */ > +#define LSILOGIC_IOCSTATUS_SUCCESS 0x0000 > +#define LSILOGIC_IOCSTATUS_INVALID_FUNCTION 0x0001 > +#define LSILOGIC_IOCSTATUS_BUSY 0x0002 > +#define LSILOGIC_IOCSTATUS_INVALID_SGL 0x0003 > +#define LSILOGIC_IOCSTATUS_INTERNAL_ERROR 0x0004 > +#define LSILOGIC_IOCSTATUS_RESERVED 0x0005 > +#define LSILOGIC_IOCSTATUS_INSUFFICIENT_RESOURCES 0x0006 > +#define LSILOGIC_IOCSTATUS_INVALID_FIELD 0x0007 > +#define LSILOGIC_IOCSTATUS_INVALID_STATE 0x0008 > +#define LSILOGIC_IOCSTATUS_OP_STATE_NOT_SUPPOTED 0x0009 > + > +/** > + * Size of the I/O and MMIO space. > + */ > +#define LSILOGIC_PCI_SPACE_IO_SIZE 256 > +#define LSILOGIC_PCI_SPACE_MEM_SIZE (16 * 1024) > + > +/** > + * Doorbell register - Used to get the status of the controller and > + * initialise it. > + */ > +#define LSILOGIC_REG_DOORBELL 0x00 > +#define LSILOGIC_REG_DOORBELL_SET_STATE(State) (((State) & 0x0f) << 28) > +#define LSILOGIC_REG_DOORBELL_SET_USED(fUsed) (((fUsed) ? 1 : 0) << 27) > +#define LSILOGIC_REG_DOORBELL_SET_WHOINIT(Who)(((Who) & 0x07) << 24) > +#define LSILOGIC_REG_DOORBELL_SET_FAULT_CODE(Code) (Code) > +#define LSILOGIC_REG_DOORBELL_GET_FUNCTION(x) (((x) & 0xff000000) >> 24) > +#define LSILOGIC_REG_DOORBELL_GET_SIZE(x) (((x) & 0x00ff0000) >> 16) > + > +/** > + * Functions which can be passed through the system doorbell. > + */ > +#define LSILOGIC_DOORBELL_FUNCTION_IOC_MSG_UNIT_RESET 0x40 > +#define LSILOGIC_DOORBELL_FUNCTION_IO_UNIT_RESET 0x41 > +#define LSILOGIC_DOORBELL_FUNCTION_HANDSHAKE 0x42 > +#define LSILOGIC_DOORBELL_FUNCTION_REPLY_FRAME_REMOVAL 0x43 > + > +/** > + * Write sequence register for the diagnostic register. > + */ > +#define LSILOGIC_REG_WRITE_SEQUENCE 0x04 > + > +/** > + * Diagnostic register - used to reset the controller. > + */ > +#define LSILOGIC_REG_HOST_DIAGNOSTIC 0x08 > +#define LSILOGIC_REG_HOST_DIAGNOSTIC_DIAG_MEM_ENABLE (1<<(0)) > +#define LSILOGIC_REG_HOST_DIAGNOSTIC_DISABLE_ARM (1<<(1)) > +#define LSILOGIC_REG_HOST_DIAGNOSTIC_RESET_ADAPTER (1<<(2)) > +#define LSILOGIC_REG_HOST_DIAGNOSTIC_DIAG_RW_ENABLE (1<<(4)) > +#define LSILOGIC_REG_HOST_DIAGNOSTIC_RESET_HISTORY (1<<(5)) > +#define LSILOGIC_REG_HOST_DIAGNOSTIC_FLASH_BAD_SIG (1<<(6)) > +#define LSILOGIC_REG_HOST_DIAGNOSTIC_DRWE (1<<(7)) > +#define LSILOGIC_REG_HOST_DIAGNOSTIC_PREVENT_IOC_BOOT (1<<(9)) > +#define LSILOGIC_REG_HOST_DIAGNOSTIC_CLEAR_FLASH_BAD_SIG (1<<(10)) > + > +#define LSILOGIC_REG_TEST_BASE_ADDRESS 0x0c > +#define LSILOGIC_REG_DIAG_RW_DATA 0x10 > +#define LSILOGIC_REG_DIAG_RW_ADDRESS 0x14 > + > +/** > + * Interrupt status register. > + */ > +#define LSILOGIC_REG_HOST_INTR_STATUS 0x30 > +#define LSILOGIC_REG_HOST_INTR_STATUS_W_MASK (1<<(3)) > +#define LSILOGIC_REG_HOST_INTR_STATUS_DOORBELL_STS (1<<(31)) > +#define LSILOGIC_REG_HOST_INTR_STATUS_REPLY_INTR (1<<(3)) > +#define LSILOGIC_REG_HOST_INTR_STATUS_SYSTEM_DOORBELL (1<<(0)) > + > +/** > + * Interrupt mask register. > + */ > +#define LSILOGIC_REG_HOST_INTR_MASK 0x34 > +#define LSILOGIC_REG_HOST_INTR_MASK_W_MASK (1<<(0) | 1<<(3) | 1<<(8) | 1<<(9)) > +#define LSILOGIC_REG_HOST_INTR_MASK_IRQ_ROUTING (1<<(8) | 1<<(9)) > +#define LSILOGIC_REG_HOST_INTR_MASK_DOORBELL (1<<(0)) > +#define LSILOGIC_REG_HOST_INTR_MASK_REPLY (1<<(3)) > + > +/** > + * Queue registers. > + */ > +#define LSILOGIC_REG_REQUEST_QUEUE 0x40 > +#define LSILOGIC_REG_REPLY_QUEUE 0x44 > + > +#endif /* __DEVLSILOGICSCSI_H__ */ > diff --git a/hw/pci_ids.h b/hw/pci_ids.h > index 301bf1c..f83c804 100644 > --- a/hw/pci_ids.h > +++ b/hw/pci_ids.h > @@ -48,6 +48,10 @@ > > #define PCI_VENDOR_ID_LSI_LOGIC 0x1000 > #define PCI_DEVICE_ID_LSI_53C895A 0x0012 > +#define PCI_DEVICE_ID_LSI_53C1030 0x0030 > +#define PCI_DEVICE_ID_LSI_SAS1064 0x0050 > +#define PCI_DEVICE_ID_LSI_SAS1068 0x0054 Interesting. I see: 1000 LSI Logic / Symbios Logic 0054 SAS1068 PCI-X Fusion-MPT SAS 0050 SAS1064 PCI-X Fusion-MPT SAS 0030 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI so in reality these are PCI-X devices? I don't mind that pci-x in qemu is incomplete but maybe add a comment about this in code. > +#define PCI_DEVICE_ID_LSI_SAS1068E 0x0058 > #define PCI_DEVICE_ID_LSI_SAS1078 0x0060 > > #define PCI_VENDOR_ID_DEC 0x1011 > diff --git a/trace-events b/trace-events > index 8fcbc50..0eb2024 100644 > --- a/trace-events > +++ b/trace-events > @@ -534,6 +534,32 @@ lm32_uart_irq_state(int level) "irq state %d" > # hw/lm32_sys.c > lm32_sys_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" > > +# hw/lsilogic.c > +lsilogic_command_complete(int cmd, uint32_t status, uint32_t resid) "scmd %d: command completed, status %x, residual %d" > +lsilogic_diag_readl(unsigned long addr, uint32_t val) "addr 0x%lx: 0x%x" > +lsilogic_diag_writel(uint32_t addr, uint32_t val) "addr 0x%x: 0x%x" > +lsilogic_handle_scsi(const char *frame, int bus, int dev, int lun, void *sdev, unsigned long size) "%s dev %x/%x/%x sdev %p xfer %lu" > +lsilogic_init(int sges, int cmds, const char *intr, const char *mode) "Using %d sges, %d cmds, %s, %s mode" > +lsilogic_io_complete(int cmd, uint32_t len) "scmd %d: %d bytes completed" > +lsilogic_iov_read_overflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes" > +lsilogic_iov_read_underflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes" > +lsilogic_iov_write_overflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes" > +lsilogic_iov_write_underflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes" > +lsilogic_irq_lower(void) "INTx" > +lsilogic_irq_raise(void) "INTx" > +lsilogic_mmio_invalid_readl(unsigned long addr) "addr 0x%lx" > +lsilogic_mmio_invalid_writel(uint32_t addr, uint32_t val) "addr 0x%x: 0x%x" > +lsilogic_mmio_readl(unsigned long addr, uint32_t val) "addr 0x%lx: 0x%x" > +lsilogic_mmio_writel(uint32_t addr, uint32_t val) "addr 0x%x: 0x%x" > +lsilogic_msix_raise(int vector) "vector %d" > +lsilogic_process_message(const char *msg) "MPT cmd %s\n" > +lsilogic_reset(void) "Reset" > +lsilogic_scsi_complete(int cmd, uint32_t status, int len, int xfer) "scmd %d: finished with status %x, len %u/%u" > +lsilogic_scsi_nodata(int cmd) "scmd %d: no data to be transferred" > +lsilogic_scsi_read_start(int cmd, int len) "scmd %d: transfer %d bytes of data" > +lsilogic_scsi_write_start(int cmd, int len) "scmd %d: transfer %d bytes of data" > +lsilogic_unhandled_cmd(int cmd, uint8_t msg_cmd) "scmd %d: Unhandled cmd %x" > + > # hw/megasas.c > megasas_init_firmware(uint64_t pa) "pa %" PRIx64 " " > megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tail, uint32_t flags) "queue at %" PRIx64 " len %d head %" PRIx64 " tail %" PRIx64 " flags %x" > -- > 1.7.1