DevLsiLogicSCSI.cpp revision 8efcefe456723ce1e613f2ff759a93ff8190fb74
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * DevLsiLogicSCSI - LsiLogic LSI53c1030 SCSI controller.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Copyright (C) 2006-2013 Oracle Corporation
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * available from http://www.virtualbox.org. This file is free software;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * you can redistribute it and/or modify it under the terms of the GNU
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * General Public License (GPL) as published by the Free Software
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/*******************************************************************************
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync* Header Files *
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync*******************************************************************************/
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/*******************************************************************************
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync* Defined Constants And Macros *
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync*******************************************************************************/
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/** The current saved state version. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/** The saved state version used by VirtualBox before SAS support was added. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/** The saved state version used by VirtualBox 3.0 and earlier. It does not
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * include the device config part. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/** Maximum number of entries in the release log. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync#define LSILOGIC_RTGCPHYS_FROM_U32(Hi, Lo) ( (RTGCPHYS)RT_MAKE_U64(Lo, Hi) )
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/*******************************************************************************
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync* Structures and Typedefs *
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync*******************************************************************************/
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Reply data.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Lower 32 bits of the reply address in memory. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Full address of the reply in guest memory. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Size of the reply. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Different views to the reply depending on the request type. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/** Pointer to reply data. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * State of a device attached to the buslogic host adapter.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @implements PDMIBASE
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @implements PDMISCSIPORT
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @implements PDMILEDPORTS
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the owning lsilogic device instance. - R3 pointer */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** LUN of the device. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Number of outstanding tasks on the port. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Our base interface. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** SCSI port interface. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Led interface. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the attached driver's base interface. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the underlying SCSI connector interface. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** The status LED state for this device. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/** Pointer to a device state. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/** Pointer to a task state. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsynctypedef struct LSILOGICTASKSTATE *PLSILOGICTASKSTATE;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Device instance data for the emulated SCSI controller.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsynctypedef struct LSILOGICSCSI
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** PCI device structure. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the device instance. - R3 ptr. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the device instance. - R0 ptr. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the device instance. - RC ptr. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Flag whether the GC part of the device is enabled. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Flag whether the R0 part of the device is enabled. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** The state the controller is currently in. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Who needs to init the driver to get into operational state. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Flag whether we are in doorbell function. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Flag whether diagnostic access is enabled. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Flag whether a notification was send to R3. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Flag whether the guest enabled event notification from the IOC. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Queue to send tasks to R3. - R3 ptr */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Queue to send tasks to R3. - R0 ptr */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Queue to send tasks to R3. - RC ptr */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Number of device states allocated. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** States for attached devices. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** MMIO address the device is mapped to. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** I/O port address the device is mapped to. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Interrupt mask. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Interrupt status register. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Buffer for messages which are passed
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * through the doorbell using the
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * handshake method. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync uint32_t aMessage[sizeof(MptConfigurationRequest)];
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Actual position in the buffer. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Size of the message which is given in the doorbell message in dwords. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Reply buffer. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Next entry to read. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Size of the reply in the buffer in 16bit words. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** The fault code of the I/O controller if we are in the fault state. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Upper 32 bits of the message frame address to locate requests in guest memory. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Upper 32 bits of the sense buffer address. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Maximum number of devices the driver reported he can handle. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Maximum number of buses the driver reported he can handle. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Current size of reply message frames in the guest. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Next key to write in the sequence to get access
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * to diagnostic memory. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Number entries allocated for the reply queue. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Number entries allocated for the outstanding request queue. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Critical section protecting the reply post queue. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Critical section protecting the reply free queue. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the start of the reply free queue - R3. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync R3PTRTYPE(volatile uint32_t *) pReplyFreeQueueBaseR3;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the start of the reply post queue - R3. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync R3PTRTYPE(volatile uint32_t *) pReplyPostQueueBaseR3;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the start of the request queue - R3. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync R3PTRTYPE(volatile uint32_t *) pRequestQueueBaseR3;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the start of the reply queue - R0. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync R0PTRTYPE(volatile uint32_t *) pReplyFreeQueueBaseR0;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the start of the reply queue - R0. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync R0PTRTYPE(volatile uint32_t *) pReplyPostQueueBaseR0;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the start of the request queue - R0. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync R0PTRTYPE(volatile uint32_t *) pRequestQueueBaseR0;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the start of the reply queue - RC. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync RCPTRTYPE(volatile uint32_t *) pReplyFreeQueueBaseRC;
15071fa8e053848b4a479e9c2be14231c115f330vboxsync /** Pointer to the start of the reply queue - RC. */
15071fa8e053848b4a479e9c2be14231c115f330vboxsync RCPTRTYPE(volatile uint32_t *) pReplyPostQueueBaseRC;
15071fa8e053848b4a479e9c2be14231c115f330vboxsync /** Pointer to the start of the request queue - RC. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync RCPTRTYPE(volatile uint32_t *) pRequestQueueBaseRC;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Next free entry in the reply queue the guest can write a address to. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync volatile uint32_t uReplyFreeQueueNextEntryFreeWrite;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Next valid entry the controller can read a valid address for reply frames from. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Next free entry in the reply queue the guest can write a address to. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync volatile uint32_t uReplyPostQueueNextEntryFreeWrite;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Next valid entry the controller can read a valid address for reply frames from. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Next free entry the guest can write a address to a request frame to. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Next valid entry the controller can read a valid address for request frames from. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Emulated controller type */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Handle counter */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Number of ports this controller has. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** BIOS emulation. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Cache for allocated tasks. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Status LUN: The base interface. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Status LUN: Leds interface. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Status LUN: Partner of ILeds. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the configuration page area. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync R3PTRTYPE(PMptConfigurationPagesSupported) pConfigurationPages;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Indicates that PDMDevHlpAsyncNotificationCompleted should be called when
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * a port is entering the idle state. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync bool volatile fSignalIdle;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Flag whether we have tasks which need to be processed again- */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync bool volatile fRedo;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** List of tasks which can be redone. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync R3PTRTYPE(volatile PLSILOGICTASKSTATE) pTasksRedoHead;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/** Pointer to the device instance data of the LsiLogic emulation. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Scatter gather list entry data.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Flag whether the buffer in the list is from the guest or an
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * allocated temporary buffer because the segments in the guest
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * are not sector aligned.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Flag whether the buffer contains data or is the destination for the transfer. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the start of the buffer. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Size of the buffer. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Flag dependent data. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Data to handle direct mappings of guest buffers. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** The segment in the guest which is not sector aligned. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/** Pointer to a scatter/gather list entry. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsynctypedef LSILOGICTASKSTATESGENTRY *PLSILOGICTASKSTATESGENTRY;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Task state object which holds all necessary data while
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * processing the request from the guest.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Next in the redo list. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Target device. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** The message request from the guest. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Reply message if the request produces one. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** SCSI request structure for the SCSI driver. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Address of the message request frame in guests memory.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Used to read the S/G entries in the second step. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Number of scatter gather list entries. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** How many entries would fit into the sg list. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** How many times the list was too big. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the first entry of the scatter gather list. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** How many entries would fit into the sg info list. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Number of entries for the information entries. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** How many times the list was too big. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the first mapping information entry. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Size of the temporary buffer for unaligned guest segments. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the temporary buffer. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Pointer to the sense buffer. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** Flag whether the request was issued from the BIOS. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/*******************************************************************************
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync* Internal Functions *
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync*******************************************************************************/
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncstatic void lsilogicR3InitializeConfigurationPages(PLSILOGICSCSI pThis);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncstatic void lsilogicR3ConfigurationPagesFree(PLSILOGICSCSI pThis);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncstatic int lsilogicR3ProcessConfigurationRequest(PLSILOGICSCSI pThis, PMptConfigurationRequest pConfigurationReq,
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/*******************************************************************************
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync* Global Variables *
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync*******************************************************************************/
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync/** Key sequence the guest has to write to enable access
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * to diagnostic memory. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncstatic const uint8_t g_lsilogicDiagnosticAccess[] = {0x04, 0x0b, 0x02, 0x07, 0x0d};
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Updates the status of the interrupt pin of the device.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @returns nothing.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pThis Pointer to the LsiLogic device state.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncstatic void lsilogicUpdateInterrupt(PLSILOGICSCSI pThis)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Mask out doorbell status so that it does not affect interrupt updating. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync uIntSts = (ASMAtomicReadU32(&pThis->uInterruptStatus) & ~LSILOGIC_REG_HOST_INTR_STATUS_DOORBELL_STS);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Check maskable interrupts. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync uIntSts &= ~(ASMAtomicReadU32(&pThis->uInterruptMask) & ~LSILOGIC_REG_HOST_INTR_MASK_IRQ_ROUTING);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 1);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PDMDevHlpPCISetIrq(pThis->CTX_SUFF(pDevIns), 0, 0);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Sets a given interrupt status bit in the status register and
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * updates the interrupt status.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @returns nothing.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pThis Pointer to the LsiLogic device state.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param uStatus The status bit to set.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncDECLINLINE(void) lsilogicSetInterrupt(PLSILOGICSCSI pThis, uint32_t uStatus)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Clears a given interrupt status bit in the status register and
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * updates the interrupt status.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @returns nothing.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pThis Pointer to the LsiLogic device state.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param uStatus The status bit to set.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncDECLINLINE(void) lsilogicClearInterrupt(PLSILOGICSCSI pThis, uint32_t uStatus)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync ASMAtomicAndU32(&pThis->uInterruptStatus, ~uStatus);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Sets the I/O controller into fault state and sets the fault code.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @returns nothing
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pThis Pointer to the LsiLogic device state.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param uIOCFaultCode Fault code to set.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncDECLINLINE(void) lsilogicSetIOCFaultCode(PLSILOGICSCSI pThis, uint16_t uIOCFaultCode)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync Log(("%s: Setting I/O controller into FAULT state: uIOCFaultCode=%u\n", __FUNCTION__, uIOCFaultCode));
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Performs a hard reset on the controller.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @returns VBox status code.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pThis Pointer to the LsiLogic device state.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* The interrupts are masked out. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pThis->uInterruptMask |= LSILOGIC_REG_HOST_INTR_MASK_DOORBELL
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Reset interrupt states. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Reset the queues. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Disable diagnostic access. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Set default values. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pThis->cbReplyFrame = 128; /* @todo Figure out where it is needed. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /** @todo: Put stuff to reset here. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Mark that we finished performing the reset. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Frees the configuration pages if allocated.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @returns nothing.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pThis The LsiLogic controller instance
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncstatic void lsilogicR3ConfigurationPagesFree(PLSILOGICSCSI pThis)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Destroy device list if we emulate a SAS controller. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SAS)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PMptConfigurationPagesSas pSasPages = &pThis->pConfigurationPages->u.SasPages;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PMptSASDevice pSASDeviceCurr = pSasPages->pSASDeviceHead;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Finishes a context reply.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @returns nothing
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pThis Pointer to the LsiLogic device state.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param u32MessageContext The message context ID to post.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncstatic void lsilogicR3FinishContextReply(PLSILOGICSCSI pThis, uint32_t u32MessageContext)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync LogFlowFunc(("pThis=%#p u32MessageContext=%#x\n", pThis, u32MessageContext));
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync AssertMsg(!pThis->fDoorbellInProgress, ("We are in a doorbell function\n"));
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Write message context ID into reply post queue. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync rc = PDMCritSectEnter(&pThis->ReplyPostQueueCritSect, VINF_SUCCESS);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Check for a entry in the queue. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync if (RT_UNLIKELY(pThis->uReplyPostQueueNextAddressRead != pThis->uReplyPostQueueNextEntryFreeWrite))
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Set error code. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync lsilogicSetIOCFaultCode(pThis, LSILOGIC_IOCSTATUS_INSUFFICIENT_RESOURCES);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* We have a context reply. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync ASMAtomicWriteU32(&pThis->CTX_SUFF(pReplyPostQueueBase)[pThis->uReplyPostQueueNextEntryFreeWrite], u32MessageContext);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync ASMAtomicIncU32(&pThis->uReplyPostQueueNextEntryFreeWrite);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pThis->uReplyPostQueueNextEntryFreeWrite %= pThis->cReplyQueueEntries;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Set interrupt. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync lsilogicSetInterrupt(pThis, LSILOGIC_REG_HOST_INTR_STATUS_REPLY_INTR);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncstatic void lsilogicR3TaskStateClear(PLSILOGICTASKSTATE pTaskState)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync RTMemPageFree(pTaskState->pvBufferUnaligned, pTaskState->cbBufferUnaligned);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @callback_method_impl{FNMEMCACHECTOR}
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncstatic DECLCALLBACK(int) lsilogicR3TaskStateCtor(RTMEMCACHE hMemCache, void *pvObj, void *pvUser)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @callback_method_impl{FNMEMCACHEDTOR}
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncstatic DECLCALLBACK(void) lsilogicR3TaskStateDtor(RTMEMCACHE hMemCache, void *pvObj, void *pvUser)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PLSILOGICTASKSTATE pTaskState = (PLSILOGICTASKSTATE)pvObj;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync#endif /* IN_RING3 */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Takes necessary steps to finish a reply frame.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @returns nothing
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pThis Pointer to the LsiLogic device state.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pReply Pointer to the reply message.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param fForceReplyFifo Flag whether the use of the reply post fifo is forced.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncstatic void lsilogicFinishAddressReply(PLSILOGICSCSI pThis, PMptReplyUnion pReply, bool fForceReplyFifo)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * If we are in a doorbell function we set the reply size now and
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * set the system doorbell status interrupt to notify the guest that
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * we are ready to send the reply.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync if (pThis->fDoorbellInProgress && !fForceReplyFifo)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Set size of the reply in 16bit words. The size in the reply is in 32bit dwords. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pThis->cReplySize = pReply->Header.u8MessageLength * 2;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync Log(("%s: cReplySize=%u\n", __FUNCTION__, pThis->cReplySize));
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync lsilogicSetInterrupt(pThis, LSILOGIC_REG_HOST_INTR_STATUS_SYSTEM_DOORBELL);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * The reply queues are only used if the request was fetched from the request queue.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Requests from the request queue are always transferred to R3. So it is not possible
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * that this case happens in R0 or GC.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Grab a free reply message from the queue. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync rc = PDMCritSectEnter(&pThis->ReplyFreeQueueCritSect, VINF_SUCCESS);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Check for a free reply frame. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync if (RT_UNLIKELY(pThis->uReplyFreeQueueNextAddressRead != pThis->uReplyFreeQueueNextEntryFreeWrite))
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Set error code. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync lsilogicSetIOCFaultCode(pThis, LSILOGIC_IOCSTATUS_INSUFFICIENT_RESOURCES);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync uint32_t u32ReplyFrameAddressLow = pThis->CTX_SUFF(pReplyFreeQueueBase)[pThis->uReplyFreeQueueNextAddressRead];
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pThis->uReplyFreeQueueNextAddressRead %= pThis->cReplyQueueEntries;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Build 64bit physical address. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync RTGCPHYS GCPhysReplyMessage = LSILOGIC_RTGCPHYS_FROM_U32(pThis->u32HostMFAHighAddr, u32ReplyFrameAddressLow);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync size_t cbReplyCopied = (pThis->cbReplyFrame < sizeof(MptReplyUnion)) ? pThis->cbReplyFrame : sizeof(MptReplyUnion);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Write reply to guest memory. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhysReplyMessage, pReply, cbReplyCopied);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Write low 32bits of reply frame into post reply queue. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync rc = PDMCritSectEnter(&pThis->ReplyPostQueueCritSect, VINF_SUCCESS);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Check for a entry in the queue. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync if (RT_UNLIKELY(pThis->uReplyPostQueueNextAddressRead != pThis->uReplyPostQueueNextEntryFreeWrite))
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Set error code. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync lsilogicSetIOCFaultCode(pThis, LSILOGIC_IOCSTATUS_INSUFFICIENT_RESOURCES);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* We have a address reply. Set the 31th bit to indicate that. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync ASMAtomicWriteU32(&pThis->CTX_SUFF(pReplyPostQueueBase)[pThis->uReplyPostQueueNextEntryFreeWrite],
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync ASMAtomicIncU32(&pThis->uReplyPostQueueNextEntryFreeWrite);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pThis->uReplyPostQueueNextEntryFreeWrite %= pThis->cReplyQueueEntries;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync lsilogicSetInterrupt(pThis, LSILOGIC_REG_HOST_INTR_STATUS_SYSTEM_DOORBELL);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Set interrupt. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync lsilogicSetInterrupt(pThis, LSILOGIC_REG_HOST_INTR_STATUS_REPLY_INTR);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync AssertMsgFailed(("This is not allowed to happen.\n"));
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Processes a given Request from the guest
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @returns VBox status code.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pThis Pointer to the LsiLogic device state.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pMessageHdr Pointer to the message header of the request.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pReply Pointer to the reply.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsyncstatic int lsilogicR3ProcessMessageRequest(PLSILOGICSCSI pThis, PMptMessageHdr pMessageHdr, PMptReplyUnion pReply)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync if (pMessageHdr->u8Function < RT_ELEMENTS(g_apszMPTFunctionNames))
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync Log(("Message request function: %s\n", g_apszMPTFunctionNames[pMessageHdr->u8Function]));
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PMptSCSITaskManagementRequest pTaskMgmtReq = (PMptSCSITaskManagementRequest)pMessageHdr;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync LogFlow(("u8TaskType=%u\n", pTaskMgmtReq->u8TaskType));
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync LogFlow(("u32TaskMessageContext=%#x\n", pTaskMgmtReq->u32TaskMessageContext));
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->SCSITaskManagement.u8MessageLength = 6; /* 6 32bit dwords. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->SCSITaskManagement.u8TaskType = pTaskMgmtReq->u8TaskType;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->SCSITaskManagement.u32TerminationCount = 0;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * This request sets the I/O controller to the
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * operational state.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PMptIOCInitRequest pIOCInitReq = (PMptIOCInitRequest)pMessageHdr;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Update configuration values. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pThis->enmWhoInit = (LSILOGICWHOINIT)pIOCInitReq->u8WhoInit;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pThis->cbReplyFrame = pIOCInitReq->u16ReplyFrameSize;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pThis->u32HostMFAHighAddr = pIOCInitReq->u32HostMfaHighAddr;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pThis->u32SenseBufferHighAddr = pIOCInitReq->u32SenseBufferHighAddr;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Return reply. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u8MessageLength = 15; /* 15 32bit dwords. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u16MessageVersion = 0x0102; /* Version from the specification. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync else if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SAS)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u16MessageVersion = 0x0105; /* Version from the specification. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync AssertMsgFailed(("Invalid controller type %d\n", pThis->enmCtrlType));
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u8IOCNumber = 0; /* PCI function number. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u8MaxChainDepth = LSILOGICSCSI_MAXIMUM_CHAIN_DEPTH;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u8BlockSize = 12; /* Block size in 32bit dwords. This is the largest request we can get (SCSI I/O). */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u8Flags = 0; /* Bit 0 is set if the guest must upload the FW prior to using the controller. Obviously not needed here. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u16ReplyQueueDepth = pThis->cReplyQueueEntries - 1; /* One entry is always free. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u16RequestFrameSize = 128; /* @todo Figure out where it is needed. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u16ProductID = 0xcafe; /* Our own product ID :) */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u32CurrentHostMFAHighAddr = pThis->u32HostMFAHighAddr;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u16GlobalCredits = pThis->cRequestQueueEntries - 1; /* One entry is always free. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u8EventState = 0; /* Event notifications not enabled. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u32CurrentSenseBufferHighAddr = pThis->u32SenseBufferHighAddr;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u16CurReplyFrameSize = pThis->cbReplyFrame;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u8MaxDevices = pThis->cMaxDevices;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->IOCFacts.u32FwImageSize = 0; /* No image needed. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PMptPortFactsRequest pPortFactsReq = (PMptPortFactsRequest)pMessageHdr;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortFacts.u8PortNumber = pPortFactsReq->u8PortNumber;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* This controller only supports one bus with bus number 0. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortFacts.u8PortType = 0; /* Not existant. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortFacts.u8PortType = 0x01; /* SCSI Port. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortFacts.u16MaxDevices = LSILOGICSCSI_PCI_SPI_DEVICES_PER_BUS_MAX;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortFacts.u16ProtocolFlags = RT_BIT(3) | RT_BIT(0); /* SCSI initiator and LUN supported. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortFacts.u16MaxPostedCmdBuffers = 0; /* Only applies for target mode which we dont support. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortFacts.u16MaxLANBuckets = 0; /* Only for the LAN controller. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync else if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SAS)
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortFacts.u8PortType = 0; /* Not existant. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortFacts.u8PortType = 0x30; /* SAS Port. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortFacts.u16ProtocolFlags = RT_BIT(3) | RT_BIT(0); /* SCSI initiator and LUN supported. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortFacts.u16MaxPostedCmdBuffers = 0; /* Only applies for target mode which we dont support. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortFacts.u16MaxLANBuckets = 0; /* Only for the LAN controller. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync AssertMsgFailed(("Invalid controller type %d\n", pThis->enmCtrlType));
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * The port enable request notifies the IOC to make the port available and perform
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * appropriate discovery on the associated link.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PMptPortEnableRequest pPortEnableReq = (PMptPortEnableRequest)pMessageHdr;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->PortEnable.u8PortNumber = pPortEnableReq->u8PortNumber;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PMptEventNotificationRequest pEventNotificationReq = (PMptEventNotificationRequest)pMessageHdr;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->EventNotification.u16EventDataLength = 1; /* 1 32bit D-Word. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->EventNotification.u8MessageFlags = (1 << 7);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->EventNotification.u32Event = MPT_EVENT_EVENT_CHANGE;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->EventNotification.u32EventData = pThis->fEventNotificationEnabled ? 1 : 0;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PMptConfigurationRequest pConfigurationReq = (PMptConfigurationRequest)pMessageHdr;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync rc = lsilogicR3ProcessConfigurationRequest(pThis, pConfigurationReq, &pReply->Configuration);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync PMptFWUploadRequest pFWUploadReq = (PMptFWUploadRequest)pMessageHdr;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->FWUpload.u8ImageType = pFWUploadReq->u8ImageType;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync //PMptFWDownloadRequest pFWDownloadReq = (PMptFWDownloadRequest)pMessageHdr;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync case MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST: /* Should be handled already. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync AssertMsgFailed(("Invalid request function %#x\n", pMessageHdr->u8Function));
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync /* Copy common bits from request message frame to reply. */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->Header.u8Function = pMessageHdr->u8Function;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync pReply->Header.u32MessageContext = pMessageHdr->u32MessageContext;
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync lsilogicFinishAddressReply(pThis, pReply, fForceReplyPostFifo);
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync#endif /* IN_RING3 */
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * Writes a value to a register at a given offset.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @returns VBox status code.
c3890ba3bf003d2670542116b4e5fe108ff0f40evboxsync * @param pThis Pointer to the LsiLogic device state.
static int lsilogicRegisterWrite(PLSILOGICSCSI pThis, uint32_t uOffset, void const *pv, unsigned cb)
switch (uOffset)
case LSILOGIC_REG_REPLY_QUEUE:
ASMAtomicWriteU32(&pThis->CTX_SUFF(pReplyFreeQueueBase)[pThis->uReplyFreeQueueNextEntryFreeWrite], u32);
uNextWrite++;
case LSILOGIC_REG_DOORBELL:
switch (uFunction)
AssertMsg(pThis->iMessage < RT_ELEMENTS(pThis->aMessage), ("Message is too big to fit into the buffer\n"));
* If the last byte of the message is written, force a switch to R3 because some requests might force
#ifndef IN_RING3
return VINF_IOM_R3_MMIO_WRITE;
#ifdef IN_RING3
int rc = lsilogicR3ProcessMessageRequest(pThis, (PMptMessageHdr)pThis->aMessage, &pThis->ReplyBuffer);
#ifndef IN_RING3
return VINF_IOM_R3_IOPORT_WRITE;
return VINF_SUCCESS;
switch (offReg)
case LSILOGIC_REG_REPLY_QUEUE:
case LSILOGIC_REG_DOORBELL:
u32 = 0;
case LSILOGIC_REG_TEST_BASE_ADDRESS: /* The spec doesn't say anything about these registers, so we just ignore them */
return rc;
return rc;
PDMBOTHCBDECL(int) lsilogicIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return rc;
PDMBOTHCBDECL(int) lsilogicMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
LogFlowFunc(("pThis=%#p GCPhysAddr=%RGp pv=%#p{%.*Rhxs} cb=%u\n", pThis, GCPhysAddr, pv, cb, pv, cb));
return VINF_SUCCESS;
LogFlowFunc(("pThis=%#p GCPhysAddr=%RGp pv=%#p{%.*Rhxs} cb=%u\n", pThis, GCPhysAddr, pv, cb, pv, cb));
return VINF_SUCCESS;
#ifdef IN_RING3
static void lsilogicR3ScatterGatherListCopyFromBuffer(PLSILOGICTASKSTATE pTaskState, void *pvBuf, size_t cbCopy)
unsigned cSGEntry = 0;
if (!cbCopy)
pSGEntry++;
cSGEntry++;
static void lsilogicR3CopyFromBufferIntoSGList(PPDMDEVINS pDevIns, PLSILOGICTASKSTATESGENTRY pSGInfo)
static void lsilogicR3CopyFromSGListIntoBuffer(PPDMDEVINS pDevIns, PLSILOGICTASKSTATESGENTRY pSGInfo)
static int lsilogicR3ScatterGatherListAllocate(PLSILOGICTASKSTATE pTaskState, uint32_t cSGList, uint32_t cSGInfo, uint32_t cbUnaligned)
return VERR_NO_MEMORY;
pTaskState->paSGEntries = (PLSILOGICTASKSTATESGENTRY)RTMemAllocZ(cSGInfo * sizeof(LSILOGICTASKSTATESGENTRY));
return VERR_NO_MEMORY;
return VERR_NO_MEMORY;
# ifdef LOG_ENABLED
return VINF_SUCCESS;
pSGInfoCurr++;
# ifdef LOG_ENABLED
if (LogIsEnabled())
case MPTSGENTRYTYPE_SIMPLE:
Log(("%s: u32DataBufferAddressLow=%u\n", __FUNCTION__, pSGEntry->Simple32.u32DataBufferAddressLow));
Log(("%s: u32DataBufferAddressHigh=%u\n", __FUNCTION__, pSGEntry->Simple64.u32DataBufferAddressHigh));
case MPTSGENTRYTYPE_CHAIN:
bool fDoMapping = false;
bool fEndOfList;
fUnaligned = false;
cbUnaligned = 0;
fEndOfList = false;
if (fDoMapping)
while (!fEndOfList)
bool fEndOfSegment = false;
while (!fEndOfSegment)
# ifdef LOG_ENABLED
return VINF_SUCCESS;
if (fDoMapping)
if (fBufferContainsData)
pSGInfoCurr++;
cSGInfo++;
fEndOfSegment = true;
fEndOfList = true;
fEndOfSegment = true;
if (uChainOffsetNext)
PDMDevHlpPhysRead(pDevIns, GCPhysSegmentStart + uChainOffsetNext, &SGEntryChain, sizeof(MptSGEntryChain));
fDoMapping = true;
if (fUnaligned)
pSGInfoCurr++;
pSGEntryCurr++;
cSGEntries++;
pSGInfoCurr++;
return rc;
* @note Current assumption is that the sense buffer is not scattered and does not cross a page boundary.
# ifdef RT_STRICT
rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, GCPhysAddrSenseBufferBase, (void **)&pTaskState->pbSenseBuffer, &pTaskState->PageLockSense);
return rc;
# ifdef LOG_ENABLED
if (LogIsEnabled())
Log(("%s: u32SenseBufferLowAddress=%#x\n", __FUNCTION__, pSCSIIORequest->u32SenseBufferLowAddress));
int rc;
rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_DISKFULL",
N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
int rc;
rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_FILETOOBIG",
N_("Host system reported that the file size limit of the host file system has been exceeded. VM execution is suspended. You need to move your virtual hard disk to a filesystem which allows bigger files"));
int rc;
rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_ISCSIDOWN",
N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
int rc2;
LogRel(("LsiLogic#%d: Unknown but recoverable error has occurred (rc=%Rrc)\n", pDevIns->iInstance, rc));
rc2 = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_UNKNOWN",
N_("An unknown but recoverable I/O error has occurred (rc=%Rrc). VM execution is suspended. You can resume when the error is fixed"), rc);
# ifdef LOG_ENABLED
if (uChainOffset)
uint8_t uDataDirection = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pTaskState->GuestRequest.SCSIIO.u32Control);
rc = pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTargetDevice->pDrvSCSIConnector, &pTaskState->PDMScsiRequest);
return VINF_SUCCESS;
static int g_cLogged = 0;
pTaskState->IOCReply.SCSIIOError.u8SenseBufferLength = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength;
pTaskState->IOCReply.SCSIIOError.u32MessageContext = pTaskState->GuestRequest.SCSIIO.u32MessageContext;
return rc;
static DECLCALLBACK(int) lsilogicR3DeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
if (fRedo)
RT_UNLIKELY(pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength < pTaskState->PDMScsiRequest.cbSenseBuffer)
pTaskState->IOCReply.SCSIIOError.u8SenseBufferLength = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength;
pTaskState->IOCReply.SCSIIOError.u32MessageContext = pTaskState->GuestRequest.SCSIIO.u32MessageContext;
return VINF_SUCCESS;
static DECLCALLBACK(int) lsilogicR3QueryDeviceLocation(PPDMISCSIPORT pInterface, const char **ppcszController,
return VINF_SUCCESS;
switch (u8PageNumber)
return rc;
switch (u8PageNumber)
return rc;
switch (u8PageNumber)
return rc;
switch (u8PageNumber)
return rc;
return VERR_NOT_FOUND;
switch (u8PageNumber)
return rc;
return VERR_NOT_FOUND;
return VERR_NOT_FOUND;
switch (u8PageNumber)
*ppPageHeader = &pPages->u.SpiPages.aBuses[u8Bus].aDevicePages[u8TargetID].SCSISPIDevicePage0.u.fields.Header;
*ppbPageData = pPages->u.SpiPages.aBuses[u8Bus].aDevicePages[u8TargetID].SCSISPIDevicePage0.u.abPageData;
*ppPageHeader = &pPages->u.SpiPages.aBuses[u8Bus].aDevicePages[u8TargetID].SCSISPIDevicePage1.u.fields.Header;
*ppbPageData = pPages->u.SpiPages.aBuses[u8Bus].aDevicePages[u8TargetID].SCSISPIDevicePage1.u.abPageData;
*ppPageHeader = &pPages->u.SpiPages.aBuses[u8Bus].aDevicePages[u8TargetID].SCSISPIDevicePage2.u.fields.Header;
*ppbPageData = pPages->u.SpiPages.aBuses[u8Bus].aDevicePages[u8TargetID].SCSISPIDevicePage2.u.abPageData;
*ppPageHeader = &pPages->u.SpiPages.aBuses[u8Bus].aDevicePages[u8TargetID].SCSISPIDevicePage3.u.fields.Header;
*ppbPageData = pPages->u.SpiPages.aBuses[u8Bus].aDevicePages[u8TargetID].SCSISPIDevicePage3.u.abPageData;
return rc;
switch (u8PageNumber)
return rc;
return VERR_NOT_FOUND;
return VERR_NOT_FOUND;
if (pPHYPages)
switch (u8PageNumber)
return rc;
if (uAddressForm == 0)
while ( pSASDevice
if (pSASDevice)
while ( pSASDevice
while ( pSASDevice
if (pSASDevice)
switch (u8PageNumber)
return rc;
static int lsilogicR3ConfigurationPageGetExtended(PLSILOGICSCSI pThis, PMptConfigurationRequest pConfigurationReq,
return rc;
static int lsilogicR3ProcessConfigurationRequest(PLSILOGICSCSI pThis, PMptConfigurationRequest pConfigurationReq,
switch (u8PageType)
return VINF_SUCCESS;
case MPT_CONFIGURATION_REQUEST_ACTION_DEFAULT: /* Nothing to do. We are always using the defaults. */
if (cbBuffer != 0)
GCPhysAddrPageBuffer |= (uint64_t)pConfigurationReq->SimpleSGElement.u32DataBufferAddressHigh << 32;
if (cbBuffer != 0)
GCPhysAddrPageBuffer |= (uint64_t)pConfigurationReq->SimpleSGElement.u32DataBufferAddressHigh << 32;
return VINF_SUCCESS;
AssertMsg(pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI, ("Controller is not the SPI SCSI one\n"));
pPages->aPortPages[i].SCSISPIPortPage0.u.fields.Header.u8PageType = MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY
pPages->aPortPages[i].SCSISPIPortPage0.u.fields.Header.u8PageLength = sizeof(MptConfigurationPageSCSISPIPort0) / 4;
pPages->aPortPages[i].SCSISPIPortPage1.u.fields.Header.u8PageType = MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE
pPages->aPortPages[i].SCSISPIPortPage1.u.fields.Header.u8PageLength = sizeof(MptConfigurationPageSCSISPIPort1) / 4;
pPages->aPortPages[i].SCSISPIPortPage2.u.fields.Header.u8PageType = MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE
pPages->aPortPages[i].SCSISPIPortPage2.u.fields.Header.u8PageLength = sizeof(MptConfigurationPageSCSISPIPort2) / 4;
for (unsigned iDevice = 0; iDevice < RT_ELEMENTS(pPages->aPortPages[i].SCSISPIPortPage2.u.fields.aDeviceSettings); iDevice++)
for (unsigned uDeviceCurr = 0; uDeviceCurr < RT_ELEMENTS(pPages->aBuses[uBusCurr].aDevicePages); uDeviceCurr++)
pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr].SCSISPIDevicePage0.u.fields.Header.u8PageType = MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY
pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr].SCSISPIDevicePage0.u.fields.Header.u8PageNumber = 0;
pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr].SCSISPIDevicePage0.u.fields.Header.u8PageLength = sizeof(MptConfigurationPageSCSISPIDevice0) / 4;
pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr].SCSISPIDevicePage1.u.fields.Header.u8PageType = MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE
pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr].SCSISPIDevicePage1.u.fields.Header.u8PageNumber = 1;
pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr].SCSISPIDevicePage1.u.fields.Header.u8PageLength = sizeof(MptConfigurationPageSCSISPIDevice1) / 4;
pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr].SCSISPIDevicePage2.u.fields.Header.u8PageType = MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE
pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr].SCSISPIDevicePage2.u.fields.Header.u8PageNumber = 2;
pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr].SCSISPIDevicePage2.u.fields.Header.u8PageLength = sizeof(MptConfigurationPageSCSISPIDevice2) / 4;
pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr].SCSISPIDevicePage3.u.fields.Header.u8PageType = MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY
pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr].SCSISPIDevicePage3.u.fields.Header.u8PageNumber = 3;
pPages->aBuses[uBusCurr].aDevicePages[uDeviceCurr].SCSISPIDevicePage3.u.fields.Header.u8PageLength = sizeof(MptConfigurationPageSCSISPIDevice3) / 4;
return u16Handle;
AssertMsg(pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SAS, ("Controller is not the SAS SCSI one\n"));
PMptConfigurationPageManufacturing7 pManufacturingPage7 = (PMptConfigurationPageManufacturing7)RTMemAllocZ(pPages->cbManufacturingPage7);
PMptConfigurationPageSASIOUnit0 pSASPage0 = (PMptConfigurationPageSASIOUnit0)RTMemAllocZ(pPages->cbSASIOUnitPage0);
PMptConfigurationPageSASIOUnit1 pSASPage1 = (PMptConfigurationPageSASIOUnit1)RTMemAllocZ(pPages->cbSASIOUnitPage1);
pPages->SASIOUnitPage2.u.fields.ExtHeader.u8ExtPageType = MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASIOUNIT;
pPages->SASIOUnitPage2.u.fields.ExtHeader.u16ExtPageLength = sizeof(MptConfigurationPageSASIOUnit2) / 4;
pPages->SASIOUnitPage3.u.fields.ExtHeader.u8ExtPageType = MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASIOUNIT;
pPages->SASIOUnitPage3.u.fields.ExtHeader.u16ExtPageLength = sizeof(MptConfigurationPageSASIOUnit3) / 4;
pSASPage0->u.fields.aPHY[i].u32ControllerPhyDeviceInfo = LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_SET(LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_NO);
pSASPage1->u.fields.aPHY[i].u8MaxMinLinkRate = LSILOGICSCSI_SASIOUNIT1_LINK_RATE_MIN_SET(LSILOGICSCSI_SASIOUNIT1_LINK_RATE_15GB)
pSASPage1->u.fields.aPHY[i].u32ControllerPhyDeviceInfo = LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_SET(LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_NO);
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.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)
pPHYPages->SASPHYPage0.u.fields.u8HwLinkRate = LSILOGICSCSI_SASIOUNIT1_LINK_RATE_MIN_SET(LSILOGICSCSI_SASIOUNIT1_LINK_RATE_15GB)
pPHYPages->SASPHYPage1.u.fields.ExtHeader.u8ExtPageType = MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASPHYS;
pPHYPages->SASPHYPage1.u.fields.ExtHeader.u16ExtPageLength = sizeof(MptConfigurationPageSASPHY1) / 4;
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)
pSASPage1->u.fields.aPHY[i].u32ControllerPhyDeviceInfo = LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_SET(LSILOGICSCSI_SASIOUNIT0_DEVICE_TYPE_END)
pPHYPages->SASPHYPage0.u.fields.u32AttachedDeviceInfo = LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_SET(LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_END);
pSASDevice->SASDevicePage0.u.fields.ExtHeader.u8PageType = MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY
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.u32DeviceInfo = LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_SET(LSILOGICSCSI_SASPHY0_DEV_INFO_DEVICE_TYPE_END)
pSASDevice->SASDevicePage1.u.fields.ExtHeader.u8PageType = MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY
pSASDevice->SASDevicePage1.u.fields.ExtHeader.u8ExtPageType = MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASDEVICE;
pSASDevice->SASDevicePage1.u.fields.ExtHeader.u16ExtPageLength = sizeof(MptConfigurationPageSASDevice1) / 4;
pSASDevice->SASDevicePage2.u.fields.ExtHeader.u8PageType = MPT_CONFIGURATION_PAGE_ATTRIBUTE_READONLY
pSASDevice->SASDevicePage2.u.fields.ExtHeader.u8ExtPageType = MPT_CONFIGURATION_PAGE_TYPE_EXTENDED_SASDEVICE;
pSASDevice->SASDevicePage2.u.fields.ExtHeader.u16ExtPageLength = sizeof(MptConfigurationPageSASDevice2) / 4;
PMptConfigurationPagesSupported pPages = (PMptConfigurationPagesSupported)RTMemAllocZ(sizeof(MptConfigurationPagesSupported));
static DECLCALLBACK(bool) lsilogicR3NotifyQueueConsumer(PPDMDEVINS pDevIns, PPDMQUEUEITEMCORE pItem)
uint32_t u32RequestMessageFrameDesc = pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextAddressRead];
PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pTaskState->GuestRequest, sizeof(MptMessageHdr));
if (cbRequest != 0)
return rc;
static DECLCALLBACK(int) lsilogicR3IsaIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return rc;
int rc;
rc = pTaskState->pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTaskState->pTargetDevice->pDrvSCSIConnector,
return VINF_SUCCESS;
ScsiInquiryData.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED;
return rc;
static DECLCALLBACK(int) lsilogicR3IsaIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
Log2(("#%d %s: pvUser=%#p cb=%d u32=%#x Port=%#x\n", pDevIns->iInstance, __FUNCTION__, pvUser, cb, u32, Port));
return VINF_SUCCESS;
static DECLCALLBACK(int) lsilogicR3IsaIOPortWriteStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port,
return rc;
static DECLCALLBACK(int) lsilogicR3IsaIOPortReadStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst,
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
static DECLCALLBACK(void) lsilogicR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
bool fVerbose = false;
if (pszArgs)
pHlp->pfnPrintf(pHlp, "uReplyFreeQueueNextEntryFreeWrite=%u\n", pThis->uReplyFreeQueueNextEntryFreeWrite);
pHlp->pfnPrintf(pHlp, "uReplyFreeQueueNextAddressRead=%u\n", pThis->uReplyFreeQueueNextAddressRead);
pHlp->pfnPrintf(pHlp, "uReplyPostQueueNextEntryFreeWrite=%u\n", pThis->uReplyPostQueueNextEntryFreeWrite);
pHlp->pfnPrintf(pHlp, "uReplyPostQueueNextAddressRead=%u\n", pThis->uReplyPostQueueNextAddressRead);
pHlp->pfnPrintf(pHlp, "uRequestQueueNextEntryFreeWrite=%u\n", pThis->uRequestQueueNextEntryFreeWrite);
if (fVerbose)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
return VINF_SSM_DONT_CALL_AGAIN;
SSMR3PutMem(pSSM, &pSpiPages->aPortPages[0].SCSISPIPortPage0, sizeof(MptConfigurationPageSCSISPIPort0));
SSMR3PutMem(pSSM, &pSpiPages->aPortPages[0].SCSISPIPortPage1, sizeof(MptConfigurationPageSCSISPIPort1));
SSMR3PutMem(pSSM, &pSpiPages->aPortPages[0].SCSISPIPortPage2, sizeof(MptConfigurationPageSCSISPIPort2));
SSMR3PutMem(pSSM, &pSpiPages->aBuses[0].aDevicePages[i].SCSISPIDevicePage0, sizeof(MptConfigurationPageSCSISPIDevice0));
SSMR3PutMem(pSSM, &pSpiPages->aBuses[0].aDevicePages[i].SCSISPIDevicePage1, sizeof(MptConfigurationPageSCSISPIDevice1));
SSMR3PutMem(pSSM, &pSpiPages->aBuses[0].aDevicePages[i].SCSISPIDevicePage2, sizeof(MptConfigurationPageSCSISPIDevice2));
SSMR3PutMem(pSSM, &pSpiPages->aBuses[0].aDevicePages[i].SCSISPIDevicePage3, sizeof(MptConfigurationPageSCSISPIDevice3));
while (pCurr)
return VINF_SUCCESS;
static DECLCALLBACK(int) lsilogicR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
int rc;
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Target config mismatch (Controller type): config=%d state=%d"),
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Target config mismatch (Device states): config=%u state=%u"),
bool fPresent;
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Target %u config mismatch: config=%RTbool state=%RTbool"),
return VINF_SUCCESS;
return rc;
sizeof(MptConfigurationPagesSupported_SSM_V2));
pSpiPages->aBuses[0].aDevicePages[i].SCSISPIDevicePage0 = ConfigPagesV2.aBuses[0].aDevicePages[i].SCSISPIDevicePage0;
pSpiPages->aBuses[0].aDevicePages[i].SCSISPIDevicePage1 = ConfigPagesV2.aBuses[0].aDevicePages[i].SCSISPIDevicePage1;
pSpiPages->aBuses[0].aDevicePages[i].SCSISPIDevicePage2 = ConfigPagesV2.aBuses[0].aDevicePages[i].SCSISPIDevicePage2;
pSpiPages->aBuses[0].aDevicePages[i].SCSISPIDevicePage3 = ConfigPagesV2.aBuses[0].aDevicePages[i].SCSISPIDevicePage3;
SSMR3GetMem(pSSM, &pSpiPages->aPortPages[0].SCSISPIPortPage0, sizeof(MptConfigurationPageSCSISPIPort0));
SSMR3GetMem(pSSM, &pSpiPages->aPortPages[0].SCSISPIPortPage1, sizeof(MptConfigurationPageSCSISPIPort1));
SSMR3GetMem(pSSM, &pSpiPages->aPortPages[0].SCSISPIPortPage2, sizeof(MptConfigurationPageSCSISPIPort2));
SSMR3GetMem(pSSM, &pSpiPages->aBuses[0].aDevicePages[i].SCSISPIDevicePage0, sizeof(MptConfigurationPageSCSISPIDevice0));
SSMR3GetMem(pSSM, &pSpiPages->aBuses[0].aDevicePages[i].SCSISPIDevicePage1, sizeof(MptConfigurationPageSCSISPIDevice1));
SSMR3GetMem(pSSM, &pSpiPages->aBuses[0].aDevicePages[i].SCSISPIDevicePage2, sizeof(MptConfigurationPageSCSISPIDevice2));
SSMR3GetMem(pSSM, &pSpiPages->aBuses[0].aDevicePages[i].SCSISPIDevicePage3, sizeof(MptConfigurationPageSCSISPIDevice3));
return VERR_SSM_LOAD_CONFIG_MISMATCH;
return VERR_SSM_LOAD_CONFIG_MISMATCH;
return rc;
return VINF_SUCCESS;
static DECLCALLBACK(int) lsilogicR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
if (iLUN == 0)
return VINF_SUCCESS;
return VERR_PDM_LUN_NOT_FOUND;
static DECLCALLBACK(void *) lsilogicR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
return NULL;
static DECLCALLBACK(int) lsilogicR3StatusQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
return VINF_SUCCESS;
return VERR_PDM_LUN_NOT_FOUND;
static DECLCALLBACK(void *) lsilogicR3StatusQueryInterface(PPDMIBASE pInterface, const char *pszIID)
return NULL;
while (pTaskState)
int rc;
return VERR_PDM_LUN_NOT_FOUND;
AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
return rc;
int rc;
return VINF_SUCCESS;
char *pszCtrlType;
bool fBootable;
# ifdef VBOX_WITH_MSI_DEVICES
return PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic: cannot create critical section for reply free queue"));
return PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic: cannot create critical section for reply post queue"));
return rc;
# ifdef VBOX_WITH_MSI_DEVICES
rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, LSILOGIC_PCI_SPACE_IO_SIZE, PCI_ADDRESS_SPACE_IO, lsilogicR3Map);
return rc;
rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, LSILOGIC_PCI_SPACE_MEM_SIZE, PCI_ADDRESS_SPACE_MEM, lsilogicR3Map);
return rc;
rc = PDMDevHlpPCIIORegionRegister(pDevIns, 2, LSILOGIC_PCI_SPACE_MEM_SIZE, PCI_ADDRESS_SPACE_MEM, lsilogicR3Map);
return rc;
return rc;
return rc;
pThis->paDeviceStates = (PLSILOGICDEVICE)RTMemAllocZ(sizeof(LSILOGICDEVICE) * pThis->cDeviceStates);
AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE);
return rc;
if (fBootable)
return rc;
sizeof(LSILOGICSCSI),
NULL,
NULL,
NULL,
NULL,
NULL,
sizeof(LSILOGICSCSI),
NULL,
NULL,
NULL,
NULL,
NULL,