/******************************************************************************* *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved. * *Redistribution and use in source and binary forms, with or without modification, are permitted provided *that the following conditions are met: *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the *following disclaimer. *2. Redistributions in binary form must reproduce the above copyright notice, *this list of conditions and the following disclaimer in the documentation and/or other materials provided *with the distribution. * *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE * * $FreeBSD$ * ********************************************************************************/ /*******************************************************************************/ /*! \file mpi.h * \brief The file defines the MPI constants and structures * * The file defines the MPI constants and structures * */ /*******************************************************************************/ #ifndef __MPI_H__ #define __MPI_H__ /*******************************************************************************/ /*******************************************************************************/ /* CONSTANTS */ /*******************************************************************************/ /*******************************************************************************/ #define MPI_QUEUE_PRIORITY_HIGHEST 0xFF /**< Highest queue priority */ #define MPI_QUEUE_PRIORITY_LOWEST 0x00 /**< Lowest queue priority */ #define MPI_MAX_INBOUND_QUEUES 64 /**< Maximum number of inbound queues */ #define MPI_MAX_OUTBOUND_QUEUES 64 /**< Maximum number of outbound queues */ /**< Max # of memory chunks supported */ #define MPI_MAX_MEM_REGIONS (MPI_MAX_INBOUND_QUEUES + MPI_MAX_OUTBOUND_QUEUES) + 4 #define MPI_LOGSIZE 4096 /**< default size */ #define MPI_IB_NUM_MASK 0x0000FFFF /**< Mask of Inbound Queue Number */ #define MPI_OB_NUM_MASK 0xFFFF0000 /**< Mask of Outbound Queue Number */ #define MPI_OB_SHIFT 16 /**< bits shift for outbound queue number */ #define BAR0 0x10 #define BAR1 0x14 #define BAR2 0x18 #define BAR3 0x1C #define BAR4 0x20 #define BAR5 0x24 /*******************************************************************************/ /*******************************************************************************/ /* ENUMERATIONS */ /*******************************************************************************/ /*******************************************************************************/ /*******************************************************************************/ /** \enum mpiMsgCategory_e, * \brief MPI message categories */ /*******************************************************************************/ enum mpiMsgCategory_e { MPI_CATEGORY_ETHERNET = 0, MPI_CATEGORY_FC, MPI_CATEGORY_SAS_SATA, MPI_CATEGORY_SCSI }; typedef enum mpiMsgCategory_e mpiMsgCategory_t; /*******************************************************************************/ /*******************************************************************************/ /* TYPES */ /*******************************************************************************/ /*******************************************************************************/ /*******************************************************************************/ /*******************************************************************************/ /* DATA STRUCTURES */ /*******************************************************************************/ /*******************************************************************************/ /*******************************************************************************/ /** \struct mpiMem_s * \brief Structure that descibes memory regions * * The mpiMemoryDescriptor_t is used to describe the attributes for a memory * region. Each element in the memory chunk has to be physically contiguous. * Different elements in the memory chunk do not necessarily have to be * contiguous to each other. */ /*******************************************************************************/ struct mpiMem_s { void* virtPtr; /**< Virtual pointer to the memory region */ void* appHandle; /**< Handle used for the application to free memory */ bit32 physAddrUpper; /**< Upper 32 bits of physical address */ bit32 physAddrLower; /**< Lower 32 bits of physical address */ bit32 totalLength; /**< Total length in bytes allocated */ bit32 numElements; /**< Number of elements */ bit32 elementSize; /**< Size in bytes of an element */ bit32 alignment; /**< Alignment in bytes needed. A value of one indicates */ /**< no specific alignment requirement */ bit32 type; /**< Memory type */ bit32 reserved; /**< Reserved */ }; typedef struct mpiMem_s mpiMem_t; /*******************************************************************************/ /** \struct mpiMemReq_s * \brief Describes MPI memory requirements * * The mpiMemRequirements_t is used to specify the memory allocation requirement * for the MPI. This is the data structure used in the mpiGetRequirements() * and the mpiInitialize() function calls */ /*******************************************************************************/ struct mpiMemReq_s { bit32 count; /**< The number of element in the mpiMemory array */ mpiMem_t region[MPI_MAX_MEM_REGIONS]; /**< Pointer to the array of structures that define memroy regions */ }; typedef struct mpiMemReq_s mpiMemReq_t; /*******************************************************************************/ /** \struct mpiQCQueue_s * \brief Circular Queue descriptor * * This structure holds outbound circular queue attributes. */ /*******************************************************************************/ struct mpiOCQueue_s { bit32 qNumber; /**< this queue number */ bit32 numElements; /**< The total number of queue elements. A value 0 disables the queue */ bit32 elementSize; /**< The size of each queue element, in bytes */ bit32 priority; /**< The queue priority. Possible values for this field are */ /**< MPI_QUEUE_PRIORITY_HIGHEST and MPI_QUEUE_PRIORITY_LOWEST */ bit32 CIPCIBar; /**< PCI Bar */ bit32 CIPCIOffset; /**< PCI Offset */ bit32 DIntTOffset; /**< Dynamic Interrupt Coalescing Timeout offset */ void* piPointer; /**< pointer of PI (virtual address)*/ mpiMem_t memoryRegion; /**< Queue's memory region descriptor */ bit32 producerIdx; /**< Copy of the producer index */ bit32 consumerIdx; /**< Copy of the consumer index */ bit32 pcibar; /**< CPI Logical Bar Number */ agsaRoot_t *agRoot; /**< Pointer of LL Layer structure */ }; typedef struct mpiOCQueue_s mpiOCQueue_t; /*******************************************************************************/ /** \struct mpiICQueue_s * \brief Circular Queue descriptor * * This structure holds inbound circular queue attributes. */ /*******************************************************************************/ struct mpiICQueue_s { bit32 qNumber; /**< this queue number */ bit32 numElements; /**< The total number of queue elements. A value 0 disables the queue */ bit32 elementSize; /**< The size of each queue element, in bytes */ bit32 priority; /**< The queue priority. Possible values for this field are */ /**< MPI_QUEUE_PRIORITY_HIGHEST and MPI_QUEUE_PRIORITY_LOWEST */ bit32 PIPCIBar; /**< PCI Bar */ bit32 PIPCIOffset; /**< PCI Offset */ void* ciPointer; /**< Pointer of CI (virtual Address) */ mpiMem_t memoryRegion; /**< Queue's memory region descriptor */ bit32 producerIdx; /**< Copy of the producer index */ bit32 consumerIdx; /**< Copy of the consumer index */ #ifdef SA_FW_TEST_BUNCH_STARTS bit32 BunchStarts_QPending; // un-started bunched IOs on queue bit32 BunchStarts_QPendingTick; // tick value when 1st IO is bunched #endif /* SA_FW_TEST_BUNCH_STARTS */ agsaRoot_t *agRoot; /**< Pointer of LL Layer structure */ }; typedef struct mpiICQueue_s mpiICQueue_t; struct mpiHostLLConfigDescriptor_s { bit32 regDumpPCIBAR; bit32 iQNPPD_HPPD_GEvent; /**< inbound Queue Process depth */ /* bit0-7 inbound normal priority process depth */ /* bit8-15 inbound high priority process depth */ /* bit16-23 OQ number to receive GENERAL_EVENT Notification */ /* bit24-31 reserved */ bit32 outboundHWEventPID0_3; /**< outbound HW event for PortId 0 to 3 */ /* bit0-7 outbound queue number of SAS_HW event for PortId 0 */ /* bit8-15 outbound queue number of SAS_HW event for PortId 1 */ /* bit16-23 outbound queue number of SAS_HW event for PortId 2 */ /* bit24-31 outbound queue number of SAS_HW event for PortId 3 */ bit32 outboundHWEventPID4_7; /**< outbound HW event for PortId 4 to 7 */ /* bit0-7 outbound queue number of SAS_HW event for PortId 4 */ /* bit8-15 outbound queue number of SAS_HW event for PortId 5 */ /* bit16-23 outbound queue number of SAS_HW event for PortId 6 */ /* bit24-31 outbound queue number of SAS_HW event for PortId 7 */ bit32 outboundNCQEventPID0_3; /**< outbound NCQ event for PortId 0 to 3 */ /* bit0-7 outbound queue number of SATA_NCQ event for PortId 0 */ /* bit8-15 outbound queue number of SATA_NCQ event for PortId 1 */ /* bit16-23 outbound queue number of SATA_NCQ event for PortId 2 */ /* bit24-31 outbound queue number of SATA_NCQ event for PortId 3 */ bit32 outboundNCQEventPID4_7; /**< outbound NCQ event for PortId 4 to 7 */ /* bit0-7 outbound queue number of SATA_NCQ event for PortId 4 */ /* bit8-15 outbound queue number of SATA_NCQ event for PortId 5 */ /* bit16-23 outbound queue number of SATA_NCQ event for PortId 6 */ /* bit24-31 outbound queue number of SATA_NCQ event for PortId 7 */ bit32 outboundTargetITNexusEventPID0_3; /**< outbound target ITNexus Event for PortId 0 to 3 */ /* bit0-7 outbound queue number of ITNexus event for PortId 0 */ /* bit8-15 outbound queue number of ITNexus event for PortId 1 */ /* bit16-23 outbound queue number of ITNexus event for PortId 2 */ /* bit24-31 outbound queue number of ITNexus event for PortId 3 */ bit32 outboundTargetITNexusEventPID4_7; /**< outbound target ITNexus Event for PortId 4 to 7 */ /* bit0-7 outbound queue number of ITNexus event for PortId 4 */ /* bit8-15 outbound queue number of ITNexus event for PortId 5 */ /* bit16-23 outbound queue number of ITNexus event for PortId 6 */ /* bit24-31 outbound queue number of ITNexus event for PortId 7 */ bit32 outboundTargetSSPEventPID0_3; /**< outbound target SSP event for PordId 0 to 3 */ /* bit0-7 outbound queue number of SSP event for PortId 0 */ /* bit8-15 outbound queue number of SSP event for PortId 1 */ /* bit16-23 outbound queue number of SSP event for PortId 2 */ /* bit24-31 outbound queue number of SSP event for PortId 3 */ bit32 outboundTargetSSPEventPID4_7; /**< outbound target SSP event for PordId 4 to 7 */ /* bit0-7 outbound queue number of SSP event for PortId 4 */ /* bit8-15 outbound queue number of SSP event for PortId 5 */ /* bit16-23 outbound queue number of SSP event for PortId 6 */ /* bit24-31 outbound queue number of SSP event for PortId 7 */ bit32 ioAbortDelay; /* was reserved */ /**< io Abort delay MPI_TABLE_CHANGE */ bit32 custset; /**< custset */ bit32 upperEventLogAddress; /**< Upper physical MSGU Event log address */ bit32 lowerEventLogAddress; /**< Lower physical MSGU Event log address */ bit32 eventLogSize; /**< Size of MSGU Event log, 0 means log disable */ bit32 eventLogOption; /**< Option of MSGU Event log */ /* bit3-0 log severity, 0x0 Disable Logging */ /* 0x1 Critical Error */ /* 0x2 Minor Error */ /* 0x3 Warning */ /* 0x4 Information */ /* 0x5 Debugging */ /* 0x6 - 0xF Reserved */ bit32 upperIOPeventLogAddress; /**< Upper physical IOP Event log address */ bit32 lowerIOPeventLogAddress; /**< Lower physical IOP Event log address */ bit32 IOPeventLogSize; /**< Size of IOP Event log, 0 means log disable */ bit32 IOPeventLogOption; /**< Option of IOP Event log */ /* bit3-0 log severity, 0x0 Disable Logging */ /* 0x1 Critical Error */ /* 0x2 Minor Error */ /* 0x3 Warning */ /* 0x4 Information */ /* 0x5 Debugging */ /* 0x6 - 0xF Reserved */ bit32 FatalErrorInterrupt; /**< Fatal Error Interrupt enable and vector */ /* bit0 Fatal Error Interrupt Enable */ /* bit1 PI/CI Address */ /* bit5 enable or disable outbound coalesce */ /* bit7-6 reserved */ /* bit15-8 Fatal Error Interrupt Vector */ /* bit31-16 Reserved */ bit32 FatalErrorDumpOffset0; /**< Fatal Error Register Dump Offset for MSGU */ bit32 FatalErrorDumpLength0; /**< Fatal Error Register Dump Length for MSGU */ bit32 FatalErrorDumpOffset1; /**< Fatal Error Register Dump Offset for IOP */ bit32 FatalErrorDumpLength1; /**< Fatal Error Register Dump Length for IOP */ bit32 HDAModeFlags; /**< HDA Mode Flags */ /* bit1-0 Bootstrap pins */ /* bit2 Force HDA Mode bit */ /* bit3 HDA Firmware load method */ bit32 analogSetupTblOffset; /**< Phy Calibration Table offset */ /* bit23-0 phy calib table offset */ /* bit31-24 entry size */ bit32 InterruptVecTblOffset; /**< DW23 Interrupt Vector Table */ /* bit23-0 interrupt vector table offset */ /* bit31-24 entry size */ bit32 phyAttributeTblOffset; /**< DW24 SAS Phy Attribute Table Offset */ /* bit23-0 phy attribute table offset */ /* bit31-24 entry size */ bit32 PortRecoveryTimerPortResetTimer; /**< DW25 Port Recovery Timer and Port Reset Timer */ bit32 InterruptReassertionDelay; /**< DW26 Interrupt Reassertion Delay 0:23 Reserved 24:31 */ }; typedef struct mpiHostLLConfigDescriptor_s mpiHostLLConfigDescriptor_t; /*******************************************************************************/ /** \struct mpiInboundQueueDescriptor_s * \brief MPI inbound queue attributes * * The mpiInboundQueueDescriptor_t structure is used to describe an inbound queue * attributes */ /*******************************************************************************/ struct mpiInboundQueueDescriptor_s { bit32 numElements; /**< The total number of queue elements. A value 0 disables the queue */ bit32 elementSize; /**< The size of each queue element, in bytes */ bit32 priority; /**< The queue priority. Possible values for this field are */ /**< MPI_QUEUE_PRIORITY_HIGHEST and MPI_QUEUE_PRIORITY_LOWEST */ bit32 PIPCIBar; /**< PI PCIe Bar */ bit32 PIOffset; /**< PI PCI Bar Offset */ void* ciPointer; /**< Pointer of CI (virtual Address) */ }; typedef struct mpiInboundQueueDescriptor_s mpiInboundQueueDescriptor_t; /*******************************************************************************/ /** \struct mpiOutboundQueueDescriptor_s * \brief MPI outbound queue attributes * * The mpiOutboundQueueDescriptor_t structure is used to describe an outbound queue * attributes */ /*******************************************************************************/ struct mpiOutboundQueueDescriptor_s { bit32 numElements; /**< The total number of queue elements. A value 0 disables the queue */ bit32 elementSize; /**< The size of each queue element, in bytes */ bit32 interruptDelay; /**< Delay in microseconds before the interrupt is asserted */ /**< if the interrupt threshold has not been reached */ bit32 interruptThreshold; /**< Number of interrupt events before the interrupt is asserted */ /**< If set to 0, interrupts for this queue are disablec */ bit32 interruptVector; /**< Interrupt vector assigned to this queue */ bit32 CIPCIBar; /**< offset 0x14:PCI BAR for CI Offset */ bit32 CIOffset; /**< offset 0x18:Offset address for outbound queue CI */ bit32 DIntTOffset; /**< Dynamic Interrupt Coalescing Timeout offset */ bit32 interruptEnable; /**< Interrupt enable flag */ void* piPointer; /**< pointer of PI (virtual address)*/ }; typedef struct mpiOutboundQueueDescriptor_s mpiOutboundQueueDescriptor_t; /*******************************************************************************/ /** \struct mpiPhyCalibration_s * \brief MPI Phy Calibration Table * * The mpiPhyCalibration_s structure is used to set Phy Calibration * attributes */ /*******************************************************************************/ struct mpiPhyCalibration_s { bit32 spaReg0; /* transmitter per port configuration 1 SAS_SATA G1 */ bit32 spaReg1; /* transmitter per port configuration 2 SAS_SATA G1*/ bit32 spaReg2; /* transmitter per port configuration 3 SAS_SATA G1*/ bit32 spaReg3; /* transmitter configuration 1 */ bit32 spaReg4; /* reveiver per port configuration 1 SAS_SATA G1G2 */ bit32 spaReg5; /* reveiver per port configuration 2 SAS_SATA G3 */ bit32 spaReg6; /* reveiver per configuration 1 */ bit32 spaReg7; /* reveiver per configuration 2 */ bit32 reserved[2]; /* reserved */ }; typedef struct mpiPhyCalibration_s mpiPhyCalibration_t; #define ANALOG_SETUP_ENTRY_NO 10 #define ANALOG_SETUP_ENTRY_SIZE 10 /*******************************************************************************/ /** \struct mpiConfig_s * \brief MPI layer configuration parameters * * The mpiConfig_s structure is used as a parameter passed in * mpiGetRequirements() and mpiInitialize() to describe the MPI software * configuration */ /*******************************************************************************/ struct mpiVConfig_s { mpiHostLLConfigDescriptor_t mainConfig; /**< main part of configuration table */ mpiInboundQueueDescriptor_t inboundQueues[MPI_MAX_INBOUND_QUEUES]; /**< mpiQueueDescriptor structures that provide initialization */ /**< attributes for the inbound queues. The maximum number of */ /**< inbound queues is MPI_MAX_INBOUND_QUEUES */ mpiOutboundQueueDescriptor_t outboundQueues[MPI_MAX_OUTBOUND_QUEUES]; /**< mpiQueueDescriptor structures that provide initialization */ /**< attributes for the outbound queues. The maximum number of */ /**< inbound queues is MPI_MAX_OUTBOUND_QUEUES */ agsaPhyAnalogSetupTable_t phyAnalogConfig; mpiInterruptVT_t interruptVTable; sasPhyAttribute_t phyAttributeTable; bit16 numInboundQueues; bit16 numOutboundQueues; bit16 maxNumInboundQueues; bit16 maxNumOutboundQueues; bit32 queueOption; }; /*******************************************************************************/ /** \struct mpiConfig_s * \brief MPI layer configuration parameters * * The mpiConfig_s structure is used as a parameter passed in * mpiGetRequirements() and mpiInitialize() to describe the MPI software * configuration */ /*******************************************************************************/ struct mpiConfig_s { mpiHostLLConfigDescriptor_t mainConfig; /**< main part of configuration table */ mpiInboundQueueDescriptor_t inboundQueues[MPI_MAX_INBOUND_QUEUES]; /**< mpiQueueDescriptor structures that provide initialization */ /**< attributes for the inbound queues. The maximum number of */ /**< inbound queues is MPI_MAX_INBOUND_QUEUES */ mpiOutboundQueueDescriptor_t outboundQueues[MPI_MAX_OUTBOUND_QUEUES]; /**< mpiQueueDescriptor structures that provide initialization */ /**< attributes for the outbound queues. The maximum number of */ /**< inbound queues is MPI_MAX_OUTBOUND_QUEUES */ agsaPhyAnalogSetupTable_t phyAnalogConfig; bit16 numInboundQueues; bit16 numOutboundQueues; bit16 maxNumInboundQueues; bit16 maxNumOutboundQueues; bit32 queueOption; }; typedef struct mpiConfig_s mpiConfig_t; #define TX_PORT_CFG1_OFFSET 0x00 #define TX_PORT_CFG2_OFFSET 0x04 #define TX_PORT_CFG3_OFFSET 0x08 #define TX_CFG_OFFSET 0x0c #define RV_PORT_CFG1_OFFSET 0x10 #define RV_PORT_CFG2_OFFSET 0x14 #define RV_CFG1_OFFSET 0x18 #define RV_CFG2_OFFSET 0x1c /*******************************************************************************/ /*******************************************************************************/ /* FUNCTIONS */ /*******************************************************************************/ /*******************************************************************************/ /*******************************************************************************/ void mpiRequirementsGet(mpiConfig_t *config, mpiMemReq_t *memoryRequirement); FORCEINLINE bit32 mpiMsgFreeGet(mpiICQueue_t *circularQ, bit16 messageSize, void** messagePtr); FORCEINLINE bit32 mpiMsgProduce(mpiICQueue_t *circularQ, void* messagePtr, mpiMsgCategory_t category, bit16 opCode, bit8 responseQueue, bit8 hiPriority); #ifdef LOOPBACK_MPI GLOBAL bit32 mpiMsgProduceOQ(mpiOCQueue_t *circularQ, void *messagePtr, mpiMsgCategory_t category, bit16 opCode, bit8 responseQueue, bit8 hiPriority); GLOBAL bit32 mpiMsgFreeGetOQ(mpiOCQueue_t *circularQ, bit16 messageSize, void** messagePtr); #endif #ifdef FAST_IO_TEST bit32 mpiMsgPrepare(mpiICQueue_t *circularQ, void* messagePtr, mpiMsgCategory_t category, bit16 opCode, bit8 responseQueue, bit8 hiPriority); bit32 mpiMsgProduceSend(mpiICQueue_t *circularQ, void* messagePtr, mpiMsgCategory_t category, bit16 opCode, bit8 responseQueue, bit8 hiPriority, int sendFl); GLOBAL void mpiIBQMsgSend(mpiICQueue_t *circularQ); #define INQ(queueNum) (bit8)(queueNum & MPI_IB_NUM_MASK) #define OUQ(queueNum) (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT) #endif FORCEINLINE bit32 mpiMsgConsume(mpiOCQueue_t *circularQ, void** messagePtr1, mpiMsgCategory_t *pCategory, bit16* pOpCode, bit8 *pBC); FORCEINLINE bit32 mpiMsgFreeSet(mpiOCQueue_t *circularQ, void* messagePtr1, bit8 bc); #endif /* __MPI_H__ */