diff --git a/sys/dev/mpi3mr/mpi/mpi30_api.h b/sys/dev/mpi3mr/mpi/mpi30_api.h index aa7b54ec470e..0c070672a16b 100644 --- a/sys/dev/mpi3mr/mpi/mpi30_api.h +++ b/sys/dev/mpi3mr/mpi/mpi30_api.h @@ -1,57 +1,57 @@ /* - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. + * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved. * Support: * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD * */ #ifndef MPI30_API_H #define MPI30_API_H 1 #include "mpi30_type.h" #include "mpi30_transport.h" #include "mpi30_cnfg.h" #include "mpi30_image.h" #include "mpi30_init.h" #include "mpi30_ioc.h" #include "mpi30_pci.h" #include "mpi30_raid.h" #include "mpi30_sas.h" #include "mpi30_targ.h" #include "mpi30_tool.h" #endif /* MPI30_API_H */ diff --git a/sys/dev/mpi3mr/mpi/mpi30_cnfg.h b/sys/dev/mpi3mr/mpi/mpi30_cnfg.h index d1ae2ebfa372..410ed0471f78 100644 --- a/sys/dev/mpi3mr/mpi/mpi30_cnfg.h +++ b/sys/dev/mpi3mr/mpi/mpi30_cnfg.h @@ -1,3839 +1,3935 @@ /* - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. + * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved. * Support: * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD * */ #ifndef MPI30_CNFG_H #define MPI30_CNFG_H 1 /***************************************************************************** * Configuration Page Types * ****************************************************************************/ #define MPI3_CONFIG_PAGETYPE_IO_UNIT (0x00) #define MPI3_CONFIG_PAGETYPE_MANUFACTURING (0x01) #define MPI3_CONFIG_PAGETYPE_IOC (0x02) #define MPI3_CONFIG_PAGETYPE_DRIVER (0x03) #define MPI3_CONFIG_PAGETYPE_SECURITY (0x04) #define MPI3_CONFIG_PAGETYPE_ENCLOSURE (0x11) #define MPI3_CONFIG_PAGETYPE_DEVICE (0x12) #define MPI3_CONFIG_PAGETYPE_SAS_IO_UNIT (0x20) #define MPI3_CONFIG_PAGETYPE_SAS_EXPANDER (0x21) #define MPI3_CONFIG_PAGETYPE_SAS_PHY (0x23) #define MPI3_CONFIG_PAGETYPE_SAS_PORT (0x24) #define MPI3_CONFIG_PAGETYPE_PCIE_IO_UNIT (0x30) #define MPI3_CONFIG_PAGETYPE_PCIE_SWITCH (0x31) #define MPI3_CONFIG_PAGETYPE_PCIE_LINK (0x33) /***************************************************************************** * Configuration Page Attributes * ****************************************************************************/ #define MPI3_CONFIG_PAGEATTR_MASK (0xF0) #define MPI3_CONFIG_PAGEATTR_READ_ONLY (0x00) #define MPI3_CONFIG_PAGEATTR_CHANGEABLE (0x10) #define MPI3_CONFIG_PAGEATTR_PERSISTENT (0x20) /***************************************************************************** * Configuration Page Actions * ****************************************************************************/ #define MPI3_CONFIG_ACTION_PAGE_HEADER (0x00) #define MPI3_CONFIG_ACTION_READ_DEFAULT (0x01) #define MPI3_CONFIG_ACTION_READ_CURRENT (0x02) #define MPI3_CONFIG_ACTION_WRITE_CURRENT (0x03) #define MPI3_CONFIG_ACTION_READ_PERSISTENT (0x04) #define MPI3_CONFIG_ACTION_WRITE_PERSISTENT (0x05) /***************************************************************************** * Configuration Page Addressing * ****************************************************************************/ /**** Device PageAddress Format ****/ #define MPI3_DEVICE_PGAD_FORM_MASK (0xF0000000) #define MPI3_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) #define MPI3_DEVICE_PGAD_FORM_HANDLE (0x20000000) #define MPI3_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF) /**** SAS Expander PageAddress Format ****/ #define MPI3_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000) #define MPI3_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) #define MPI3_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM (0x10000000) #define MPI3_SAS_EXPAND_PGAD_FORM_HANDLE (0x20000000) #define MPI3_SAS_EXPAND_PGAD_PHYNUM_MASK (0x00FF0000) #define MPI3_SAS_EXPAND_PGAD_PHYNUM_SHIFT (16) #define MPI3_SAS_EXPAND_PGAD_HANDLE_MASK (0x0000FFFF) /**** SAS Phy PageAddress Format ****/ #define MPI3_SAS_PHY_PGAD_FORM_MASK (0xF0000000) #define MPI3_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x00000000) #define MPI3_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF) /**** SAS Port PageAddress Format ****/ #define MPI3_SASPORT_PGAD_FORM_MASK (0xF0000000) #define MPI3_SASPORT_PGAD_FORM_GET_NEXT_PORT (0x00000000) #define MPI3_SASPORT_PGAD_FORM_PORT_NUM (0x10000000) #define MPI3_SASPORT_PGAD_PORT_NUMBER_MASK (0x000000FF) /**** Enclosure PageAddress Format ****/ #define MPI3_ENCLOS_PGAD_FORM_MASK (0xF0000000) #define MPI3_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) #define MPI3_ENCLOS_PGAD_FORM_HANDLE (0x10000000) #define MPI3_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF) /**** PCIe Switch PageAddress Format ****/ #define MPI3_PCIE_SWITCH_PGAD_FORM_MASK (0xF0000000) #define MPI3_PCIE_SWITCH_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) #define MPI3_PCIE_SWITCH_PGAD_FORM_HANDLE_PORT_NUM (0x10000000) #define MPI3_PCIE_SWITCH_PGAD_FORM_HANDLE (0x20000000) #define MPI3_PCIE_SWITCH_PGAD_PORTNUM_MASK (0x00FF0000) #define MPI3_PCIE_SWITCH_PGAD_PORTNUM_SHIFT (16) #define MPI3_PCIE_SWITCH_PGAD_HANDLE_MASK (0x0000FFFF) /**** PCIe Link PageAddress Format ****/ #define MPI3_PCIE_LINK_PGAD_FORM_MASK (0xF0000000) #define MPI3_PCIE_LINK_PGAD_FORM_GET_NEXT_LINK (0x00000000) #define MPI3_PCIE_LINK_PGAD_FORM_LINK_NUM (0x10000000) #define MPI3_PCIE_LINK_PGAD_LINKNUM_MASK (0x000000FF) /**** Security PageAddress Format ****/ #define MPI3_SECURITY_PGAD_FORM_MASK (0xF0000000) #define MPI3_SECURITY_PGAD_FORM_GET_NEXT_SLOT (0x00000000) #define MPI3_SECURITY_PGAD_FORM_SLOT_NUM (0x10000000) #define MPI3_SECURITY_PGAD_SLOT_GROUP_MASK (0x0000FF00) #define MPI3_SECURITY_PGAD_SLOT_GROUP_SHIFT (8) #define MPI3_SECURITY_PGAD_SLOT_MASK (0x000000FF) /***************************************************************************** * Configuration Request Message * ****************************************************************************/ typedef struct _MPI3_CONFIG_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U8 PageVersion; /* 0x0C */ U8 PageNumber; /* 0x0D */ U8 PageType; /* 0x0E */ U8 Action; /* 0x0F */ U32 PageAddress; /* 0x10 */ U16 PageLength; /* 0x14 */ U16 Reserved16; /* 0x16 */ U32 Reserved18[2]; /* 0x18 */ MPI3_SGE_UNION SGL; /* 0x20 */ } MPI3_CONFIG_REQUEST, MPI3_POINTER PTR_MPI3_CONFIG_REQUEST, Mpi3ConfigRequest_t, MPI3_POINTER pMpi3ConfigRequest_t; /***************************************************************************** * Configuration Pages * ****************************************************************************/ /***************************************************************************** * Configuration Page Header * ****************************************************************************/ typedef struct _MPI3_CONFIG_PAGE_HEADER { U8 PageVersion; /* 0x00 */ U8 Reserved01; /* 0x01 */ U8 PageNumber; /* 0x02 */ U8 PageAttribute; /* 0x03 */ U16 PageLength; /* 0x04 */ U8 PageType; /* 0x06 */ U8 Reserved07; /* 0x07 */ } MPI3_CONFIG_PAGE_HEADER, MPI3_POINTER PTR_MPI3_CONFIG_PAGE_HEADER, Mpi3ConfigPageHeader_t, MPI3_POINTER pMpi3ConfigPageHeader_t; /***************************************************************************** * Common definitions used by Configuration Pages * ****************************************************************************/ -/**** Defines for Negotiated Link Rates ****/ +/**** Defines for NegotiatedLinkRates ****/ #define MPI3_SAS_NEG_LINK_RATE_LOGICAL_MASK (0xF0) #define MPI3_SAS_NEG_LINK_RATE_LOGICAL_SHIFT (4) #define MPI3_SAS_NEG_LINK_RATE_PHYSICAL_MASK (0x0F) #define MPI3_SAS_NEG_LINK_RATE_PHYSICAL_SHIFT (0) /*** Below defines are used in both the PhysicalLinkRate and ***/ /*** LogicalLinkRate fields above. ***/ /*** (by applying the proper _SHIFT value) ***/ #define MPI3_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE (0x00) #define MPI3_SAS_NEG_LINK_RATE_PHY_DISABLED (0x01) #define MPI3_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED (0x02) #define MPI3_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03) #define MPI3_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04) #define MPI3_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05) #define MPI3_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY (0x06) #define MPI3_SAS_NEG_LINK_RATE_1_5 (0x08) #define MPI3_SAS_NEG_LINK_RATE_3_0 (0x09) #define MPI3_SAS_NEG_LINK_RATE_6_0 (0x0A) #define MPI3_SAS_NEG_LINK_RATE_12_0 (0x0B) #define MPI3_SAS_NEG_LINK_RATE_22_5 (0x0C) /**** Defines for the AttachedPhyInfo field ****/ #define MPI3_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT (0x00000040) #define MPI3_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS (0x00000020) #define MPI3_SAS_APHYINFO_BREAK_REPLY_CAPABLE (0x00000010) #define MPI3_SAS_APHYINFO_REASON_MASK (0x0000000F) #define MPI3_SAS_APHYINFO_REASON_UNKNOWN (0x00000000) #define MPI3_SAS_APHYINFO_REASON_POWER_ON (0x00000001) #define MPI3_SAS_APHYINFO_REASON_HARD_RESET (0x00000002) #define MPI3_SAS_APHYINFO_REASON_SMP_PHY_CONTROL (0x00000003) #define MPI3_SAS_APHYINFO_REASON_LOSS_OF_SYNC (0x00000004) #define MPI3_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ (0x00000005) #define MPI3_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00000006) #define MPI3_SAS_APHYINFO_REASON_BREAK_TIMEOUT (0x00000007) #define MPI3_SAS_APHYINFO_REASON_PHY_TEST_STOPPED (0x00000008) #define MPI3_SAS_APHYINFO_REASON_EXP_REDUCED_FUNC (0x00000009) /**** Defines for the PhyInfo field ****/ #define MPI3_SAS_PHYINFO_STATUS_MASK (0xC0000000) #define MPI3_SAS_PHYINFO_STATUS_SHIFT (30) #define MPI3_SAS_PHYINFO_STATUS_ACCESSIBLE (0x00000000) #define MPI3_SAS_PHYINFO_STATUS_NOT_EXIST (0x40000000) #define MPI3_SAS_PHYINFO_STATUS_VACANT (0x80000000) #define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_MASK (0x18000000) #define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_ACTIVE (0x00000000) #define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_PARTIAL (0x08000000) #define MPI3_SAS_PHYINFO_PHY_POWER_CONDITION_SLUMBER (0x10000000) #define MPI3_SAS_PHYINFO_REQUESTED_INSIDE_ZPSDS_CHANGED_MASK (0x04000000) #define MPI3_SAS_PHYINFO_REQUESTED_INSIDE_ZPSDS_CHANGED_SHIFT (26) #define MPI3_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT_MASK (0x02000000) #define MPI3_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT_SHIFT (25) #define MPI3_SAS_PHYINFO_REQUESTED_INSIDE_ZPSDS_MASK (0x01000000) #define MPI3_SAS_PHYINFO_REQUESTED_INSIDE_ZPSDS_SHIFT (24) #define MPI3_SAS_PHYINFO_ZONE_GROUP_PERSISTENT (0x00400000) #define MPI3_SAS_PHYINFO_INSIDE_ZPSDS_WITHIN (0x00200000) #define MPI3_SAS_PHYINFO_ZONING_ENABLED (0x00100000) #define MPI3_SAS_PHYINFO_REASON_MASK (0x000F0000) #define MPI3_SAS_PHYINFO_REASON_UNKNOWN (0x00000000) #define MPI3_SAS_PHYINFO_REASON_POWER_ON (0x00010000) #define MPI3_SAS_PHYINFO_REASON_HARD_RESET (0x00020000) #define MPI3_SAS_PHYINFO_REASON_SMP_PHY_CONTROL (0x00030000) #define MPI3_SAS_PHYINFO_REASON_LOSS_OF_SYNC (0x00040000) #define MPI3_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ (0x00050000) #define MPI3_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00060000) #define MPI3_SAS_PHYINFO_REASON_BREAK_TIMEOUT (0x00070000) #define MPI3_SAS_PHYINFO_REASON_PHY_TEST_STOPPED (0x00080000) #define MPI3_SAS_PHYINFO_REASON_EXP_REDUCED_FUNC (0x00090000) #define MPI3_SAS_PHYINFO_SATA_PORT_ACTIVE (0x00004000) #define MPI3_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT (0x00002000) #define MPI3_SAS_PHYINFO_VIRTUAL_PHY (0x00001000) #define MPI3_SAS_PHYINFO_PARTIAL_PATHWAY_TIME_MASK (0x00000F00) #define MPI3_SAS_PHYINFO_PARTIAL_PATHWAY_TIME_SHIFT (8) #define MPI3_SAS_PHYINFO_ROUTING_ATTRIBUTE_MASK (0x000000F0) #define MPI3_SAS_PHYINFO_ROUTING_ATTRIBUTE_DIRECT (0x00000000) #define MPI3_SAS_PHYINFO_ROUTING_ATTRIBUTE_SUBTRACTIVE (0x00000010) #define MPI3_SAS_PHYINFO_ROUTING_ATTRIBUTE_TABLE (0x00000020) /**** Defines for the ProgrammedLinkRate field ****/ #define MPI3_SAS_PRATE_MAX_RATE_MASK (0xF0) #define MPI3_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00) #define MPI3_SAS_PRATE_MAX_RATE_1_5 (0x80) #define MPI3_SAS_PRATE_MAX_RATE_3_0 (0x90) #define MPI3_SAS_PRATE_MAX_RATE_6_0 (0xA0) #define MPI3_SAS_PRATE_MAX_RATE_12_0 (0xB0) #define MPI3_SAS_PRATE_MAX_RATE_22_5 (0xC0) #define MPI3_SAS_PRATE_MIN_RATE_MASK (0x0F) #define MPI3_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00) #define MPI3_SAS_PRATE_MIN_RATE_1_5 (0x08) #define MPI3_SAS_PRATE_MIN_RATE_3_0 (0x09) #define MPI3_SAS_PRATE_MIN_RATE_6_0 (0x0A) #define MPI3_SAS_PRATE_MIN_RATE_12_0 (0x0B) #define MPI3_SAS_PRATE_MIN_RATE_22_5 (0x0C) /**** Defines for the HwLinkRate field ****/ #define MPI3_SAS_HWRATE_MAX_RATE_MASK (0xF0) #define MPI3_SAS_HWRATE_MAX_RATE_1_5 (0x80) #define MPI3_SAS_HWRATE_MAX_RATE_3_0 (0x90) #define MPI3_SAS_HWRATE_MAX_RATE_6_0 (0xA0) #define MPI3_SAS_HWRATE_MAX_RATE_12_0 (0xB0) #define MPI3_SAS_HWRATE_MAX_RATE_22_5 (0xC0) #define MPI3_SAS_HWRATE_MIN_RATE_MASK (0x0F) #define MPI3_SAS_HWRATE_MIN_RATE_1_5 (0x08) #define MPI3_SAS_HWRATE_MIN_RATE_3_0 (0x09) #define MPI3_SAS_HWRATE_MIN_RATE_6_0 (0x0A) #define MPI3_SAS_HWRATE_MIN_RATE_12_0 (0x0B) #define MPI3_SAS_HWRATE_MIN_RATE_22_5 (0x0C) /**** Defines for the Slot field ****/ #define MPI3_SLOT_INVALID (0xFFFF) /**** Defines for the SlotIndex field ****/ #define MPI3_SLOT_INDEX_INVALID (0xFFFF) /**** Defines for the LinkChangeCount fields ****/ #define MPI3_LINK_CHANGE_COUNT_INVALID (0xFFFF) /**** Defines for the RateChangeCount fields ****/ #define MPI3_RATE_CHANGE_COUNT_INVALID (0xFFFF) /**** Defines for the Temp Sensor Location field ****/ #define MPI3_TEMP_SENSOR_LOCATION_INTERNAL (0x0) #define MPI3_TEMP_SENSOR_LOCATION_INLET (0x1) #define MPI3_TEMP_SENSOR_LOCATION_OUTLET (0x2) #define MPI3_TEMP_SENSOR_LOCATION_DRAM (0x3) /***************************************************************************** * Manufacturing Configuration Pages * ****************************************************************************/ #define MPI3_MFGPAGE_VENDORID_BROADCOM (0x1000) /* MPI v3.0 SAS Products */ #define MPI3_MFGPAGE_DEVID_SAS4116 (0x00A5) #define MPI3_MFGPAGE_DEVID_SAS5116_MPI (0x00B3) #define MPI3_MFGPAGE_DEVID_SAS5116_NVME (0x00B4) #define MPI3_MFGPAGE_DEVID_SAS5116_MPI_NS (0x00B5) #define MPI3_MFGPAGE_DEVID_SAS5116_NVME_NS (0x00B6) #define MPI3_MFGPAGE_DEVID_SAS5116_PCIE_SWITCH (0x00B8) /***************************************************************************** * Manufacturing Page 0 * ****************************************************************************/ typedef struct _MPI3_MAN_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 ChipRevision[8]; /* 0x08 */ U8 ChipName[32]; /* 0x10 */ U8 BoardName[32]; /* 0x30 */ U8 BoardAssembly[32]; /* 0x50 */ U8 BoardTracerNumber[32]; /* 0x70 */ U32 BoardPower; /* 0x90 */ U32 Reserved94; /* 0x94 */ U32 Reserved98; /* 0x98 */ U8 OEM; /* 0x9C */ U8 ProfileIdentifier; /* 0x9D */ U16 Flags; /* 0x9E */ U8 BoardMfgDay; /* 0xA0 */ U8 BoardMfgMonth; /* 0xA1 */ U16 BoardMfgYear; /* 0xA2 */ U8 BoardReworkDay; /* 0xA4 */ U8 BoardReworkMonth; /* 0xA5 */ U16 BoardReworkYear; /* 0xA6 */ U8 BoardRevision[8]; /* 0xA8 */ U8 EPackFRU[16]; /* 0xB0 */ U8 ProductName[256]; /* 0xC0 */ } MPI3_MAN_PAGE0, MPI3_POINTER PTR_MPI3_MAN_PAGE0, Mpi3ManPage0_t, MPI3_POINTER pMpi3ManPage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN0_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_MAN0_FLAGS_SWITCH_PRESENT (0x0002) #define MPI3_MAN0_FLAGS_EXPANDER_PRESENT (0x0001) /***************************************************************************** * Manufacturing Page 1 * ****************************************************************************/ #define MPI3_MAN1_VPD_SIZE (512) typedef struct _MPI3_MAN_PAGE1 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08[2]; /* 0x08 */ U8 VPD[MPI3_MAN1_VPD_SIZE]; /* 0x10 */ } MPI3_MAN_PAGE1, MPI3_POINTER PTR_MPI3_MAN_PAGE1, Mpi3ManPage1_t, MPI3_POINTER pMpi3ManPage1_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN1_PAGEVERSION (0x00) /***************************************************************************** * Manufacturing Page 2 * ****************************************************************************/ typedef struct _MPI3_MAN_PAGE2 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 Flags; /* 0x08 */ U8 Reserved09[3]; /* 0x09 */ U32 Reserved0C[3]; /* 0x0C */ U8 OEMBoardTracerNumber[32]; /* 0x18 */ } MPI3_MAN_PAGE2, MPI3_POINTER PTR_MPI3_MAN_PAGE2, Mpi3ManPage2_t, MPI3_POINTER pMpi3ManPage2_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN2_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_MAN2_FLAGS_TRACER_PRESENT (0x01) /***************************************************************************** * Manufacturing Page 5 * ****************************************************************************/ typedef struct _MPI3_MAN5_PHY_ENTRY { U64 IOC_WWID; /* 0x00 */ U64 DeviceName; /* 0x08 */ U64 SATA_WWID; /* 0x10 */ } MPI3_MAN5_PHY_ENTRY, MPI3_POINTER PTR_MPI3_MAN5_PHY_ENTRY, Mpi3Man5PhyEntry_t, MPI3_POINTER pMpi3Man5PhyEntry_t; #ifndef MPI3_MAN5_PHY_MAX #define MPI3_MAN5_PHY_MAX (1) #endif /* MPI3_MAN5_PHY_MAX */ typedef struct _MPI3_MAN_PAGE5 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 NumPhys; /* 0x08 */ U8 Reserved09[3]; /* 0x09 */ U32 Reserved0C; /* 0x0C */ MPI3_MAN5_PHY_ENTRY Phy[MPI3_MAN5_PHY_MAX]; /* 0x10 */ } MPI3_MAN_PAGE5, MPI3_POINTER PTR_MPI3_MAN_PAGE5, Mpi3ManPage5_t, MPI3_POINTER pMpi3ManPage5_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN5_PAGEVERSION (0x00) /***************************************************************************** * Manufacturing Page 6 * ****************************************************************************/ typedef struct _MPI3_MAN6_GPIO_ENTRY { U8 FunctionCode; /* 0x00 */ U8 FunctionFlags; /* 0x01 */ U16 Flags; /* 0x02 */ U8 Param1; /* 0x04 */ U8 Param2; /* 0x05 */ U16 Reserved06; /* 0x06 */ U32 Param3; /* 0x08 */ } MPI3_MAN6_GPIO_ENTRY, MPI3_POINTER PTR_MPI3_MAN6_GPIO_ENTRY, Mpi3Man6GpioEntry_t, MPI3_POINTER pMpi3Man6GpioEntry_t; /**** Defines for the FunctionCode field ****/ #define MPI3_MAN6_GPIO_FUNCTION_GENERIC (0x00) #define MPI3_MAN6_GPIO_FUNCTION_ALTERNATE (0x01) #define MPI3_MAN6_GPIO_FUNCTION_EXT_INTERRUPT (0x02) #define MPI3_MAN6_GPIO_FUNCTION_GLOBAL_ACTIVITY (0x03) #define MPI3_MAN6_GPIO_FUNCTION_OVER_TEMPERATURE (0x04) #define MPI3_MAN6_GPIO_FUNCTION_PORT_STATUS_GREEN (0x05) #define MPI3_MAN6_GPIO_FUNCTION_PORT_STATUS_YELLOW (0x06) #define MPI3_MAN6_GPIO_FUNCTION_CABLE_MANAGEMENT (0x07) #define MPI3_MAN6_GPIO_FUNCTION_BKPLANE_MGMT_TYPE (0x08) #define MPI3_MAN6_GPIO_FUNCTION_ISTWI_RESET (0x0A) #define MPI3_MAN6_GPIO_FUNCTION_BACKEND_PCIE_RESET (0x0B) #define MPI3_MAN6_GPIO_FUNCTION_GLOBAL_FAULT (0x0C) #define MPI3_MAN6_GPIO_FUNCTION_PBLP_STATUS_CHANGE (0x0D) #define MPI3_MAN6_GPIO_FUNCTION_EPACK_ONLINE (0x0E) #define MPI3_MAN6_GPIO_FUNCTION_EPACK_FAULT (0x0F) #define MPI3_MAN6_GPIO_FUNCTION_CTRL_TYPE (0x10) #define MPI3_MAN6_GPIO_FUNCTION_LICENSE (0x11) #define MPI3_MAN6_GPIO_FUNCTION_REFCLK_CONTROL (0x12) #define MPI3_MAN6_GPIO_FUNCTION_BACKEND_PCIE_RESET_CLAMP (0x13) #define MPI3_MAN6_GPIO_FUNCTION_AUXILIARY_POWER (0x14) #define MPI3_MAN6_GPIO_FUNCTION_RAID_DATA_CACHE_DIRTY (0x15) #define MPI3_MAN6_GPIO_FUNCTION_BOARD_FAN_CONTROL (0x16) #define MPI3_MAN6_GPIO_FUNCTION_BOARD_FAN_FAULT (0x17) #define MPI3_MAN6_GPIO_FUNCTION_POWER_BRAKE (0x18) #define MPI3_MAN6_GPIO_FUNCTION_MGMT_CONTROLLER_RESET (0x19) /**** Defines for FunctionFlags when FunctionCode is ISTWI_RESET ****/ #define MPI3_MAN6_GPIO_ISTWI_RESET_FUNCTIONFLAGS_DEVSELECT_MASK (0x01) #define MPI3_MAN6_GPIO_ISTWI_RESET_FUNCTIONFLAGS_DEVSELECT_ISTWI (0x00) #define MPI3_MAN6_GPIO_ISTWI_RESET_FUNCTIONFLAGS_DEVSELECT_RECEPTACLEID (0x01) /**** Defines for Param1 (Flags) when FunctionCode is EXT_INTERRUPT ****/ #define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_SOURCE_MASK (0xF0) #define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_SOURCE_GENERIC (0x00) #define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_SOURCE_CABLE_MGMT (0x10) #define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_SOURCE_ACTIVE_CABLE_OVERCURRENT (0x20) +#define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_ACK_REQUIRED (0x02) #define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_TRIGGER_MASK (0x01) #define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_TRIGGER_EDGE (0x00) #define MPI3_MAN6_GPIO_EXTINT_PARAM1_FLAGS_TRIGGER_LEVEL (0x01) /**** Defines for Param1 (PHY STATE) when FunctionCode is PORT_STATUS_GREEN ****/ #define MPI3_MAN6_GPIO_PORT_GREEN_PARAM1_PHY_STATUS_ALL_UP (0x00) #define MPI3_MAN6_GPIO_PORT_GREEN_PARAM1_PHY_STATUS_ONE_OR_MORE_UP (0x01) /**** Defines for Param1 (INTERFACE_SIGNAL) when FunctionCode is CABLE_MANAGEMENT ****/ #define MPI3_MAN6_GPIO_CABLE_MGMT_PARAM1_INTERFACE_MODULE_PRESENT (0x00) #define MPI3_MAN6_GPIO_CABLE_MGMT_PARAM1_INTERFACE_ACTIVE_CABLE_ENABLE (0x01) #define MPI3_MAN6_GPIO_CABLE_MGMT_PARAM1_INTERFACE_CABLE_MGMT_ENABLE (0x02) /**** Defines for Param1 (LICENSE_TYPE) when FunctionCode is LICENSE ****/ #define MPI3_MAN6_GPIO_LICENSE_PARAM1_TYPE_IBUTTON (0x00) /**** Defines for the Flags field ****/ #define MPI3_MAN6_GPIO_FLAGS_SLEW_RATE_MASK (0x0100) #define MPI3_MAN6_GPIO_FLAGS_SLEW_RATE_FAST_EDGE (0x0100) #define MPI3_MAN6_GPIO_FLAGS_SLEW_RATE_SLOW_EDGE (0x0000) #define MPI3_MAN6_GPIO_FLAGS_DRIVE_STRENGTH_MASK (0x00C0) #define MPI3_MAN6_GPIO_FLAGS_DRIVE_STRENGTH_100OHM (0x0000) #define MPI3_MAN6_GPIO_FLAGS_DRIVE_STRENGTH_66OHM (0x0040) #define MPI3_MAN6_GPIO_FLAGS_DRIVE_STRENGTH_50OHM (0x0080) #define MPI3_MAN6_GPIO_FLAGS_DRIVE_STRENGTH_33OHM (0x00C0) #define MPI3_MAN6_GPIO_FLAGS_ALT_DATA_SEL_MASK (0x0030) #define MPI3_MAN6_GPIO_FLAGS_ALT_DATA_SEL_SHIFT (4) #define MPI3_MAN6_GPIO_FLAGS_ACTIVE_HIGH (0x0008) #define MPI3_MAN6_GPIO_FLAGS_BI_DIR_ENABLED (0x0004) #define MPI3_MAN6_GPIO_FLAGS_DIRECTION_MASK (0x0003) #define MPI3_MAN6_GPIO_FLAGS_DIRECTION_INPUT (0x0000) #define MPI3_MAN6_GPIO_FLAGS_DIRECTION_OPEN_DRAIN_OUTPUT (0x0001) #define MPI3_MAN6_GPIO_FLAGS_DIRECTION_OPEN_SOURCE_OUTPUT (0x0002) #define MPI3_MAN6_GPIO_FLAGS_DIRECTION_PUSH_PULL_OUTPUT (0x0003) #ifndef MPI3_MAN6_GPIO_MAX #define MPI3_MAN6_GPIO_MAX (1) #endif /* MPI3_MAN6_GPIO_MAX */ typedef struct _MPI3_MAN_PAGE6 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U16 Flags; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U8 NumGPIO; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_MAN6_GPIO_ENTRY GPIO[MPI3_MAN6_GPIO_MAX]; /* 0x10 */ } MPI3_MAN_PAGE6, MPI3_POINTER PTR_MPI3_MAN_PAGE6, Mpi3ManPage6_t, MPI3_POINTER pMpi3ManPage6_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN6_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_MAN6_FLAGS_HEARTBEAT_LED_DISABLED (0x0001) /***************************************************************************** * Manufacturing Page 7 * ****************************************************************************/ typedef struct _MPI3_MAN7_RECEPTACLE_INFO { U32 Name[4]; /* 0x00 */ U8 Location; /* 0x10 */ U8 ConnectorType; /* 0x11 */ U8 PEDClk; /* 0x12 */ U8 ConnectorID; /* 0x13 */ U32 Reserved14; /* 0x14 */ } MPI3_MAN7_RECEPTACLE_INFO, MPI3_POINTER PTR_MPI3_MAN7_RECEPTACLE_INFO, Mpi3Man7ReceptacleInfo_t, MPI3_POINTER pMpi3Man7ReceptacleInfo_t; /**** Defines for Location field ****/ #define MPI3_MAN7_LOCATION_UNKNOWN (0x00) #define MPI3_MAN7_LOCATION_INTERNAL (0x01) #define MPI3_MAN7_LOCATION_EXTERNAL (0x02) #define MPI3_MAN7_LOCATION_VIRTUAL (0x03) #define MPI3_MAN7_LOCATION_HOST (0x04) /**** Defines for ConnectorType - Use definitions from SES-4 ****/ #define MPI3_MAN7_CONNECTOR_TYPE_NO_INFO (0x00) /**** Defines for PEDClk field ****/ #define MPI3_MAN7_PEDCLK_ROUTING_MASK (0x10) #define MPI3_MAN7_PEDCLK_ROUTING_DIRECT (0x00) #define MPI3_MAN7_PEDCLK_ROUTING_CLOCK_BUFFER (0x10) #define MPI3_MAN7_PEDCLK_ID_MASK (0x0F) #ifndef MPI3_MAN7_RECEPTACLE_INFO_MAX #define MPI3_MAN7_RECEPTACLE_INFO_MAX (1) #endif /* MPI3_MAN7_RECEPTACLE_INFO_MAX */ typedef struct _MPI3_MAN_PAGE7 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Flags; /* 0x08 */ U8 NumReceptacles; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ U32 EnclosureName[4]; /* 0x10 */ MPI3_MAN7_RECEPTACLE_INFO ReceptacleInfo[MPI3_MAN7_RECEPTACLE_INFO_MAX]; /* 0x20 */ /* variable length array */ } MPI3_MAN_PAGE7, MPI3_POINTER PTR_MPI3_MAN_PAGE7, Mpi3ManPage7_t, MPI3_POINTER pMpi3ManPage7_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN7_PAGEVERSION (0x00) /**** Defines for Flags field ****/ #define MPI3_MAN7_FLAGS_BASE_ENCLOSURE_LEVEL_MASK (0x01) #define MPI3_MAN7_FLAGS_BASE_ENCLOSURE_LEVEL_0 (0x00) #define MPI3_MAN7_FLAGS_BASE_ENCLOSURE_LEVEL_1 (0x01) /***************************************************************************** * Manufacturing Page 8 * ****************************************************************************/ typedef struct _MPI3_MAN8_PHY_INFO { U8 ReceptacleID; /* 0x00 */ U8 ConnectorLane; /* 0x01 */ U16 Reserved02; /* 0x02 */ U16 Slotx1; /* 0x04 */ U16 Slotx2; /* 0x06 */ U16 Slotx4; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U32 Reserved0C; /* 0x0C */ } MPI3_MAN8_PHY_INFO, MPI3_POINTER PTR_MPI3_MAN8_PHY_INFO, Mpi3Man8PhyInfo_t, MPI3_POINTER pMpi3Man8PhyInfo_t; /**** Defines for ReceptacleID field ****/ #define MPI3_MAN8_PHY_INFO_RECEPTACLE_ID_NOT_ASSOCIATED (0xFF) /**** Defines for ConnectorLane field ****/ #define MPI3_MAN8_PHY_INFO_CONNECTOR_LANE_NOT_ASSOCIATED (0xFF) #ifndef MPI3_MAN8_PHY_INFO_MAX #define MPI3_MAN8_PHY_INFO_MAX (1) #endif /* MPI3_MAN8_PHY_INFO_MAX */ typedef struct _MPI3_MAN_PAGE8 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumPhys; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_MAN8_PHY_INFO PhyInfo[MPI3_MAN8_PHY_INFO_MAX]; /* 0x10 */ /* variable length array */ } MPI3_MAN_PAGE8, MPI3_POINTER PTR_MPI3_MAN_PAGE8, Mpi3ManPage8_t, MPI3_POINTER pMpi3ManPage8_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN8_PAGEVERSION (0x00) /***************************************************************************** * Manufacturing Page 9 * ****************************************************************************/ typedef struct _MPI3_MAN9_RSRC_ENTRY { U32 Maximum; /* 0x00 */ U32 Decrement; /* 0x04 */ U32 Minimum; /* 0x08 */ U32 Actual; /* 0x0C */ } MPI3_MAN9_RSRC_ENTRY, MPI3_POINTER PTR_MPI3_MAN9_RSRC_ENTRY, Mpi3Man9RsrcEntry_t, MPI3_POINTER pMpi3Man9RsrcEntry_t; typedef enum _MPI3_MAN9_RESOURCES { MPI3_MAN9_RSRC_OUTSTANDING_REQS = 0, MPI3_MAN9_RSRC_TARGET_CMDS = 1, MPI3_MAN9_RSRC_RESERVED02 = 2, MPI3_MAN9_RSRC_NVME = 3, MPI3_MAN9_RSRC_INITIATORS = 4, MPI3_MAN9_RSRC_VDS = 5, MPI3_MAN9_RSRC_ENCLOSURES = 6, MPI3_MAN9_RSRC_ENCLOSURE_PHYS = 7, MPI3_MAN9_RSRC_EXPANDERS = 8, MPI3_MAN9_RSRC_PCIE_SWITCHES = 9, MPI3_MAN9_RSRC_RESERVED10 = 10, MPI3_MAN9_RSRC_HOST_PD_DRIVES = 11, MPI3_MAN9_RSRC_ADV_HOST_PD_DRIVES = 12, MPI3_MAN9_RSRC_RAID_PD_DRIVES = 13, MPI3_MAN9_RSRC_DRV_DIAG_BUF = 14, MPI3_MAN9_RSRC_NAMESPACE_COUNT = 15, MPI3_MAN9_RSRC_NUM_RESOURCES } MPI3_MAN9_RESOURCES; #define MPI3_MAN9_MIN_OUTSTANDING_REQS (1) #define MPI3_MAN9_MAX_OUTSTANDING_REQS (65000) #define MPI3_MAN9_MIN_TARGET_CMDS (0) #define MPI3_MAN9_MAX_TARGET_CMDS (65535) #define MPI3_MAN9_MIN_NVME_TARGETS (0) /* Max NVMe Targets is product specific */ #define MPI3_MAN9_MIN_INITIATORS (0) /* Max Initiators is product specific */ #define MPI3_MAN9_MIN_VDS (0) /* Max VDs is product specific */ #define MPI3_MAN9_MIN_ENCLOSURES (1) #define MPI3_MAN9_MAX_ENCLOSURES (65535) #define MPI3_MAN9_MIN_ENCLOSURE_PHYS (0) /* Max Enclosure Phys is product specific */ #define MPI3_MAN9_MIN_EXPANDERS (0) #define MPI3_MAN9_MAX_EXPANDERS (65535) #define MPI3_MAN9_MIN_PCIE_SWITCHES (0) /* Max PCIe Switches is product specific */ #define MPI3_MAN9_MIN_HOST_PD_DRIVES (0) /* Max Host PD Drives is product specific */ #define MPI3_MAN9_ADV_HOST_PD_DRIVES (0) /* Max Advanced Host PD Drives is product specific */ #define MPI3_MAN9_RAID_PD_DRIVES (0) /* Max RAID PD Drives is product specific */ #define MPI3_MAN9_DRIVER_DIAG_BUFFER (0) /* Max Driver Diag Buffer is product specific */ #define MPI3_MAN9_MIN_NAMESPACE_COUNT (1) #define MPI3_MAN9_MIN_EXPANDERS (0) #define MPI3_MAN9_MAX_EXPANDERS (65535) typedef struct _MPI3_MAN_PAGE9 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 NumResources; /* 0x08 */ U8 Reserved09; /* 0x09 */ U16 Reserved0A; /* 0x0A */ U32 Reserved0C; /* 0x0C */ U32 Reserved10; /* 0x10 */ U32 Reserved14; /* 0x14 */ U32 Reserved18; /* 0x18 */ U32 Reserved1C; /* 0x1C */ MPI3_MAN9_RSRC_ENTRY Resource[MPI3_MAN9_RSRC_NUM_RESOURCES]; /* 0x20 */ } MPI3_MAN_PAGE9, MPI3_POINTER PTR_MPI3_MAN_PAGE9, Mpi3ManPage9_t, MPI3_POINTER pMpi3ManPage9_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN9_PAGEVERSION (0x00) /***************************************************************************** * Manufacturing Page 10 * ****************************************************************************/ typedef struct _MPI3_MAN10_ISTWI_CTRLR_ENTRY { U16 TargetAddress; /* 0x00 */ U16 Flags; /* 0x02 */ U8 SCLLowOverride; /* 0x04 */ U8 SCLHighOverride; /* 0x05 */ U16 Reserved06; /* 0x06 */ } MPI3_MAN10_ISTWI_CTRLR_ENTRY, MPI3_POINTER PTR_MPI3_MAN10_ISTWI_CTRLR_ENTRY, Mpi3Man10IstwiCtrlrEntry_t, MPI3_POINTER pMpi3Man10IstwiCtrlrEntry_t; /**** Defines for the Flags field ****/ #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I2C_GLICH_FLTR_MASK (0xC000) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I2C_GLICH_FLTR_SHIFT (14) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I2C_GLICH_FLTR_50_NS (0x0000) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I2C_GLICH_FLTR_10_NS (0x4000) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I2C_GLICH_FLTR_5_NS (0x8000) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I2C_GLICH_FLTR_0_NS (0xC000) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_TYPE_MASK (0x3000) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_TYPE_SHIFT (12) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_TYPE_I2C (0x0000) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_TYPE_I3C (0x1000) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_TYPE_AUTO (0x2000) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_MASK (0x0E00) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_SHIFT (9) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_12_5_MHZ (0x0000) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_8_MHZ (0x0200) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_6_MHZ (0x0400) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_4_MHZ (0x0600) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_I3C_MAX_DATA_RATE_2_MHZ (0x0800) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_MASK (0x000C) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_SHIFT (0) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_100_KHZ (0x0000) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_BUS_SPEED_400_KHZ (0x0004) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_TARGET_ENABLED (0x0002) #define MPI3_MAN10_ISTWI_CTRLR_FLAGS_INITIATOR_ENABLED (0x0001) #ifndef MPI3_MAN10_ISTWI_CTRLR_MAX #define MPI3_MAN10_ISTWI_CTRLR_MAX (1) #endif /* MPI3_MAN10_ISTWI_CTRLR_MAX */ typedef struct _MPI3_MAN_PAGE10 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumISTWICtrl; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_MAN10_ISTWI_CTRLR_ENTRY ISTWIController[MPI3_MAN10_ISTWI_CTRLR_MAX]; /* 0x10 */ } MPI3_MAN_PAGE10, MPI3_POINTER PTR_MPI3_MAN_PAGE10, Mpi3ManPage10_t, MPI3_POINTER pMpi3ManPage10_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN10_PAGEVERSION (0x00) /***************************************************************************** * Manufacturing Page 11 * ****************************************************************************/ typedef struct _MPI3_MAN11_MUX_DEVICE_FORMAT { U8 MaxChannel; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ U32 Reserved04; /* 0x04 */ } MPI3_MAN11_MUX_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_MUX_DEVICE_FORMAT, Mpi3Man11MuxDeviceFormat_t, MPI3_POINTER pMpi3Man11MuxDeviceFormat_t; typedef struct _MPI3_MAN11_TEMP_SENSOR_DEVICE_FORMAT { U8 Type; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ U8 TempChannel[4]; /* 0x04 */ } MPI3_MAN11_TEMP_SENSOR_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_TEMP_SENSOR_DEVICE_FORMAT, Mpi3Man11TempSensorDeviceFormat_t, MPI3_POINTER pMpi3Man11TempSensorDeviceFormat_t; /**** Defines for the Type field ****/ #define MPI3_MAN11_TEMP_SENSOR_TYPE_MAX6654 (0x00) #define MPI3_MAN11_TEMP_SENSOR_TYPE_EMC1442 (0x01) #define MPI3_MAN11_TEMP_SENSOR_TYPE_ADT7476 (0x02) #define MPI3_MAN11_TEMP_SENSOR_TYPE_SE97B (0x03) /**** Define for the TempChannel field ****/ #define MPI3_MAN11_TEMP_SENSOR_CHANNEL_LOCATION_MASK (0xE0) #define MPI3_MAN11_TEMP_SENSOR_CHANNEL_LOCATION_SHIFT (5) /**** for the Location field values - use MPI3_TEMP_SENSOR_LOCATION_ defines ****/ #define MPI3_MAN11_TEMP_SENSOR_CHANNEL_ENABLED (0x01) typedef struct _MPI3_MAN11_SEEPROM_DEVICE_FORMAT { U8 Size; /* 0x00 */ U8 PageWriteSize; /* 0x01 */ U16 Reserved02; /* 0x02 */ U32 Reserved04; /* 0x04 */ } MPI3_MAN11_SEEPROM_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_SEEPROM_DEVICE_FORMAT, Mpi3Man11SeepromDeviceFormat_t, MPI3_POINTER pMpi3Man11SeepromDeviceFormat_t; /**** Defines for the Size field ****/ #define MPI3_MAN11_SEEPROM_SIZE_1KBITS (0x01) #define MPI3_MAN11_SEEPROM_SIZE_2KBITS (0x02) #define MPI3_MAN11_SEEPROM_SIZE_4KBITS (0x03) #define MPI3_MAN11_SEEPROM_SIZE_8KBITS (0x04) #define MPI3_MAN11_SEEPROM_SIZE_16KBITS (0x05) #define MPI3_MAN11_SEEPROM_SIZE_32KBITS (0x06) #define MPI3_MAN11_SEEPROM_SIZE_64KBITS (0x07) #define MPI3_MAN11_SEEPROM_SIZE_128KBITS (0x08) typedef struct _MPI3_MAN11_DDR_SPD_DEVICE_FORMAT { U8 Channel; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ U32 Reserved04; /* 0x04 */ } MPI3_MAN11_DDR_SPD_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_DDR_SPD_DEVICE_FORMAT, Mpi3Man11DdrSpdDeviceFormat_t, MPI3_POINTER pMpi3Man11DdrSpdDeviceFormat_t; typedef struct _MPI3_MAN11_CABLE_MGMT_DEVICE_FORMAT { U8 Type; /* 0x00 */ U8 ReceptacleID; /* 0x01 */ U16 Reserved02; /* 0x02 */ U32 Reserved04; /* 0x04 */ } MPI3_MAN11_CABLE_MGMT_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_CABLE_MGMT_DEVICE_FORMAT, Mpi3Man11CableMgmtDeviceFormat_t, MPI3_POINTER pMpi3Man11CableMgmtDeviceFormat_t; /**** Defines for the Type field ****/ #define MPI3_MAN11_CABLE_MGMT_TYPE_SFF_8636 (0x00) typedef struct _MPI3_MAN11_BKPLANE_SPEC_UBM_FORMAT { U16 Flags; /* 0x00 */ U16 Reserved02; /* 0x02 */ } MPI3_MAN11_BKPLANE_SPEC_UBM_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_BKPLANE_SPEC_UBM_FORMAT, Mpi3Man11BkplaneSpecUBMFormat_t, MPI3_POINTER pMpi3Man11BkplaneSpecUBMFormat_t; /**** Defines for the Flags field ****/ #define MPI3_MAN11_BKPLANE_UBM_FLAGS_REFCLK_POLICY_ALWAYS_ENABLED (0x0200) #define MPI3_MAN11_BKPLANE_UBM_FLAGS_FORCE_POLLING (0x0100) #define MPI3_MAN11_BKPLANE_UBM_FLAGS_MAX_FRU_MASK (0x00F0) #define MPI3_MAN11_BKPLANE_UBM_FLAGS_MAX_FRU_SHIFT (4) #define MPI3_MAN11_BKPLANE_UBM_FLAGS_POLL_INTERVAL_MASK (0x000F) #define MPI3_MAN11_BKPLANE_UBM_FLAGS_POLL_INTERVAL_SHIFT (0) typedef struct _MPI3_MAN11_BKPLANE_SPEC_NON_UBM_FORMAT { U16 Flags; /* 0x00 */ U8 Reserved02; /* 0x02 */ U8 Type; /* 0x03 */ } MPI3_MAN11_BKPLANE_SPEC_NON_UBM_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_BKPLANE_SPEC_NON_UBM_FORMAT, Mpi3Man11BkplaneSpecNonUBMFormat_t, MPI3_POINTER pMpi3Man11BkplaneSpecNonUBMFormat_t; /**** Defines for the Flags field ****/ #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_GROUP_MASK (0xF000) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_GROUP_SHIFT (12) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_REFCLK_POLICY_MASK (0x0600) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_REFCLK_POLICY_SHIFT (9) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_REFCLK_POLICY_DEVICE_PRESENT (0x0000) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_REFCLK_POLICY_ALWAYS_ENABLED (0x0200) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_REFCLK_POLICY_SRIS (0x0400) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_LINKWIDTH_MASK (0x00C0) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_LINKWIDTH_SHIFT (6) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_LINKWIDTH_4 (0x0000) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_LINKWIDTH_2 (0x0040) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_LINKWIDTH_1 (0x0080) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_PRESENCE_DETECT_MASK (0x0030) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_PRESENCE_DETECT_SHIFT (4) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_PRESENCE_DETECT_GPIO (0x0000) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_PRESENCE_DETECT_REG (0x0010) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_POLL_INTERVAL_MASK (0x000F) #define MPI3_MAN11_BKPLANE_NON_UBM_FLAGS_POLL_INTERVAL_SHIFT (0) /**** Defines for the Type field ****/ #define MPI3_MAN11_BKPLANE_NON_UBM_TYPE_VPP (0x00) typedef union _MPI3_MAN11_BKPLANE_SPEC_FORMAT { MPI3_MAN11_BKPLANE_SPEC_UBM_FORMAT Ubm; MPI3_MAN11_BKPLANE_SPEC_NON_UBM_FORMAT NonUbm; } MPI3_MAN11_BKPLANE_SPEC_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_BKPLANE_SPEC_FORMAT, Mpi3Man11BkplaneSpecFormat_t, MPI3_POINTER pMpi3Man11BkplaneSpecFormat_t; typedef struct _MPI3_MAN11_BKPLANE_MGMT_DEVICE_FORMAT { U8 Type; /* 0x00 */ U8 ReceptacleID; /* 0x01 */ U8 ResetInfo; /* 0x02 */ U8 Reserved03; /* 0x03 */ MPI3_MAN11_BKPLANE_SPEC_FORMAT BackplaneMgmtSpecific; /* 0x04 */ } MPI3_MAN11_BKPLANE_MGMT_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_BKPLANE_MGMT_DEVICE_FORMAT, Mpi3Man11BkplaneMgmtDeviceFormat_t, MPI3_POINTER pMpi3Man11BkplaneMgmtDeviceFormat_t; /**** Defines for the Type field ****/ #define MPI3_MAN11_BKPLANE_MGMT_TYPE_UBM (0x00) #define MPI3_MAN11_BKPLANE_MGMT_TYPE_NON_UBM (0x01) /**** Defines for the ResetInfo field ****/ #define MPI3_MAN11_BACKPLANE_RESETINFO_ASSERT_TIME_MASK (0xF0) #define MPI3_MAN11_BACKPLANE_RESETINFO_ASSERT_TIME_SHIFT (4) #define MPI3_MAN11_BACKPLANE_RESETINFO_READY_TIME_MASK (0x0F) #define MPI3_MAN11_BACKPLANE_RESETINFO_READY_TIME_SHIFT (0) typedef struct _MPI3_MAN11_GAS_GAUGE_DEVICE_FORMAT { U8 Type; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ U32 Reserved04; /* 0x04 */ } MPI3_MAN11_GAS_GAUGE_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_GAS_GAUGE_DEVICE_FORMAT, Mpi3Man11GasGaugeDeviceFormat_t, MPI3_POINTER pMpi3Man11GasGaugeDeviceFormat_t; /**** Defines for the Type field ****/ #define MPI3_MAN11_GAS_GAUGE_TYPE_STANDARD (0x00) typedef struct _MPI3_MAN11_MGMT_CTRLR_DEVICE_FORMAT { U32 Reserved00; /* 0x00 */ U32 Reserved04; /* 0x04 */ } MPI3_MAN11_MGMT_CTRLR_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_MGMT_CTRLR_DEVICE_FORMAT, Mpi3Man11MgmtCtrlrDeviceFormat_t, MPI3_POINTER pMpi3Man11MgmtCtrlrDeviceFormat_t; typedef struct _MPI3_MAN11_BOARD_FAN_DEVICE_FORMAT { U8 Flags; /* 0x00 */ U8 Reserved01; /* 0x01 */ U8 MinFanSpeed; /* 0x02 */ U8 MaxFanSpeed; /* 0x03 */ U32 Reserved04; /* 0x04 */ } MPI3_MAN11_BOARD_FAN_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_BOARD_FAN_DEVICE_FORMAT, Mpi3Man11BoardFanDeviceFormat_t, MPI3_POINTER pMpi3Man11BoardFanDeviceFormat_t; /**** Defines for the Flags field ****/ #define MPI3_MAN11_BOARD_FAN_FLAGS_FAN_CTRLR_TYPE_MASK (0x07) #define MPI3_MAN11_BOARD_FAN_FLAGS_FAN_CTRLR_TYPE_AMC6821 (0x00) typedef union _MPI3_MAN11_DEVICE_SPECIFIC_FORMAT { MPI3_MAN11_MUX_DEVICE_FORMAT Mux; MPI3_MAN11_TEMP_SENSOR_DEVICE_FORMAT TempSensor; MPI3_MAN11_SEEPROM_DEVICE_FORMAT Seeprom; MPI3_MAN11_DDR_SPD_DEVICE_FORMAT DdrSpd; MPI3_MAN11_CABLE_MGMT_DEVICE_FORMAT CableMgmt; MPI3_MAN11_BKPLANE_MGMT_DEVICE_FORMAT BkplaneMgmt; MPI3_MAN11_GAS_GAUGE_DEVICE_FORMAT GasGauge; MPI3_MAN11_MGMT_CTRLR_DEVICE_FORMAT MgmtController; MPI3_MAN11_BOARD_FAN_DEVICE_FORMAT BoardFan; U32 Words[2]; } MPI3_MAN11_DEVICE_SPECIFIC_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_DEVICE_SPECIFIC_FORMAT, Mpi3Man11DeviceSpecificFormat_t, MPI3_POINTER pMpi3Man11DeviceSpecificFormat_t; typedef struct _MPI3_MAN11_ISTWI_DEVICE_FORMAT { U8 DeviceType; /* 0x00 */ U8 Controller; /* 0x01 */ U8 Reserved02; /* 0x02 */ U8 Flags; /* 0x03 */ U16 DeviceAddress; /* 0x04 */ U8 MuxChannel; /* 0x06 */ U8 MuxIndex; /* 0x07 */ MPI3_MAN11_DEVICE_SPECIFIC_FORMAT DeviceSpecific; /* 0x08 */ } MPI3_MAN11_ISTWI_DEVICE_FORMAT, MPI3_POINTER PTR_MPI3_MAN11_ISTWI_DEVICE_FORMAT, Mpi3Man11IstwiDeviceFormat_t, MPI3_POINTER pMpi3Man11IstwiDeviceFormat_t; /**** Defines for the DeviceType field ****/ #define MPI3_MAN11_ISTWI_DEVTYPE_MUX (0x00) #define MPI3_MAN11_ISTWI_DEVTYPE_TEMP_SENSOR (0x01) #define MPI3_MAN11_ISTWI_DEVTYPE_SEEPROM (0x02) #define MPI3_MAN11_ISTWI_DEVTYPE_DDR_SPD (0x03) #define MPI3_MAN11_ISTWI_DEVTYPE_CABLE_MGMT (0x04) #define MPI3_MAN11_ISTWI_DEVTYPE_BACKPLANE_MGMT (0x05) #define MPI3_MAN11_ISTWI_DEVTYPE_GAS_GAUGE (0x06) #define MPI3_MAN11_ISTWI_DEVTYPE_MGMT_CONTROLLER (0x07) #define MPI3_MAN11_ISTWI_DEVTYPE_BOARD_FAN (0x08) /**** Defines for the Flags field ****/ #define MPI3_MAN11_ISTWI_FLAGS_MUX_PRESENT (0x01) #ifndef MPI3_MAN11_ISTWI_DEVICE_MAX #define MPI3_MAN11_ISTWI_DEVICE_MAX (1) #endif /* MPI3_MAN11_ISTWI_DEVICE_MAX */ typedef struct _MPI3_MAN_PAGE11 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumISTWIDev; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_MAN11_ISTWI_DEVICE_FORMAT ISTWIDevice[MPI3_MAN11_ISTWI_DEVICE_MAX]; /* 0x10 */ } MPI3_MAN_PAGE11, MPI3_POINTER PTR_MPI3_MAN_PAGE11, Mpi3ManPage11_t, MPI3_POINTER pMpi3ManPage11_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN11_PAGEVERSION (0x00) /***************************************************************************** * Manufacturing Page 12 * ****************************************************************************/ #ifndef MPI3_MAN12_NUM_SGPIO_MAX #define MPI3_MAN12_NUM_SGPIO_MAX (1) #endif /* MPI3_MAN12_NUM_SGPIO_MAX */ typedef struct _MPI3_MAN12_SGPIO_INFO { U8 SlotCount; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ U32 Reserved04; /* 0x04 */ U8 PhyOrder[32]; /* 0x08 */ } MPI3_MAN12_SGPIO_INFO, MPI3_POINTER PTR_MPI3_MAN12_SGPIO_INFO, Mpi3Man12SGPIOInfo_t, MPI3_POINTER pMpi3Man12SGPIOInfo_t; typedef struct _MPI3_MAN_PAGE12 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Flags; /* 0x08 */ U32 SClockFreq; /* 0x0C */ U32 ActivityModulation; /* 0x10 */ U8 NumSGPIO; /* 0x14 */ U8 Reserved15[3]; /* 0x15 */ U32 Reserved18; /* 0x18 */ U32 Reserved1C; /* 0x1C */ U32 Pattern[8]; /* 0x20 */ MPI3_MAN12_SGPIO_INFO SGPIOInfo[MPI3_MAN12_NUM_SGPIO_MAX]; /* 0x40 */ /* variable length */ } MPI3_MAN_PAGE12, MPI3_POINTER PTR_MPI3_MAN_PAGE12, Mpi3ManPage12_t, MPI3_POINTER pMpi3ManPage12_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN12_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_MAN12_FLAGS_ERROR_PRESENCE_ENABLED (0x0400) #define MPI3_MAN12_FLAGS_ACTIVITY_INVERT_ENABLED (0x0200) #define MPI3_MAN12_FLAGS_GROUP_ID_DISABLED (0x0100) #define MPI3_MAN12_FLAGS_SIO_CLK_FILTER_ENABLED (0x0004) #define MPI3_MAN12_FLAGS_SCLOCK_SLOAD_TYPE_MASK (0x0002) #define MPI3_MAN12_FLAGS_SCLOCK_SLOAD_TYPE_PUSH_PULL (0x0000) #define MPI3_MAN12_FLAGS_SCLOCK_SLOAD_TYPE_OPEN_DRAIN (0x0002) #define MPI3_MAN12_FLAGS_SDATAOUT_TYPE_MASK (0x0001) #define MPI3_MAN12_FLAGS_SDATAOUT_TYPE_PUSH_PULL (0x0000) #define MPI3_MAN12_FLAGS_SDATAOUT_TYPE_OPEN_DRAIN (0x0001) -/**** Defines for the SioClkFreq field ****/ +/**** Defines for the SClockFreq field ****/ #define MPI3_MAN12_SIO_CLK_FREQ_MIN (32) /* 32 Hz min SIO Clk Freq */ #define MPI3_MAN12_SIO_CLK_FREQ_MAX (100000) /* 100 KHz max SIO Clk Freq */ /**** Defines for the ActivityModulation field ****/ #define MPI3_MAN12_ACTIVITY_MODULATION_FORCE_OFF_MASK (0x0000F000) #define MPI3_MAN12_ACTIVITY_MODULATION_FORCE_OFF_SHIFT (12) #define MPI3_MAN12_ACTIVITY_MODULATION_MAX_ON_MASK (0x00000F00) #define MPI3_MAN12_ACTIVITY_MODULATION_MAX_ON_SHIFT (8) #define MPI3_MAN12_ACTIVITY_MODULATION_STRETCH_OFF_MASK (0x000000F0) #define MPI3_MAN12_ACTIVITY_MODULATION_STRETCH_OFF_SHIFT (4) #define MPI3_MAN12_ACTIVITY_MODULATION_STRETCH_ON_MASK (0x0000000F) #define MPI3_MAN12_ACTIVITY_MODULATION_STRETCH_ON_SHIFT (0) /*** Defines for the Pattern field ****/ #define MPI3_MAN12_PATTERN_RATE_MASK (0xE0000000) #define MPI3_MAN12_PATTERN_RATE_2_HZ (0x00000000) #define MPI3_MAN12_PATTERN_RATE_4_HZ (0x20000000) #define MPI3_MAN12_PATTERN_RATE_8_HZ (0x40000000) #define MPI3_MAN12_PATTERN_RATE_16_HZ (0x60000000) #define MPI3_MAN12_PATTERN_RATE_10_HZ (0x80000000) #define MPI3_MAN12_PATTERN_RATE_20_HZ (0xA0000000) #define MPI3_MAN12_PATTERN_RATE_40_HZ (0xC0000000) #define MPI3_MAN12_PATTERN_LENGTH_MASK (0x1F000000) #define MPI3_MAN12_PATTERN_LENGTH_SHIFT (24) #define MPI3_MAN12_PATTERN_BIT_PATTERN_MASK (0x00FFFFFF) #define MPI3_MAN12_PATTERN_BIT_PATTERN_SHIFT (0) /***************************************************************************** * Manufacturing Page 13 * ****************************************************************************/ #ifndef MPI3_MAN13_NUM_TRANSLATION_MAX #define MPI3_MAN13_NUM_TRANSLATION_MAX (1) #endif /* MPI3_MAN13_NUM_TRANSLATION_MAX */ typedef struct _MPI3_MAN13_TRANSLATION_INFO { U32 SlotStatus; /* 0x00 */ U32 Mask; /* 0x04 */ U8 Activity; /* 0x08 */ U8 Locate; /* 0x09 */ U8 Error; /* 0x0A */ U8 Reserved0B; /* 0x0B */ } MPI3_MAN13_TRANSLATION_INFO, MPI3_POINTER PTR_MPI3_MAN13_TRANSLATION_INFO, Mpi3Man13TranslationInfo_t, MPI3_POINTER pMpi3Man13TranslationInfo_t; /**** Defines for the SlotStatus field ****/ #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_FAULT (0x20000000) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_DEVICE_OFF (0x10000000) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_DEVICE_ACTIVITY (0x00800000) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_DO_NOT_REMOVE (0x00400000) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_DEVICE_MISSING (0x00100000) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_INSERT (0x00080000) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_REMOVAL (0x00040000) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_IDENTIFY (0x00020000) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_OK (0x00008000) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_RESERVED_DEVICE (0x00004000) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_HOT_SPARE (0x00002000) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_CONSISTENCY_CHECK (0x00001000) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000800) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_IN_FAILED_ARRAY (0x00000400) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_REBUILD_REMAP (0x00000200) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_REBUILD_REMAP_ABORT (0x00000100) #define MPI3_MAN13_TRANSLATION_SLOTSTATUS_PREDICTED_FAILURE (0x00000040) /**** Defines for the Mask field - use MPI3_MAN13_TRANSLATION_SLOTSTATUS_ defines ****/ /**** Defines for the Activity, Locate, and Error fields ****/ #define MPI3_MAN13_BLINK_PATTERN_FORCE_OFF (0x00) #define MPI3_MAN13_BLINK_PATTERN_FORCE_ON (0x01) #define MPI3_MAN13_BLINK_PATTERN_PATTERN_0 (0x02) #define MPI3_MAN13_BLINK_PATTERN_PATTERN_1 (0x03) #define MPI3_MAN13_BLINK_PATTERN_PATTERN_2 (0x04) #define MPI3_MAN13_BLINK_PATTERN_PATTERN_3 (0x05) #define MPI3_MAN13_BLINK_PATTERN_PATTERN_4 (0x06) #define MPI3_MAN13_BLINK_PATTERN_PATTERN_5 (0x07) #define MPI3_MAN13_BLINK_PATTERN_PATTERN_6 (0x08) #define MPI3_MAN13_BLINK_PATTERN_PATTERN_7 (0x09) #define MPI3_MAN13_BLINK_PATTERN_ACTIVITY (0x0A) #define MPI3_MAN13_BLINK_PATTERN_ACTIVITY_TRAIL (0x0B) typedef struct _MPI3_MAN_PAGE13 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 NumTrans; /* 0x08 */ U8 Reserved09[3]; /* 0x09 */ U32 Reserved0C; /* 0x0C */ MPI3_MAN13_TRANSLATION_INFO Translation[MPI3_MAN13_NUM_TRANSLATION_MAX]; /* 0x10 */ /* variable length */ } MPI3_MAN_PAGE13, MPI3_POINTER PTR_MPI3_MAN_PAGE13, Mpi3ManPage13_t, MPI3_POINTER pMpi3ManPage13_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN13_PAGEVERSION (0x00) /***************************************************************************** * Manufacturing Page 14 * ****************************************************************************/ typedef struct _MPI3_MAN_PAGE14 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumSlotGroups; /* 0x0C */ U8 NumSlots; /* 0x0D */ U16 MaxCertChainLength; /* 0x0E */ U32 SealedSlots; /* 0x10 */ U32 PopulatedSlots; /* 0x14 */ U32 MgmtPTUpdatableSlots; /* 0x18 */ } MPI3_MAN_PAGE14, MPI3_POINTER PTR_MPI3_MAN_PAGE14, Mpi3ManPage14_t, MPI3_POINTER pMpi3ManPage14_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN14_PAGEVERSION (0x00) /**** Defines for the NumSlots field ****/ #define MPI3_MAN14_NUMSLOTS_MAX (32) /***************************************************************************** * Manufacturing Page 15 * ****************************************************************************/ #ifndef MPI3_MAN15_VERSION_RECORD_MAX #define MPI3_MAN15_VERSION_RECORD_MAX 1 #endif /* MPI3_MAN15_VERSION_RECORD_MAX */ typedef struct _MPI3_MAN15_VERSION_RECORD { U16 SPDMVersion; /* 0x00 */ U16 Reserved02; /* 0x02 */ } MPI3_MAN15_VERSION_RECORD, MPI3_POINTER PTR_MPI3_MAN15_VERSION_RECORD, Mpi3Man15VersionRecord_t, MPI3_POINTER pMpi3Man15VersionRecord_t; typedef struct _MPI3_MAN_PAGE15 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 NumVersionRecords; /* 0x08 */ U8 Reserved09[3]; /* 0x09 */ U32 Reserved0C; /* 0x0C */ MPI3_MAN15_VERSION_RECORD VersionRecord[MPI3_MAN15_VERSION_RECORD_MAX]; /* 0x10 */ } MPI3_MAN_PAGE15, MPI3_POINTER PTR_MPI3_MAN_PAGE15, Mpi3ManPage15_t, MPI3_POINTER pMpi3ManPage15_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN15_PAGEVERSION (0x00) /***************************************************************************** * Manufacturing Page 16 * ****************************************************************************/ #ifndef MPI3_MAN16_CERT_ALGO_MAX #define MPI3_MAN16_CERT_ALGO_MAX 1 #endif /* MPI3_MAN16_CERT_ALGO_MAX */ typedef struct _MPI3_MAN16_CERTIFICATE_ALGORITHM { U8 SlotGroup; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ U32 BaseAsymAlgo; /* 0x04 */ U32 BaseHashAlgo; /* 0x08 */ U32 Reserved0C[3]; /* 0x0C */ } MPI3_MAN16_CERTIFICATE_ALGORITHM, MPI3_POINTER PTR_MPI3_MAN16_CERTIFICATE_ALGORITHM, Mpi3Man16CertificateAlgorithm_t, MPI3_POINTER pMpi3Man16CertificateAlgorithm_t; typedef struct _MPI3_MAN_PAGE16 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumCertAlgos; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_MAN16_CERTIFICATE_ALGORITHM CertificateAlgorithm[MPI3_MAN16_CERT_ALGO_MAX]; /* 0x10 */ } MPI3_MAN_PAGE16, MPI3_POINTER PTR_MPI3_MAN_PAGE16, Mpi3ManPage16_t, MPI3_POINTER pMpi3ManPage16_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN16_PAGEVERSION (0x00) /***************************************************************************** * Manufacturing Page 17 * ****************************************************************************/ #ifndef MPI3_MAN17_HASH_ALGORITHM_MAX #define MPI3_MAN17_HASH_ALGORITHM_MAX 1 #endif /* MPI3_MAN17_HASH_ALGORITHM_MAX */ typedef struct _MPI3_MAN17_HASH_ALGORITHM { U8 MeasSpecification; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ U32 MeasurementHashAlgo; /* 0x04 */ U32 Reserved08[2]; /* 0x08 */ } MPI3_MAN17_HASH_ALGORITHM, MPI3_POINTER PTR_MPI3_MAN17_HASH_ALGORITHM, Mpi3Man17HashAlgorithm_t, MPI3_POINTER pMpi3Man17HashAlgorithm_t; typedef struct _MPI3_MAN_PAGE17 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumHashAlgos; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_MAN17_HASH_ALGORITHM HashAlgorithm[MPI3_MAN17_HASH_ALGORITHM_MAX]; /* 0x10 */ } MPI3_MAN_PAGE17, MPI3_POINTER PTR_MPI3_MAN_PAGE17, Mpi3ManPage17_t, MPI3_POINTER pMpi3ManPage17_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN17_PAGEVERSION (0x00) /***************************************************************************** * Manufacturing Page 20 * ****************************************************************************/ typedef struct _MPI3_MAN_PAGE20 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U32 NonpremiumFeatures; /* 0x0C */ U8 AllowedPersonalities; /* 0x10 */ U8 Reserved11[3]; /* 0x11 */ } MPI3_MAN_PAGE20, MPI3_POINTER PTR_MPI3_MAN_PAGE20, Mpi3ManPage20_t, MPI3_POINTER pMpi3ManPage20_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN20_PAGEVERSION (0x00) /**** Defines for the AllowedPersonalities field ****/ #define MPI3_MAN20_ALLOWEDPERSON_RAID_MASK (0x02) #define MPI3_MAN20_ALLOWEDPERSON_RAID_ALLOWED (0x02) #define MPI3_MAN20_ALLOWEDPERSON_RAID_NOT_ALLOWED (0x00) #define MPI3_MAN20_ALLOWEDPERSON_EHBA_MASK (0x01) #define MPI3_MAN20_ALLOWEDPERSON_EHBA_ALLOWED (0x01) #define MPI3_MAN20_ALLOWEDPERSON_EHBA_NOT_ALLOWED (0x00) -/**** Defines for the NonpremuimFeatures field ****/ +/**** Defines for the NonpremiumFeatures field ****/ #define MPI3_MAN20_NONPREMUIM_DISABLE_PD_DEGRADED_MASK (0x01) #define MPI3_MAN20_NONPREMUIM_DISABLE_PD_DEGRADED_ENABLED (0x00) #define MPI3_MAN20_NONPREMUIM_DISABLE_PD_DEGRADED_DISABLED (0x01) /***************************************************************************** * Manufacturing Page 21 * ****************************************************************************/ typedef struct _MPI3_MAN_PAGE21 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U32 Flags; /* 0x0C */ } MPI3_MAN_PAGE21, MPI3_POINTER PTR_MPI3_MAN_PAGE21, Mpi3ManPage21_t, MPI3_POINTER pMpi3ManPage21_t; /**** Defines for the PageVersion field ****/ #define MPI3_MAN21_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_MASK (0x00000060) #define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_BLOCK (0x00000000) #define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_ALLOW (0x00000020) #define MPI3_MAN21_FLAGS_UNCERTIFIED_DRIVES_WARN (0x00000040) #define MPI3_MAN21_FLAGS_BLOCK_SSD_WR_CACHE_CHANGE_MASK (0x00000008) #define MPI3_MAN21_FLAGS_BLOCK_SSD_WR_CACHE_CHANGE_ALLOW (0x00000000) #define MPI3_MAN21_FLAGS_BLOCK_SSD_WR_CACHE_CHANGE_PREVENT (0x00000008) #define MPI3_MAN21_FLAGS_SES_VPD_ASSOC_MASK (0x00000001) #define MPI3_MAN21_FLAGS_SES_VPD_ASSOC_DEFAULT (0x00000000) #define MPI3_MAN21_FLAGS_SES_VPD_ASSOC_OEM_SPECIFIC (0x00000001) +/***************************************************************************** + * Manufacturing Page 22 * + ****************************************************************************/ + +typedef struct _MPI3_MAN_PAGE22 +{ + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U32 Reserved08; /* 0x08 */ + U16 NumEUI64; /* 0x0C */ + U16 Reserved0E; /* 0x0E */ + U64 BaseEUI64; /* 0x10 */ +} MPI3_MAN_PAGE22, MPI3_POINTER PTR_MPI3_MAN_PAGE22, + Mpi3ManPage22_t, MPI3_POINTER pMpi3ManPage22_t; + +/**** Defines for the PageVersion field ****/ +#define MPI3_MAN22_PAGEVERSION (0x00) + /***************************************************************************** * Manufacturing Pages 32-63 (ProductSpecific) * ****************************************************************************/ #ifndef MPI3_MAN_PROD_SPECIFIC_MAX #define MPI3_MAN_PROD_SPECIFIC_MAX (1) #endif /* MPI3_MAN_PROD_SPECIFIC_MAX */ typedef struct _MPI3_MAN_PAGE_PRODUCT_SPECIFIC { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 ProductSpecificInfo[MPI3_MAN_PROD_SPECIFIC_MAX]; /* 0x08 */ /* variable length array */ } MPI3_MAN_PAGE_PRODUCT_SPECIFIC, MPI3_POINTER PTR_MPI3_MAN_PAGE_PRODUCT_SPECIFIC, Mpi3ManPageProductSpecific_t, MPI3_POINTER pMpi3ManPageProductSpecific_t; /***************************************************************************** * IO Unit Configuration Pages * ****************************************************************************/ /***************************************************************************** * IO Unit Page 0 * ****************************************************************************/ typedef struct _MPI3_IO_UNIT_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U64 UniqueValue; /* 0x08 */ U32 NvdataVersionDefault; /* 0x10 */ U32 NvdataVersionPersistent; /* 0x14 */ } MPI3_IO_UNIT_PAGE0, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE0, Mpi3IOUnitPage0_t, MPI3_POINTER pMpi3IOUnitPage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT0_PAGEVERSION (0x00) /***************************************************************************** * IO Unit Page 1 * ****************************************************************************/ typedef struct _MPI3_IO_UNIT_PAGE1 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Flags; /* 0x08 */ U8 DMDIoDelay; /* 0x0C */ U8 DMDReportPCIe; /* 0x0D */ U8 DMDReportSATA; /* 0x0E */ U8 DMDReportSAS; /* 0x0F */ } MPI3_IO_UNIT_PAGE1, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE1, Mpi3IOUnitPage1_t, MPI3_POINTER pMpi3IOUnitPage1_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT1_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_IOUNIT1_FLAGS_NVME_WRITE_CACHE_MASK (0x00000030) #define MPI3_IOUNIT1_FLAGS_NVME_WRITE_CACHE_ENABLE (0x00000000) #define MPI3_IOUNIT1_FLAGS_NVME_WRITE_CACHE_DISABLE (0x00000010) #define MPI3_IOUNIT1_FLAGS_NVME_WRITE_CACHE_NO_MODIFY (0x00000020) #define MPI3_IOUNIT1_FLAGS_ATA_SECURITY_FREEZE_LOCK (0x00000008) #define MPI3_IOUNIT1_FLAGS_WRITE_SAME_BUFFER (0x00000004) #define MPI3_IOUNIT1_FLAGS_SATA_WRITE_CACHE_MASK (0x00000003) #define MPI3_IOUNIT1_FLAGS_SATA_WRITE_CACHE_ENABLE (0x00000000) #define MPI3_IOUNIT1_FLAGS_SATA_WRITE_CACHE_DISABLE (0x00000001) #define MPI3_IOUNIT1_FLAGS_SATA_WRITE_CACHE_UNCHANGED (0x00000002) /**** Defines for the DMDReport PCIe/SATA/SAS fields ****/ #define MPI3_IOUNIT1_DMD_REPORT_DELAY_TIME_MASK (0x7F) #define MPI3_IOUNIT1_DMD_REPORT_UNIT_16_SEC (0x80) /***************************************************************************** * IO Unit Page 2 * ****************************************************************************/ #ifndef MPI3_IO_UNIT2_GPIO_VAL_MAX #define MPI3_IO_UNIT2_GPIO_VAL_MAX (1) #endif /* MPI3_IO_UNIT2_GPIO_VAL_MAX */ typedef struct _MPI3_IO_UNIT_PAGE2 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 GPIOCount; /* 0x08 */ U8 Reserved09[3]; /* 0x09 */ U16 GPIOVal[MPI3_IO_UNIT2_GPIO_VAL_MAX]; /* 0x0C */ } MPI3_IO_UNIT_PAGE2, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE2, Mpi3IOUnitPage2_t, MPI3_POINTER pMpi3IOUnitPage2_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT2_PAGEVERSION (0x00) /**** Define for the GPIOVal field ****/ #define MPI3_IOUNIT2_GPIO_FUNCTION_MASK (0xFFFC) #define MPI3_IOUNIT2_GPIO_FUNCTION_SHIFT (2) #define MPI3_IOUNIT2_GPIO_SETTING_MASK (0x0001) #define MPI3_IOUNIT2_GPIO_SETTING_OFF (0x0000) #define MPI3_IOUNIT2_GPIO_SETTING_ON (0x0001) /***************************************************************************** * IO Unit Page 3 * ****************************************************************************/ +typedef enum _MPI3_IOUNIT3_THRESHOLD +{ + MPI3_IOUNIT3_THRESHOLD_WARNING = 0, + MPI3_IOUNIT3_THRESHOLD_CRITICAL = 1, + MPI3_IOUNIT3_THRESHOLD_FATAL = 2, + MPI3_IOUNIT3_THRESHOLD_LOW = 3, + MPI3_IOUNIT3_NUM_THRESHOLDS +} MPI3_IOUNIT3_THRESHOLD; + typedef struct _MPI3_IO_UNIT3_SENSOR { U16 Flags; /* 0x00 */ U8 ThresholdMargin; /* 0x02 */ U8 Reserved03; /* 0x03 */ - U16 Threshold[3]; /* 0x04 */ - U16 Reserved0A; /* 0x0A */ + U16 Threshold[MPI3_IOUNIT3_NUM_THRESHOLDS]; /* 0x04 */ U32 Reserved0C; /* 0x0C */ U32 Reserved10; /* 0x10 */ U32 Reserved14; /* 0x14 */ } MPI3_IO_UNIT3_SENSOR, MPI3_POINTER PTR_MPI3_IO_UNIT3_SENSOR, Mpi3IOUnit3Sensor_t, MPI3_POINTER pMpi3IOUnit3Sensor_t; /**** Defines for the Flags field ****/ +#define MPI3_IOUNIT3_SENSOR_FLAGS_LOW_THRESHOLD_VALID (0x0020) #define MPI3_IOUNIT3_SENSOR_FLAGS_FATAL_EVENT_ENABLED (0x0010) #define MPI3_IOUNIT3_SENSOR_FLAGS_FATAL_ACTION_ENABLED (0x0008) #define MPI3_IOUNIT3_SENSOR_FLAGS_CRITICAL_EVENT_ENABLED (0x0004) #define MPI3_IOUNIT3_SENSOR_FLAGS_CRITICAL_ACTION_ENABLED (0x0002) #define MPI3_IOUNIT3_SENSOR_FLAGS_WARNING_EVENT_ENABLED (0x0001) #ifndef MPI3_IO_UNIT3_SENSOR_MAX #define MPI3_IO_UNIT3_SENSOR_MAX (1) #endif /* MPI3_IO_UNIT3_SENSOR_MAX */ typedef struct _MPI3_IO_UNIT_PAGE3 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumSensors; /* 0x0C */ U8 NominalPollInterval; /* 0x0D */ U8 WarningPollInterval; /* 0x0E */ U8 Reserved0F; /* 0x0F */ MPI3_IO_UNIT3_SENSOR Sensor[MPI3_IO_UNIT3_SENSOR_MAX]; /* 0x10 */ } MPI3_IO_UNIT_PAGE3, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE3, Mpi3IOUnitPage3_t, MPI3_POINTER pMpi3IOUnitPage3_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT3_PAGEVERSION (0x00) /***************************************************************************** * IO Unit Page 4 * ****************************************************************************/ typedef struct _MPI3_IO_UNIT4_SENSOR { U16 CurrentTemperature; /* 0x00 */ U16 Reserved02; /* 0x02 */ U8 Flags; /* 0x04 */ U8 Reserved05[3]; /* 0x05 */ U16 ISTWIIndex; /* 0x08 */ U8 Channel; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 Reserved0C; /* 0x0C */ } MPI3_IO_UNIT4_SENSOR, MPI3_POINTER PTR_MPI3_IO_UNIT4_SENSOR, Mpi3IOUnit4Sensor_t, MPI3_POINTER pMpi3IOUnit4Sensor_t; /**** Defines for the Flags field ****/ #define MPI3_IOUNIT4_SENSOR_FLAGS_LOC_MASK (0xE0) #define MPI3_IOUNIT4_SENSOR_FLAGS_LOC_SHIFT (5) /**** for the Location field values - use MPI3_TEMP_SENSOR_LOCATION_ defines ****/ #define MPI3_IOUNIT4_SENSOR_FLAGS_TEMP_VALID (0x01) /**** Defines for the ISTWIIndex field ****/ #define MPI3_IOUNIT4_SENSOR_ISTWI_INDEX_INTERNAL (0xFFFF) /**** Defines for the Channel field ****/ #define MPI3_IOUNIT4_SENSOR_CHANNEL_RESERVED (0xFF) #ifndef MPI3_IO_UNIT4_SENSOR_MAX #define MPI3_IO_UNIT4_SENSOR_MAX (1) #endif /* MPI3_IO_UNIT4_SENSOR_MAX */ typedef struct _MPI3_IO_UNIT_PAGE4 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumSensors; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_IO_UNIT4_SENSOR Sensor[MPI3_IO_UNIT4_SENSOR_MAX]; /* 0x10 */ } MPI3_IO_UNIT_PAGE4, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE4, Mpi3IOUnitPage4_t, MPI3_POINTER pMpi3IOUnitPage4_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT4_PAGEVERSION (0x00) /***************************************************************************** * IO Unit Page 5 * ****************************************************************************/ typedef struct _MPI3_IO_UNIT5_SPINUP_GROUP { U8 MaxTargetSpinup; /* 0x00 */ U8 SpinupDelay; /* 0x01 */ U8 SpinupFlags; /* 0x02 */ U8 Reserved03; /* 0x03 */ } MPI3_IO_UNIT5_SPINUP_GROUP, MPI3_POINTER PTR_MPI3_IO_UNIT5_SPINUP_GROUP, Mpi3IOUnit5SpinupGroup_t, MPI3_POINTER pMpi3IOUnit5SpinupGroup_t; /**** Defines for the SpinupFlags field ****/ #define MPI3_IOUNIT5_SPINUP_FLAGS_DISABLE (0x01) #ifndef MPI3_IO_UNIT5_PHY_MAX #define MPI3_IO_UNIT5_PHY_MAX (4) #endif /* MPI3_IO_UNIT5_PHY_MAX */ typedef struct _MPI3_IO_UNIT_PAGE5 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ MPI3_IO_UNIT5_SPINUP_GROUP SpinupGroupParameters[4]; /* 0x08 */ U32 Reserved18; /* 0x18 */ U32 Reserved1C; /* 0x1C */ U16 DeviceShutdown; /* 0x20 */ U16 Reserved22; /* 0x22 */ U8 PCIeDeviceWaitTime; /* 0x24 */ U8 SATADeviceWaitTime; /* 0x25 */ U8 SpinupEnclDriveCount; /* 0x26 */ U8 SpinupEnclDelay; /* 0x27 */ U8 NumPhys; /* 0x28 */ U8 PEInitialSpinupDelay; /* 0x29 */ U8 TopologyStableTime; /* 0x2A */ U8 Flags; /* 0x2B */ U8 Phy[MPI3_IO_UNIT5_PHY_MAX]; /* 0x2C */ } MPI3_IO_UNIT_PAGE5, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE5, Mpi3IOUnitPage5_t, MPI3_POINTER pMpi3IOUnitPage5_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT5_PAGEVERSION (0x00) /**** Defines for the DeviceShutdown field ****/ #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_NO_ACTION (0x00) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_DIRECT_ATTACHED (0x01) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_EXPANDER_ATTACHED (0x02) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SWITCH_ATTACHED (0x02) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_DIRECT_AND_EXPANDER (0x03) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_DIRECT_AND_SWITCH (0x03) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_HDD_MASK (0x0300) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_HDD_SHIFT (8) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_HDD_MASK (0x00C0) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_HDD_SHIFT (6) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_NVME_SSD_MASK (0x0030) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_NVME_SSD_SHIFT (4) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_SSD_MASK (0x000C) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SATA_SSD_SHIFT (2) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_SSD_MASK (0x0003) #define MPI3_IOUNIT5_DEVICE_SHUTDOWN_SAS_SSD_SHIFT (0) /**** Defines for the Flags field ****/ #define MPI3_IOUNIT5_FLAGS_SATAPUIS_MASK (0x0C) #define MPI3_IOUNIT5_FLAGS_SATAPUIS_SHIFT (2) #define MPI3_IOUNIT5_FLAGS_SATAPUIS_NOT_SUPPORTED (0x00) #define MPI3_IOUNIT5_FLAGS_SATAPUIS_OS_CONTROLLED (0x04) #define MPI3_IOUNIT5_FLAGS_SATAPUIS_APP_CONTROLLED (0x08) #define MPI3_IOUNIT5_FLAGS_SATAPUIS_BLOCKED (0x0C) #define MPI3_IOUNIT5_FLAGS_POWER_CAPABLE_SPINUP (0x02) #define MPI3_IOUNIT5_FLAGS_AUTO_PORT_ENABLE (0x01) -/**** Defines for the PHY field ****/ +/**** Defines for the Phy field ****/ #define MPI3_IOUNIT5_PHY_SPINUP_GROUP_MASK (0x03) /***************************************************************************** * IO Unit Page 6 * ****************************************************************************/ typedef struct _MPI3_IO_UNIT_PAGE6 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 BoardPowerRequirement; /* 0x08 */ U32 PCISlotPowerAllocation; /* 0x0C */ U8 Flags; /* 0x10 */ U8 Reserved11[3]; /* 0x11 */ } MPI3_IO_UNIT_PAGE6, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE6, Mpi3IOUnitPage6_t, MPI3_POINTER pMpi3IOUnitPage6_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT6_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_IOUNIT6_FLAGS_ACT_CABLE_PWR_EXC (0x01) /***************************************************************************** * IO Unit Page 8 * ****************************************************************************/ #ifndef MPI3_IOUNIT8_DIGEST_MAX #define MPI3_IOUNIT8_DIGEST_MAX (1) #endif /* MPI3_IOUNIT8_DIGEST_MAX */ -typedef union _MPI3_IOUNIT8_DIGEST +typedef union _MPI3_IOUNIT8_RAW_DIGEST { U32 Dword[16]; U16 Word[32]; U8 Byte[64]; +} MPI3_IOUNIT8_RAW_DIGEST, MPI3_POINTER PTR_MPI3_IOUNIT8_RAW_DIGEST, + Mpi3IOUnit8RawDigest_t, MPI3_POINTER pMpi3IOUnit8RawDigest_t; + +typedef struct _MPI3_IOUNIT8_METADATA_DIGEST +{ + U8 SlotStatus; /* 0x00 */ + U8 Reserved01[3]; /* 0x01 */ + U32 Reserved04[3]; /* 0x04 */ + MPI3_IOUNIT8_RAW_DIGEST DigestData; /* 0x10 */ +} MPI3_IOUNIT8_METADATA_DIGEST, MPI3_POINTER PTR_MPI3_IOUNIT8_METADATA_DIGEST, + Mpi3IOUnit8MetadataDigest_t, MPI3_POINTER pMpi3IOUnit8MetadataDigest_t; + +/**** Defines for the SlotStatus field ****/ +#define MPI3_IOUNIT8_METADATA_DIGEST_SLOTSTATUS_UNUSED (0x00) +#define MPI3_IOUNIT8_METADATA_DIGEST_SLOTSTATUS_UPDATE_PENDING (0x01) +#define MPI3_IOUNIT8_METADATA_DIGEST_SLOTSTATUS_VALID (0x03) +#define MPI3_IOUNIT8_METADATA_DIGEST_SLOTSTATUS_INVALID (0x07) + +typedef union _MPI3_IOUNIT8_DIGEST +{ + MPI3_IOUNIT8_RAW_DIGEST RawDigest[MPI3_IOUNIT8_DIGEST_MAX]; + MPI3_IOUNIT8_METADATA_DIGEST MetadataDigest[MPI3_IOUNIT8_DIGEST_MAX]; } MPI3_IOUNIT8_DIGEST, MPI3_POINTER PTR_MPI3_IOUNIT8_DIGEST, Mpi3IOUnit8Digest_t, MPI3_POINTER pMpi3IOUnit8Digest_t; typedef struct _MPI3_IO_UNIT_PAGE8 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 SBMode; /* 0x08 */ - U8 SbState; /* 0x09 */ - U16 Reserved0A; /* 0x0A */ + U8 SBState; /* 0x09 */ + U8 Flags; /* 0x0A */ + U8 Reserved0A; /* 0x0B */ U8 NumSlots; /* 0x0C */ U8 SlotsAvailable; /* 0x0D */ U8 CurrentKeyEncryptionAlgo; /* 0x0E */ U8 KeyDigestHashAlgo; /* 0x0F */ MPI3_VERSION_UNION CurrentSvn; /* 0x10 */ U32 Reserved14; /* 0x14 */ U32 CurrentKey[128]; /* 0x18 */ - MPI3_IOUNIT8_DIGEST Digest[MPI3_IOUNIT8_DIGEST_MAX]; /* 0x218 */ /* variable length */ + MPI3_IOUNIT8_DIGEST Digest; /* 0x218 */ /* variable length */ } MPI3_IO_UNIT_PAGE8, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE8, Mpi3IOUnitPage8_t, MPI3_POINTER pMpi3IOUnitPage8_t; /**** Defines for the PageVersion field ****/ -#define MPI3_IOUNIT8_PAGEVERSION (0x00) +#define MPI3_IOUNIT8_PAGEVERSION (0x00) /**** Defines for the SBMode field ****/ -#define MPI3_IOUNIT8_SBMODE_SECURE_DEBUG (0x04) -#define MPI3_IOUNIT8_SBMODE_HARD_SECURE (0x02) -#define MPI3_IOUNIT8_SBMODE_CONFIG_SECURE (0x01) +#define MPI3_IOUNIT8_SBMODE_SECURE_DEBUG (0x04) +#define MPI3_IOUNIT8_SBMODE_HARD_SECURE (0x02) +#define MPI3_IOUNIT8_SBMODE_CONFIG_SECURE (0x01) /**** Defines for the SBState field ****/ -#define MPI3_IOUNIT8_SBSTATE_SVN_UPDATE_PENDING (0x04) -#define MPI3_IOUNIT8_SBSTATE_KEY_UPDATE_PENDING (0x02) -#define MPI3_IOUNIT8_SBSTATE_SECURE_BOOT_ENABLED (0x01) +#define MPI3_IOUNIT8_SBSTATE_SVN_UPDATE_PENDING (0x04) +#define MPI3_IOUNIT8_SBSTATE_KEY_UPDATE_PENDING (0x02) +#define MPI3_IOUNIT8_SBSTATE_SECURE_BOOT_ENABLED (0x01) + +/**** Defines for the Flags field ****/ +#define MPI3_IOUNIT8_FLAGS_DIGESTFORM_MASK (0x07) +#define MPI3_IOUNIT8_FLAGS_DIGESTFORM_RAW (0x00) +#define MPI3_IOUNIT8_FLAGS_DIGESTFORM_DIGEST_WITH_METADATA (0x01) /***************************************************************************** * IO Unit Page 9 * ****************************************************************************/ typedef struct _MPI3_IO_UNIT_PAGE9 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Flags; /* 0x08 */ U16 FirstDevice; /* 0x0C */ U16 Reserved0E; /* 0x0E */ } MPI3_IO_UNIT_PAGE9, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE9, Mpi3IOUnitPage9_t, MPI3_POINTER pMpi3IOUnitPage9_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT9_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_IOUNIT9_FLAGS_UBM_ENCLOSURE_ORDER_MASK (0x00000006) #define MPI3_IOUNIT9_FLAGS_UBM_ENCLOSURE_ORDER_SHIFT (1) #define MPI3_IOUNIT9_FLAGS_UBM_ENCLOSURE_ORDER_NONE (0x00000000) #define MPI3_IOUNIT9_FLAGS_UBM_ENCLOSURE_ORDER_RECEPTACLE (0x00000002) #define MPI3_IOUNIT9_FLAGS_UBM_ENCLOSURE_ORDER_BACKPLANE_TYPE (0x00000004) #define MPI3_IOUNIT9_FLAGS_VDFIRST_ENABLED (0x00000001) /**** Defines for the FirstDevice field ****/ #define MPI3_IOUNIT9_FIRSTDEVICE_UNKNOWN (0xFFFF) /***************************************************************************** * IO Unit Page 10 * ****************************************************************************/ typedef struct _MPI3_IO_UNIT_PAGE10 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 Flags; /* 0x08 */ U8 Reserved09[3]; /* 0x09 */ U32 SiliconID; /* 0x0C */ U8 FWVersionMinor; /* 0x10 */ U8 FWVersionMajor; /* 0x11 */ U8 HWVersionMinor; /* 0x12 */ U8 HWVersionMajor; /* 0x13 */ U8 PartNumber[16]; /* 0x14 */ } MPI3_IO_UNIT_PAGE10, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE10, Mpi3IOUnitPage10_t, MPI3_POINTER pMpi3IOUnitPage10_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT10_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_IOUNIT10_FLAGS_VALID (0x01) #define MPI3_IOUNIT10_FLAGS_ACTIVEID_MASK (0x02) #define MPI3_IOUNIT10_FLAGS_ACTIVEID_FIRST_REGION (0x00) #define MPI3_IOUNIT10_FLAGS_ACTIVEID_SECOND_REGION (0x02) #define MPI3_IOUNIT10_FLAGS_PBLP_EXPECTED (0x80) /***************************************************************************** * IO Unit Page 11 * ****************************************************************************/ #ifndef MPI3_IOUNIT11_PROFILE_MAX #define MPI3_IOUNIT11_PROFILE_MAX (1) #endif /* MPI3_IOUNIT11_PROFILE_MAX */ typedef struct _MPI3_IOUNIT11_PROFILE { U8 ProfileIdentifier; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ U16 MaxVDs; /* 0x04 */ U16 MaxHostPDs; /* 0x06 */ U16 MaxAdvHostPDs; /* 0x08 */ U16 MaxRAIDPDs; /* 0x0A */ U16 MaxNVMe; /* 0x0C */ U16 MaxOutstandingRequests; /* 0x0E */ U16 SubsystemID; /* 0x10 */ U16 Reserved12; /* 0x12 */ U32 Reserved14[2]; /* 0x14 */ } MPI3_IOUNIT11_PROFILE, MPI3_POINTER PTR_MPI3_IOUNIT11_PROFILE, Mpi3IOUnit11Profile_t, MPI3_POINTER pMpi3IOUnit11Profile_t; typedef struct _MPI3_IO_UNIT_PAGE11 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumProfiles; /* 0x0C */ U8 CurrentProfileIdentifier; /* 0x0D */ U16 Reserved0E; /* 0x0E */ MPI3_IOUNIT11_PROFILE Profile[MPI3_IOUNIT11_PROFILE_MAX]; /* 0x10 */ /* variable length */ } MPI3_IO_UNIT_PAGE11, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE11, Mpi3IOUnitPage11_t, MPI3_POINTER pMpi3IOUnitPage11_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT11_PAGEVERSION (0x00) /***************************************************************************** * IO Unit Page 12 * ****************************************************************************/ #ifndef MPI3_IOUNIT12_BUCKET_MAX #define MPI3_IOUNIT12_BUCKET_MAX (1) #endif /* MPI3_IOUNIT12_BUCKET_MAX */ typedef struct _MPI3_IOUNIT12_BUCKET { U8 CoalescingDepth; /* 0x00 */ U8 CoalescingTimeout; /* 0x01 */ U16 IOCountLowBoundary; /* 0x02 */ U32 Reserved04; /* 0x04 */ } MPI3_IOUNIT12_BUCKET, MPI3_POINTER PTR_MPI3_IOUNIT12_BUCKET, Mpi3IOUnit12Bucket_t, MPI3_POINTER pMpi3IOUnit12Bucket_t; typedef struct _MPI3_IO_UNIT_PAGE12 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Flags; /* 0x08 */ U32 Reserved0C[4]; /* 0x0C */ U8 NumBuckets; /* 0x1C */ U8 Reserved1D[3]; /* 0x1D */ MPI3_IOUNIT12_BUCKET Bucket[MPI3_IOUNIT12_BUCKET_MAX]; /* 0x20 */ /* variable length */ } MPI3_IO_UNIT_PAGE12, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE12, Mpi3IOUnitPage12_t, MPI3_POINTER pMpi3IOUnitPage12_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT12_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_IOUNIT12_FLAGS_NUMPASSES_MASK (0x00000300) #define MPI3_IOUNIT12_FLAGS_NUMPASSES_SHIFT (8) #define MPI3_IOUNIT12_FLAGS_NUMPASSES_8 (0x00000000) #define MPI3_IOUNIT12_FLAGS_NUMPASSES_16 (0x00000100) #define MPI3_IOUNIT12_FLAGS_NUMPASSES_32 (0x00000200) #define MPI3_IOUNIT12_FLAGS_NUMPASSES_64 (0x00000300) #define MPI3_IOUNIT12_FLAGS_PASSPERIOD_MASK (0x00000003) #define MPI3_IOUNIT12_FLAGS_PASSPERIOD_DISABLED (0x00000000) #define MPI3_IOUNIT12_FLAGS_PASSPERIOD_500US (0x00000001) #define MPI3_IOUNIT12_FLAGS_PASSPERIOD_1MS (0x00000002) #define MPI3_IOUNIT12_FLAGS_PASSPERIOD_2MS (0x00000003) /***************************************************************************** * IO Unit Page 13 * ****************************************************************************/ #ifndef MPI3_IOUNIT13_FUNC_MAX #define MPI3_IOUNIT13_FUNC_MAX (1) #endif /* MPI3_IOUNIT13_FUNC_MAX */ typedef struct _MPI3_IOUNIT13_ALLOWED_FUNCTION { U16 SubFunction; /* 0x00 */ U8 FunctionCode; /* 0x02 */ U8 FunctionFlags; /* 0x03 */ } MPI3_IOUNIT13_ALLOWED_FUNCTION, MPI3_POINTER PTR_MPI3_IOUNIT13_ALLOWED_FUNCTION, Mpi3IOUnit13AllowedFunction_t, MPI3_POINTER pMpi3IOUnit13AllowedFunction_t; /**** Defines for the FunctionFlags field ****/ #define MPI3_IOUNIT13_FUNCTION_FLAGS_ADMIN_BLOCKED (0x04) #define MPI3_IOUNIT13_FUNCTION_FLAGS_OOB_BLOCKED (0x02) #define MPI3_IOUNIT13_FUNCTION_FLAGS_CHECK_SUBFUNCTION_ENABLED (0x01) typedef struct _MPI3_IO_UNIT_PAGE13 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U16 Flags; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U8 NumAllowedFunctions; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_IOUNIT13_ALLOWED_FUNCTION AllowedFunction[MPI3_IOUNIT13_FUNC_MAX]; /* 0x10 */ /* variable length */ } MPI3_IO_UNIT_PAGE13, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE13, Mpi3IOUnitPage13_t, MPI3_POINTER pMpi3IOUnitPage13_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT13_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_IOUNIT13_FLAGS_ADMIN_BLOCKED (0x0002) #define MPI3_IOUNIT13_FLAGS_OOB_BLOCKED (0x0001) /***************************************************************************** * IO Unit Page 14 * ****************************************************************************/ #ifndef MPI3_IOUNIT14_MD_MAX #define MPI3_IOUNIT14_MD_MAX (1) #endif /* MPI3_IOUNIT14_MD_MAX */ typedef struct _MPI3_IOUNIT14_PAGEMETADATA { U8 PageType; /* 0x00 */ U8 PageNumber; /* 0x01 */ U8 Reserved02; /* 0x02 */ U8 PageFlags; /* 0x03 */ } MPI3_IOUNIT14_PAGEMETADATA, MPI3_POINTER PTR_MPI3_IOUNIT14_PAGEMETADATA, Mpi3IOUnit14PageMetadata_t, MPI3_POINTER pMpi3IOUnit14PageMetadata_t; /**** Defines for the PageFlags field ****/ #define MPI3_IOUNIT14_PAGEMETADATA_PAGEFLAGS_OOBWRITE_ALLOWED (0x02) #define MPI3_IOUNIT14_PAGEMETADATA_PAGEFLAGS_HOSTWRITE_ALLOWED (0x01) typedef struct _MPI3_IO_UNIT_PAGE14 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 Flags; /* 0x08 */ U8 Reserved09[3]; /* 0x09 */ U8 NumPages; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_IOUNIT14_PAGEMETADATA PageMetadata[MPI3_IOUNIT14_MD_MAX]; /* 0x10 */ /* variable length */ } MPI3_IO_UNIT_PAGE14, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE14, Mpi3IOUnitPage14_t, MPI3_POINTER pMpi3IOUnitPage14_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT14_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_IOUNIT14_FLAGS_READONLY (0x01) /***************************************************************************** * IO Unit Page 15 * ****************************************************************************/ #ifndef MPI3_IOUNIT15_PBD_MAX #define MPI3_IOUNIT15_PBD_MAX (1) #endif /* MPI3_IOUNIT15_PBD_MAX */ typedef struct _MPI3_IO_UNIT_PAGE15 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 Flags; /* 0x08 */ U8 Reserved09[3]; /* 0x09 */ U32 Reserved0C; /* 0x0C */ U8 PowerBudgetingCapability; /* 0x10 */ U8 Reserved11[3]; /* 0x11 */ U8 NumPowerBudgetData; /* 0x14 */ U8 Reserved15[3]; /* 0x15 */ U32 PowerBudgetData[MPI3_IOUNIT15_PBD_MAX]; /* 0x18 */ /* variable length */ } MPI3_IO_UNIT_PAGE15, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE15, Mpi3IOUnitPage15_t, MPI3_POINTER pMpi3IOUnitPage15_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOUNIT15_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_IOUNIT15_FLAGS_EPRINIT_INITREQUIRED (0x04) #define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_MASK (0x03) #define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_NOT_SUPPORTED (0x00) #define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_WITHOUT_POWER_BRAKE_GPIO (0x01) #define MPI3_IOUNIT15_FLAGS_EPRSUPPORT_WITH_POWER_BRAKE_GPIO (0x02) /**** Defines for the NumPowerBudgetData field ****/ #define MPI3_IOUNIT15_NUMPOWERBUDGETDATA_POWER_BUDGETING_DISABLED (0x00) +/***************************************************************************** + * IO Unit Page 16 * + ****************************************************************************/ + +#ifndef MPI3_IOUNIT16_ERROR_MAX +#define MPI3_IOUNIT16_ERROR_MAX (1) +#endif /* MPI3_IOUNIT16_ERROR_MAX */ + +typedef struct _MPI3_IOUNIT16_ERROR +{ + U32 Offset; /* 0x00 */ + U32 Reserved04; /* 0x04 */ + U64 Count; /* 0x08 */ + U64 Timestamp; /* 0x10 */ +} MPI3_IOUNIT16_ERROR, MPI3_POINTER PTR_MPI3_IOUNIT16_ERROR, + Mpi3IOUnit16Error_t, MPI3_POINTER pMpi3IOUnit16Error_t; + +typedef struct _MPI3_IO_UNIT_PAGE16 +{ + MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ + U64 TotalErrorCount; /* 0x08 */ + U32 Reserved10[3]; /* 0x10 */ + U8 NumErrors; /* 0x1C */ + U8 MaxErrorsTracked; /* 0x1D */ + U16 Reserved1E; /* 0x1E */ + MPI3_IOUNIT16_ERROR Error[MPI3_IOUNIT16_ERROR_MAX]; /* 0x20 */ /* variable length */ +} MPI3_IO_UNIT_PAGE16, MPI3_POINTER PTR_MPI3_IO_UNIT_PAGE16, + Mpi3IOUnitPage16_t, MPI3_POINTER pMpi3IOUnitPage16_t; + +/**** Defines for the PageVersion field ****/ +#define MPI3_IOUNIT16_PAGEVERSION (0x00) + /***************************************************************************** * IOC Configuration Pages * ****************************************************************************/ /***************************************************************************** * IOC Page 0 * ****************************************************************************/ typedef struct _MPI3_IOC_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U16 VendorID; /* 0x0C */ U16 DeviceID; /* 0x0E */ U8 RevisionID; /* 0x10 */ U8 Reserved11[3]; /* 0x11 */ U32 ClassCode; /* 0x14 */ U16 SubsystemVendorID; /* 0x18 */ U16 SubsystemID; /* 0x1A */ } MPI3_IOC_PAGE0, MPI3_POINTER PTR_MPI3_IOC_PAGE0, Mpi3IOCPage0_t, MPI3_POINTER pMpi3IOCPage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOC0_PAGEVERSION (0x00) /***************************************************************************** * IOC Page 1 * ****************************************************************************/ typedef struct _MPI3_IOC_PAGE1 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 CoalescingTimeout; /* 0x08 */ U8 CoalescingDepth; /* 0x0C */ U8 Obsolete; /* 0x0D */ U16 Reserved0E; /* 0x0E */ } MPI3_IOC_PAGE1, MPI3_POINTER PTR_MPI3_IOC_PAGE1, Mpi3IOCPage1_t, MPI3_POINTER pMpi3IOCPage1_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOC1_PAGEVERSION (0x00) /***************************************************************************** * IOC Page 2 * ****************************************************************************/ #ifndef MPI3_IOC2_EVENTMASK_WORDS #define MPI3_IOC2_EVENTMASK_WORDS (4) #endif /* MPI3_IOC2_EVENTMASK_WORDS */ typedef struct _MPI3_IOC_PAGE2 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U16 SASBroadcastPrimitiveMasks; /* 0x0C */ U16 SASNotifyPrimitiveMasks; /* 0x0E */ U32 EventMasks[MPI3_IOC2_EVENTMASK_WORDS]; /* 0x10 */ } MPI3_IOC_PAGE2, MPI3_POINTER PTR_MPI3_IOC_PAGE2, Mpi3IOCPage2_t, MPI3_POINTER pMpi3IOCPage2_t; /**** Defines for the PageVersion field ****/ #define MPI3_IOC2_PAGEVERSION (0x00) /***************************************************************************** * Driver Configuration Pages * ****************************************************************************/ -/**** Defines for the Flags field ****/ +/**** Defines for the Flags field in Driver Pages 10, 20, and 30 ****/ +/**** NOT used in Driver Page 1 Flags field ****/ #define MPI3_DRIVER_FLAGS_ADMINRAIDPD_BLOCKED (0x0010) #define MPI3_DRIVER_FLAGS_OOBRAIDPD_BLOCKED (0x0008) #define MPI3_DRIVER_FLAGS_OOBRAIDVD_BLOCKED (0x0004) #define MPI3_DRIVER_FLAGS_OOBADVHOSTPD_BLOCKED (0x0002) #define MPI3_DRIVER_FLAGS_OOBHOSTPD_BLOCKED (0x0001) typedef struct _MPI3_ALLOWED_CMD_SCSI { U16 ServiceAction; /* 0x00 */ U8 OperationCode; /* 0x02 */ U8 CommandFlags; /* 0x03 */ } MPI3_ALLOWED_CMD_SCSI, MPI3_POINTER PTR_MPI3_ALLOWED_CMD_SCSI, Mpi3AllowedCmdScsi_t, MPI3_POINTER pMpi3AllowedCmdScsi_t; typedef struct _MPI3_ALLOWED_CMD_ATA { U8 Subcommand; /* 0x00 */ U8 Reserved01; /* 0x01 */ U8 Command; /* 0x02 */ U8 CommandFlags; /* 0x03 */ } MPI3_ALLOWED_CMD_ATA, MPI3_POINTER PTR_MPI3_ALLOWED_CMD_ATA, Mpi3AllowedCmdAta_t, MPI3_POINTER pMpi3AllowedCmdAta_t; typedef struct _MPI3_ALLOWED_CMD_NVME { U8 Reserved00; /* 0x00 */ U8 NVMeCmdFlags; /* 0x01 */ U8 OpCode; /* 0x02 */ U8 CommandFlags; /* 0x03 */ } MPI3_ALLOWED_CMD_NVME, MPI3_POINTER PTR_MPI3_ALLOWED_CMD_NVME, Mpi3AllowedCmdNvme_t, MPI3_POINTER pMpi3AllowedCmdNvme_t; -/**** Defines for the CommandFlags field ****/ +/**** Defines for the NVMeCmdFlags field ****/ #define MPI3_DRIVER_ALLOWEDCMD_NVMECMDFLAGS_SUBQ_TYPE_MASK (0x80) #define MPI3_DRIVER_ALLOWEDCMD_NVMECMDFLAGS_SUBQ_TYPE_IO (0x00) #define MPI3_DRIVER_ALLOWEDCMD_NVMECMDFLAGS_SUBQ_TYPE_ADMIN (0x80) #define MPI3_DRIVER_ALLOWEDCMD_NVMECMDFLAGS_CMDSET_MASK (0x3F) #define MPI3_DRIVER_ALLOWEDCMD_NVMECMDFLAGS_CMDSET_NVM (0x00) typedef union _MPI3_ALLOWED_CMD { MPI3_ALLOWED_CMD_SCSI Scsi; MPI3_ALLOWED_CMD_ATA Ata; MPI3_ALLOWED_CMD_NVME NVMe; } MPI3_ALLOWED_CMD, MPI3_POINTER PTR_MPI3_ALLOWED_CMD, Mpi3AllowedCmd_t, MPI3_POINTER pMpi3AllowedCmd_t; /**** Defines for the CommandFlags field ****/ #define MPI3_DRIVER_ALLOWEDCMD_CMDFLAGS_ADMINRAIDPD_BLOCKED (0x20) #define MPI3_DRIVER_ALLOWEDCMD_CMDFLAGS_OOBRAIDPD_BLOCKED (0x10) #define MPI3_DRIVER_ALLOWEDCMD_CMDFLAGS_OOBRAIDVD_BLOCKED (0x08) #define MPI3_DRIVER_ALLOWEDCMD_CMDFLAGS_OOBADVHOSTPD_BLOCKED (0x04) #define MPI3_DRIVER_ALLOWEDCMD_CMDFLAGS_OOBHOSTPD_BLOCKED (0x02) #define MPI3_DRIVER_ALLOWEDCMD_CMDFLAGS_CHECKSUBCMD_ENABLED (0x01) #ifndef MPI3_ALLOWED_CMDS_MAX #define MPI3_ALLOWED_CMDS_MAX (1) #endif /* MPI3_ALLOWED_CMDS_MAX */ /***************************************************************************** * Driver Page 0 * ****************************************************************************/ typedef struct _MPI3_DRIVER_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 BSDOptions; /* 0x08 */ U8 SSUTimeout; /* 0x0C */ U8 IOTimeout; /* 0x0D */ U8 TURRetries; /* 0x0E */ U8 TURInterval; /* 0x0F */ U8 Reserved10; /* 0x10 */ U8 SecurityKeyTimeout; /* 0x11 */ U16 Reserved12; /* 0x12 */ U32 Reserved14; /* 0x14 */ U32 Reserved18; /* 0x18 */ } MPI3_DRIVER_PAGE0, MPI3_POINTER PTR_MPI3_DRIVER_PAGE0, Mpi3DriverPage0_t, MPI3_POINTER pMpi3DriverPage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_DRIVER0_PAGEVERSION (0x00) /**** Defines for the BSDOptions field ****/ +#define MPI3_DRIVER0_BSDOPTS_DEVICEEXPOSURE_DISABLE (0x00000020) +#define MPI3_DRIVER0_BSDOPTS_WRITECACHE_DISABLE (0x00000010) #define MPI3_DRIVER0_BSDOPTS_HEADLESS_MODE_ENABLE (0x00000008) #define MPI3_DRIVER0_BSDOPTS_DIS_HII_CONFIG_UTIL (0x00000004) #define MPI3_DRIVER0_BSDOPTS_REGISTRATION_MASK (0x00000003) #define MPI3_DRIVER0_BSDOPTS_REGISTRATION_IOC_AND_DEVS (0x00000000) #define MPI3_DRIVER0_BSDOPTS_REGISTRATION_IOC_ONLY (0x00000001) #define MPI3_DRIVER0_BSDOPTS_REGISTRATION_IOC_AND_INTERNAL_DEVS (0x00000002) /***************************************************************************** * Driver Page 1 * ****************************************************************************/ typedef struct _MPI3_DRIVER_PAGE1 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Flags; /* 0x08 */ U32 Reserved0C; /* 0x0C */ U16 HostDiagTraceMaxSize; /* 0x10 */ U16 HostDiagTraceMinSize; /* 0x12 */ U16 HostDiagTraceDecrementSize; /* 0x14 */ U16 Reserved16; /* 0x16 */ U16 HostDiagFwMaxSize; /* 0x18 */ U16 HostDiagFwMinSize; /* 0x1A */ U16 HostDiagFwDecrementSize; /* 0x1C */ U16 Reserved1E; /* 0x1E */ U16 HostDiagDriverMaxSize; /* 0x20 */ U16 HostDiagDriverMinSize; /* 0x22 */ U16 HostDiagDriverDecrementSize; /* 0x24 */ U16 Reserved26; /* 0x26 */ } MPI3_DRIVER_PAGE1, MPI3_POINTER PTR_MPI3_DRIVER_PAGE1, Mpi3DriverPage1_t, MPI3_POINTER pMpi3DriverPage1_t; /**** Defines for the PageVersion field ****/ #define MPI3_DRIVER1_PAGEVERSION (0x00) /***************************************************************************** * Driver Page 2 * ****************************************************************************/ #ifndef MPI3_DRIVER2_TRIGGER_MAX #define MPI3_DRIVER2_TRIGGER_MAX (1) #endif /* MPI3_DRIVER2_TRIGGER_MAX */ typedef struct _MPI3_DRIVER2_TRIGGER_EVENT { U8 Type; /* 0x00 */ U8 Flags; /* 0x01 */ U8 Reserved02; /* 0x02 */ U8 Event; /* 0x03 */ U32 Reserved04[3]; /* 0x04 */ } MPI3_DRIVER2_TRIGGER_EVENT, MPI3_POINTER PTR_MPI3_DRIVER2_TRIGGER_EVENT, Mpi3Driver2TriggerEvent_t, MPI3_POINTER pMpi3Driver2TriggerEvent_t; typedef struct _MPI3_DRIVER2_TRIGGER_SCSI_SENSE { U8 Type; /* 0x00 */ U8 Flags; /* 0x01 */ U16 Reserved02; /* 0x02 */ U8 ASCQ; /* 0x04 */ U8 ASC; /* 0x05 */ U8 SenseKey; /* 0x06 */ U8 Reserved07; /* 0x07 */ U32 Reserved08[2]; /* 0x08 */ } MPI3_DRIVER2_TRIGGER_SCSI_SENSE, MPI3_POINTER PTR_MPI3_DRIVER2_TRIGGER_SCSI_SENSE, Mpi3Driver2TriggerScsiSense_t, MPI3_POINTER pMpi3Driver2TriggerScsiSense_t; /**** Defines for the ASCQ field ****/ #define MPI3_DRIVER2_TRIGGER_SCSI_SENSE_ASCQ_MATCH_ALL (0xFF) /**** Defines for the ASC field ****/ #define MPI3_DRIVER2_TRIGGER_SCSI_SENSE_ASC_MATCH_ALL (0xFF) /**** Defines for the SenseKey field ****/ #define MPI3_DRIVER2_TRIGGER_SCSI_SENSE_SENSE_KEY_MATCH_ALL (0xFF) typedef struct _MPI3_DRIVER2_TRIGGER_REPLY { U8 Type; /* 0x00 */ U8 Flags; /* 0x01 */ U16 IOCStatus; /* 0x02 */ U32 IOCLogInfo; /* 0x04 */ U32 IOCLogInfoMask; /* 0x08 */ U32 Reserved0C; /* 0x0C */ } MPI3_DRIVER2_TRIGGER_REPLY, MPI3_POINTER PTR_MPI3_DRIVER2_TRIGGER_REPLY, Mpi3Driver2TriggerReply_t, MPI3_POINTER pMpi3Driver2TriggerReply_t; /**** Defines for the IOCStatus field ****/ #define MPI3_DRIVER2_TRIGGER_REPLY_IOCSTATUS_MATCH_ALL (0xFFFF) typedef union _MPI3_DRIVER2_TRIGGER_ELEMENT { MPI3_DRIVER2_TRIGGER_EVENT Event; MPI3_DRIVER2_TRIGGER_SCSI_SENSE ScsiSense; MPI3_DRIVER2_TRIGGER_REPLY Reply; } MPI3_DRIVER2_TRIGGER_ELEMENT, MPI3_POINTER PTR_MPI3_DRIVER2_TRIGGER_ELEMENT, Mpi3Driver2TriggerElement_t, MPI3_POINTER pMpi3Driver2TriggerElement_t; /**** Defines for the Type field ****/ #define MPI3_DRIVER2_TRIGGER_TYPE_EVENT (0x00) #define MPI3_DRIVER2_TRIGGER_TYPE_SCSI_SENSE (0x01) #define MPI3_DRIVER2_TRIGGER_TYPE_REPLY (0x02) /**** Defines for the Flags field ****/ #define MPI3_DRIVER2_TRIGGER_FLAGS_DIAG_TRACE_RELEASE (0x02) #define MPI3_DRIVER2_TRIGGER_FLAGS_DIAG_FW_RELEASE (0x01) typedef struct _MPI3_DRIVER_PAGE2 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U64 GlobalTrigger; /* 0x08 */ U32 Reserved10[3]; /* 0x10 */ U8 NumTriggers; /* 0x1C */ U8 Reserved1D[3]; /* 0x1D */ MPI3_DRIVER2_TRIGGER_ELEMENT Trigger[MPI3_DRIVER2_TRIGGER_MAX]; /* 0x20 */ /* variable length */ } MPI3_DRIVER_PAGE2, MPI3_POINTER PTR_MPI3_DRIVER_PAGE2, Mpi3DriverPage2_t, MPI3_POINTER pMpi3DriverPage2_t; /**** Defines for the PageVersion field ****/ #define MPI3_DRIVER2_PAGEVERSION (0x00) /**** Defines for the GlobalTrigger field ****/ #define MPI3_DRIVER2_GLOBALTRIGGER_DIAG_TRACE_RELEASE (0x8000000000000000ULL) #define MPI3_DRIVER2_GLOBALTRIGGER_DIAG_FW_RELEASE (0x4000000000000000ULL) #define MPI3_DRIVER2_GLOBALTRIGGER_SNAPDUMP_ENABLED (0x2000000000000000ULL) #define MPI3_DRIVER2_GLOBALTRIGGER_POST_DIAG_TRACE_DISABLED (0x1000000000000000ULL) #define MPI3_DRIVER2_GLOBALTRIGGER_POST_DIAG_FW_DISABLED (0x0800000000000000ULL) #define MPI3_DRIVER2_GLOBALTRIGGER_DEVICE_REMOVAL_ENABLED (0x0000000000000004ULL) #define MPI3_DRIVER2_GLOBALTRIGGER_TASK_MANAGEMENT_ENABLED (0x0000000000000002ULL) /***************************************************************************** * Driver Page 10 * ****************************************************************************/ typedef struct _MPI3_DRIVER_PAGE10 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U16 Flags; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U8 NumAllowedCommands; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_ALLOWED_CMD AllowedCommand[MPI3_ALLOWED_CMDS_MAX]; /* 0x10 */ /* variable length */ } MPI3_DRIVER_PAGE10, MPI3_POINTER PTR_MPI3_DRIVER_PAGE10, Mpi3DriverPage10_t, MPI3_POINTER pMpi3DriverPage10_t; /**** Defines for the PageVersion field ****/ #define MPI3_DRIVER10_PAGEVERSION (0x00) /**** Defines for the Flags field - use MPI3_DRIVER_FLAGS_ defines ****/ /***************************************************************************** * Driver Page 20 * ****************************************************************************/ typedef struct _MPI3_DRIVER_PAGE20 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U16 Flags; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U8 NumAllowedCommands; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_ALLOWED_CMD AllowedCommand[MPI3_ALLOWED_CMDS_MAX]; /* 0x10 */ /* variable length */ } MPI3_DRIVER_PAGE20, MPI3_POINTER PTR_MPI3_DRIVER_PAGE20, Mpi3DriverPage20_t, MPI3_POINTER pMpi3DriverPage20_t; /**** Defines for the PageVersion field ****/ #define MPI3_DRIVER20_PAGEVERSION (0x00) /**** Defines for the Flags field - use MPI3_DRIVER_FLAGS_ defines ****/ /***************************************************************************** * Driver Page 30 * ****************************************************************************/ typedef struct _MPI3_DRIVER_PAGE30 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U16 Flags; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U8 NumAllowedCommands; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_ALLOWED_CMD AllowedCommand[MPI3_ALLOWED_CMDS_MAX]; /* 0x10 */ /* variable length */ } MPI3_DRIVER_PAGE30, MPI3_POINTER PTR_MPI3_DRIVER_PAGE30, Mpi3DriverPage30_t, MPI3_POINTER pMpi3DriverPage30_t; /**** Defines for the PageVersion field ****/ #define MPI3_DRIVER30_PAGEVERSION (0x00) /**** Defines for the Flags field - use MPI3_DRIVER_FLAGS_ defines ****/ /***************************************************************************** * Security Configuration Pages * ****************************************************************************/ typedef union _MPI3_SECURITY_MAC { U32 Dword[16]; U16 Word[32]; U8 Byte[64]; } MPI3_SECURITY_MAC, MPI3_POINTER PTR_MPI3_SECURITY_MAC, Mpi3SecurityMAC_t, MPI3_POINTER pMpi3SecurityMAC_t; typedef union _MPI3_SECURITY_NONCE { U32 Dword[16]; U16 Word[32]; U8 Byte[64]; } MPI3_SECURITY_NONCE, MPI3_POINTER PTR_MPI3_SECURITY_NONCE, Mpi3SecurityNonce_t, MPI3_POINTER pMpi3SecurityNonce_t; -typedef union _MPI3_SECURITY_ROOT_DIGEST -{ - U32 Dword[16]; - U16 Word[32]; - U8 Byte[64]; -} MPI3_SECURITY_ROOT_DIGEST, MPI3_POINTER PTR_MPI3_SECURITY_ROOT_DIGEST, - Mpi3SecurityRootDigest_t, MPI3_POINTER pMpi3SecurityRootDigest_t; - /***************************************************************************** * Security Page 0 * ****************************************************************************/ typedef union _MPI3_SECURITY0_CERT_CHAIN { U32 Dword[1024]; U16 Word[2048]; U8 Byte[4096]; } MPI3_SECURITY0_CERT_CHAIN, MPI3_POINTER PTR_MPI3_SECURITY0_CERT_CHAIN, Mpi3Security0CertChain_t, MPI3_POINTER pMpi3Security0CertChain_t; typedef struct _MPI3_SECURITY_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 SlotNumGroup; /* 0x08 */ U8 SlotNum; /* 0x09 */ U16 CertChainLength; /* 0x0A */ U8 CertChainFlags; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ U32 BaseAsymAlgo; /* 0x10 */ U32 BaseHashAlgo; /* 0x14 */ U32 Reserved18[4]; /* 0x18 */ MPI3_SECURITY_MAC Mac; /* 0x28 */ MPI3_SECURITY_NONCE Nonce; /* 0x68 */ MPI3_SECURITY0_CERT_CHAIN CertificateChain; /* 0xA8 */ } MPI3_SECURITY_PAGE0, MPI3_POINTER PTR_MPI3_SECURITY_PAGE0, Mpi3SecurityPage0_t, MPI3_POINTER pMpi3SecurityPage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_SECURITY0_PAGEVERSION (0x00) /**** Defines for the CertChainFlags field ****/ #define MPI3_SECURITY0_CERTCHAIN_FLAGS_AUTH_API_MASK (0x0E) #define MPI3_SECURITY0_CERTCHAIN_FLAGS_AUTH_API_UNUSED (0x00) #define MPI3_SECURITY0_CERTCHAIN_FLAGS_AUTH_API_CERBERUS (0x02) #define MPI3_SECURITY0_CERTCHAIN_FLAGS_AUTH_API_SPDM (0x04) #define MPI3_SECURITY0_CERTCHAIN_FLAGS_SEALED (0x01) /***************************************************************************** * Security Page 1 * ****************************************************************************/ #ifndef MPI3_SECURITY1_KEY_RECORD_MAX #define MPI3_SECURITY1_KEY_RECORD_MAX 1 #endif /* MPI3_SECURITY1_KEY_RECORD_MAX */ #ifndef MPI3_SECURITY1_PAD_MAX #define MPI3_SECURITY1_PAD_MAX 4 #endif /* MPI3_SECURITY1_PAD_MAX */ typedef union _MPI3_SECURITY1_KEY_DATA { U32 Dword[128]; U16 Word[256]; U8 Byte[512]; } MPI3_SECURITY1_KEY_DATA, MPI3_POINTER PTR_MPI3_SECURITY1_KEY_DATA, Mpi3Security1KeyData_t, MPI3_POINTER pMpi3Security1KeyData_t; typedef struct _MPI3_SECURITY1_KEY_RECORD { U8 Flags; /* 0x00 */ U8 Consumer; /* 0x01 */ U16 KeyDataSize; /* 0x02 */ U32 AdditionalKeyData; /* 0x04 */ U32 Reserved08[2]; /* 0x08 */ MPI3_SECURITY1_KEY_DATA KeyData; /* 0x10 */ } MPI3_SECURITY1_KEY_RECORD, MPI3_POINTER PTR_MPI3_SECURITY1_KEY_RECORD, Mpi3Security1KeyRecord_t, MPI3_POINTER pMpi3Security1KeyRecord_t; /**** Defines for the Flags field ****/ #define MPI3_SECURITY1_KEY_RECORD_FLAGS_TYPE_MASK (0x1F) #define MPI3_SECURITY1_KEY_RECORD_FLAGS_TYPE_NOT_VALID (0x00) #define MPI3_SECURITY1_KEY_RECORD_FLAGS_TYPE_HMAC (0x01) #define MPI3_SECURITY1_KEY_RECORD_FLAGS_TYPE_AES (0x02) #define MPI3_SECURITY1_KEY_RECORD_FLAGS_TYPE_ECDSA_PRIVATE (0x03) #define MPI3_SECURITY1_KEY_RECORD_FLAGS_TYPE_ECDSA_PUBLIC (0x04) /**** Defines for the Consumer field ****/ #define MPI3_SECURITY1_KEY_RECORD_CONSUMER_NOT_VALID (0x00) #define MPI3_SECURITY1_KEY_RECORD_CONSUMER_SAFESTORE (0x01) #define MPI3_SECURITY1_KEY_RECORD_CONSUMER_CERT_CHAIN (0x02) #define MPI3_SECURITY1_KEY_RECORD_CONSUMER_DEVICE_KEY (0x03) #define MPI3_SECURITY1_KEY_RECORD_CONSUMER_CACHE_OFFLOAD (0x04) typedef struct _MPI3_SECURITY_PAGE1 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08[2]; /* 0x08 */ MPI3_SECURITY_MAC Mac; /* 0x10 */ MPI3_SECURITY_NONCE Nonce; /* 0x50 */ U8 NumKeys; /* 0x90 */ U8 Reserved91[3]; /* 0x91 */ U32 Reserved94[3]; /* 0x94 */ MPI3_SECURITY1_KEY_RECORD KeyRecord[MPI3_SECURITY1_KEY_RECORD_MAX]; /* 0xA0 */ U8 Pad[MPI3_SECURITY1_PAD_MAX]; /* ?? */ } MPI3_SECURITY_PAGE1, MPI3_POINTER PTR_MPI3_SECURITY_PAGE1, Mpi3SecurityPage1_t, MPI3_POINTER pMpi3SecurityPage1_t; /**** Defines for the PageVersion field ****/ #define MPI3_SECURITY1_PAGEVERSION (0x00) /***************************************************************************** * Security Page 2 * ****************************************************************************/ #ifndef MPI3_SECURITY2_TRUSTED_ROOT_MAX #define MPI3_SECURITY2_TRUSTED_ROOT_MAX 1 #endif /* MPI3_SECURITY2_TRUSTED_ROOT_MAX */ +#ifndef MPI3_SECURITY2_ROOT_LEN +#define MPI3_SECURITY2_ROOT_LEN 4 +#endif /* MPI3_SECURITY2_ROOT_LEN */ + typedef struct _MPI3_SECURITY2_TRUSTED_ROOT { U8 Level; /* 0x00 */ U8 HashAlgorithm; /* 0x01 */ U16 TrustedRootFlags; /* 0x02 */ U32 Reserved04[3]; /* 0x04 */ - MPI3_SECURITY_ROOT_DIGEST RootDigest; /* 0x10 */ + U8 Root[MPI3_SECURITY2_ROOT_LEN]; /* 0x10 */ /* variable length */ } MPI3_SECURITY2_TRUSTED_ROOT, MPI3_POINTER PTR_MPI3_SECURITY2_TRUSTED_ROOT, Mpi3Security2TrustedRoot_t, MPI3_POINTER pMpi3Security2TrustedRoot_t; /**** Defines for the TrustedRootFlags field ****/ +#define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_ROOTFORM_MASK (0xF000) +#define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_ROOTFORM_SHIFT (12) +#define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_ROOTFORM_DIGEST (0x0000) +#define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_ROOTFORM_DERCERT (0x1000) #define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_HASHALGOSOURCE_MASK (0x0006) #define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_HASHALGOSOURCE_SHIFT (1) #define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_HASHALGOSOURCE_HA_FIELD (0x0000) #define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_HASHALGOSOURCE_AKI (0x0002) #define MPI3_SECURITY2_TRUSTEDROOT_TRUSTEDROOTFLAGS_USERPROVISIONED_YES (0x0001) typedef struct _MPI3_SECURITY_PAGE2 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08[2]; /* 0x08 */ MPI3_SECURITY_MAC Mac; /* 0x10 */ MPI3_SECURITY_NONCE Nonce; /* 0x50 */ U32 Reserved90[3]; /* 0x90 */ U8 NumRoots; /* 0x9C */ - U8 Reserved9D[3]; /* 0x9D */ + U8 Reserved9D; /* 0x9D */ + U16 RootElementSize; /* 0x9E */ MPI3_SECURITY2_TRUSTED_ROOT TrustedRoot[MPI3_SECURITY2_TRUSTED_ROOT_MAX]; /* 0xA0 */ /* variable length */ } MPI3_SECURITY_PAGE2, MPI3_POINTER PTR_MPI3_SECURITY_PAGE2, Mpi3SecurityPage2_t, MPI3_POINTER pMpi3SecurityPage2_t; /**** Defines for the PageVersion field ****/ #define MPI3_SECURITY2_PAGEVERSION (0x00) /***************************************************************************** * SAS IO Unit Configuration Pages * ****************************************************************************/ /***************************************************************************** * SAS IO Unit Page 0 * ****************************************************************************/ typedef struct _MPI3_SAS_IO_UNIT0_PHY_DATA { U8 IOUnitPort; /* 0x00 */ U8 PortFlags; /* 0x01 */ U8 PhyFlags; /* 0x02 */ U8 NegotiatedLinkRate; /* 0x03 */ U16 ControllerPhyDeviceInfo; /* 0x04 */ U16 Reserved06; /* 0x06 */ U16 AttachedDevHandle; /* 0x08 */ U16 ControllerDevHandle; /* 0x0A */ U32 DiscoveryStatus; /* 0x0C */ U32 Reserved10; /* 0x10 */ } MPI3_SAS_IO_UNIT0_PHY_DATA, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT0_PHY_DATA, Mpi3SasIOUnit0PhyData_t, MPI3_POINTER pMpi3SasIOUnit0PhyData_t; #ifndef MPI3_SAS_IO_UNIT0_PHY_MAX #define MPI3_SAS_IO_UNIT0_PHY_MAX (1) #endif /* MPI3_SAS_IO_UNIT0_PHY_MAX */ typedef struct _MPI3_SAS_IO_UNIT_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumPhys; /* 0x0C */ U8 InitStatus; /* 0x0D */ U16 Reserved0E; /* 0x0E */ MPI3_SAS_IO_UNIT0_PHY_DATA PhyData[MPI3_SAS_IO_UNIT0_PHY_MAX]; /* 0x10 */ } MPI3_SAS_IO_UNIT_PAGE0, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT_PAGE0, Mpi3SasIOUnitPage0_t, MPI3_POINTER pMpi3SasIOUnitPage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASIOUNIT0_PAGEVERSION (0x00) /**** Defines for the InitStatus field ****/ #define MPI3_SASIOUNIT0_INITSTATUS_NO_ERRORS (0x00) #define MPI3_SASIOUNIT0_INITSTATUS_NEEDS_INITIALIZATION (0x01) #define MPI3_SASIOUNIT0_INITSTATUS_NO_TARGETS_ALLOCATED (0x02) #define MPI3_SASIOUNIT0_INITSTATUS_BAD_NUM_PHYS (0x04) #define MPI3_SASIOUNIT0_INITSTATUS_UNSUPPORTED_CONFIG (0x05) #define MPI3_SASIOUNIT0_INITSTATUS_HOST_PHYS_ENABLED (0x06) #define MPI3_SASIOUNIT0_INITSTATUS_PRODUCT_SPECIFIC_MIN (0xF0) #define MPI3_SASIOUNIT0_INITSTATUS_PRODUCT_SPECIFIC_MAX (0xFF) /**** Defines for the PortFlags field ****/ #define MPI3_SASIOUNIT0_PORTFLAGS_DISC_IN_PROGRESS (0x08) #define MPI3_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG_MASK (0x03) #define MPI3_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG_IOUNIT1 (0x00) #define MPI3_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG_DYNAMIC (0x01) #define MPI3_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG_BACKPLANE (0x02) /**** Defines for the PhyFlags field ****/ #define MPI3_SASIOUNIT0_PHYFLAGS_INIT_PERSIST_CONNECT (0x40) #define MPI3_SASIOUNIT0_PHYFLAGS_TARG_PERSIST_CONNECT (0x20) #define MPI3_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08) #define MPI3_SASIOUNIT0_PHYFLAGS_VIRTUAL_PHY (0x02) #define MPI3_SASIOUNIT0_PHYFLAGS_HOST_PHY (0x01) /**** Use MPI3_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field ****/ /**** Use MPI3_SAS_DEVICE_INFO_ defines (see mpi30_sas.h) for the ControllerPhyDeviceInfo field ****/ /**** Use MPI3_SAS_DISC_STATUS_ defines (see mpi30_ioc.h) for the DiscoveryStatus field ****/ /***************************************************************************** * SAS IO Unit Page 1 * ****************************************************************************/ typedef struct _MPI3_SAS_IO_UNIT1_PHY_DATA { U8 IOUnitPort; /* 0x00 */ U8 PortFlags; /* 0x01 */ U8 PhyFlags; /* 0x02 */ U8 MaxMinLinkRate; /* 0x03 */ U16 ControllerPhyDeviceInfo; /* 0x04 */ U16 MaxTargetPortConnectTime; /* 0x06 */ U32 Reserved08; /* 0x08 */ } MPI3_SAS_IO_UNIT1_PHY_DATA, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT1_PHY_DATA, Mpi3SasIOUnit1PhyData_t, MPI3_POINTER pMpi3SasIOUnit1PhyData_t; #ifndef MPI3_SAS_IO_UNIT1_PHY_MAX #define MPI3_SAS_IO_UNIT1_PHY_MAX (1) #endif /* MPI3_SAS_IO_UNIT1_PHY_MAX */ typedef struct _MPI3_SAS_IO_UNIT_PAGE1 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U16 ControlFlags; /* 0x08 */ U16 SASNarrowMaxQueueDepth; /* 0x0A */ U16 AdditionalControlFlags; /* 0x0C */ U16 SASWideMaxQueueDepth; /* 0x0E */ U8 NumPhys; /* 0x10 */ U8 SATAMaxQDepth; /* 0x11 */ U16 Reserved12; /* 0x12 */ MPI3_SAS_IO_UNIT1_PHY_DATA PhyData[MPI3_SAS_IO_UNIT1_PHY_MAX]; /* 0x14 */ } MPI3_SAS_IO_UNIT_PAGE1, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT_PAGE1, Mpi3SasIOUnitPage1_t, MPI3_POINTER pMpi3SasIOUnitPage1_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASIOUNIT1_PAGEVERSION (0x00) /**** Defines for the ControlFlags field ****/ #define MPI3_SASIOUNIT1_CONTROL_CONTROLLER_DEVICE_SELF_TEST (0x8000) #define MPI3_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) #define MPI3_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) #define MPI3_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) #define MPI3_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) #define MPI3_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) #define MPI3_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL (0x0008) #define MPI3_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) #define MPI3_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) #define MPI3_SASIOUNIT1_CONTROL_HARD_RESET_MASK (0x0001) #define MPI3_SASIOUNIT1_CONTROL_HARD_RESET_DEVICE_NAME (0x0000) #define MPI3_SASIOUNIT1_CONTROL_HARD_RESET_SAS_ADDRESS (0x0001) /**** Defines for the AdditionalControlFlags field ****/ #define MPI3_SASIOUNIT1_ACONTROL_DA_PERSIST_CONNECT (0x0100) #define MPI3_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080) #define MPI3_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040) #define MPI3_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020) #define MPI3_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010) #define MPI3_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008) #define MPI3_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004) #define MPI3_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002) #define MPI3_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001) /**** Defines for the PortFlags field ****/ #define MPI3_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) /**** Defines for the PhyFlags field ****/ #define MPI3_SASIOUNIT1_PHYFLAGS_INIT_PERSIST_CONNECT (0x40) #define MPI3_SASIOUNIT1_PHYFLAGS_TARG_PERSIST_CONNECT (0x20) #define MPI3_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08) /**** Defines for the MaxMinLinkRate field ****/ #define MPI3_SASIOUNIT1_MMLR_MAX_RATE_MASK (0xF0) #define MPI3_SASIOUNIT1_MMLR_MAX_RATE_SHIFT (4) #define MPI3_SASIOUNIT1_MMLR_MAX_RATE_6_0 (0xA0) #define MPI3_SASIOUNIT1_MMLR_MAX_RATE_12_0 (0xB0) #define MPI3_SASIOUNIT1_MMLR_MAX_RATE_22_5 (0xC0) #define MPI3_SASIOUNIT1_MMLR_MIN_RATE_MASK (0x0F) #define MPI3_SASIOUNIT1_MMLR_MIN_RATE_6_0 (0x0A) #define MPI3_SASIOUNIT1_MMLR_MIN_RATE_12_0 (0x0B) #define MPI3_SASIOUNIT1_MMLR_MIN_RATE_22_5 (0x0C) /**** Use MPI3_SAS_DEVICE_INFO_ defines (see mpi30_sas.h) for the ControllerPhyDeviceInfo field ****/ /***************************************************************************** * SAS IO Unit Page 2 * ****************************************************************************/ typedef struct _MPI3_SAS_IO_UNIT2_PHY_PM_SETTINGS { U8 ControlFlags; /* 0x00 */ U8 Reserved01; /* 0x01 */ U16 InactivityTimerExponent; /* 0x02 */ U8 SATAPartialTimeout; /* 0x04 */ U8 Reserved05; /* 0x05 */ U8 SATASlumberTimeout; /* 0x06 */ U8 Reserved07; /* 0x07 */ U8 SASPartialTimeout; /* 0x08 */ U8 Reserved09; /* 0x09 */ U8 SASSlumberTimeout; /* 0x0A */ U8 Reserved0B; /* 0x0B */ } MPI3_SAS_IO_UNIT2_PHY_PM_SETTINGS, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT2_PHY_PM_SETTINGS, Mpi3SasIOUnit2PhyPmSettings_t, MPI3_POINTER pMpi3SasIOUnit2PhyPmSettings_t; #ifndef MPI3_SAS_IO_UNIT2_PHY_MAX #define MPI3_SAS_IO_UNIT2_PHY_MAX (1) #endif /* MPI3_SAS_IO_UNIT2_PHY_MAX */ typedef struct _MPI3_SAS_IO_UNIT_PAGE2 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 NumPhys; /* 0x08 */ U8 Reserved09[3]; /* 0x09 */ U32 Reserved0C; /* 0x0C */ MPI3_SAS_IO_UNIT2_PHY_PM_SETTINGS SASPhyPowerManagementSettings[MPI3_SAS_IO_UNIT2_PHY_MAX]; /* 0x10 */ } MPI3_SAS_IO_UNIT_PAGE2, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT_PAGE2, Mpi3SasIOUnitPage2_t, MPI3_POINTER pMpi3SasIOUnitPage2_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASIOUNIT2_PAGEVERSION (0x00) /**** Defines for the ControlFlags field ****/ #define MPI3_SASIOUNIT2_CONTROL_SAS_SLUMBER_ENABLE (0x08) #define MPI3_SASIOUNIT2_CONTROL_SAS_PARTIAL_ENABLE (0x04) #define MPI3_SASIOUNIT2_CONTROL_SATA_SLUMBER_ENABLE (0x02) #define MPI3_SASIOUNIT2_CONTROL_SATA_PARTIAL_ENABLE (0x01) /**** Defines for the InactivityTimerExponent field ****/ #define MPI3_SASIOUNIT2_ITE_SAS_SLUMBER_MASK (0x7000) #define MPI3_SASIOUNIT2_ITE_SAS_SLUMBER_SHIFT (12) #define MPI3_SASIOUNIT2_ITE_SAS_PARTIAL_MASK (0x0700) #define MPI3_SASIOUNIT2_ITE_SAS_PARTIAL_SHIFT (8) #define MPI3_SASIOUNIT2_ITE_SATA_SLUMBER_MASK (0x0070) #define MPI3_SASIOUNIT2_ITE_SATA_SLUMBER_SHIFT (4) #define MPI3_SASIOUNIT2_ITE_SATA_PARTIAL_MASK (0x0007) #define MPI3_SASIOUNIT2_ITE_SATA_PARTIAL_SHIFT (0) #define MPI3_SASIOUNIT2_ITE_EXP_TEN_SECONDS (7) #define MPI3_SASIOUNIT2_ITE_EXP_ONE_SECOND (6) #define MPI3_SASIOUNIT2_ITE_EXP_HUNDRED_MILLISECONDS (5) #define MPI3_SASIOUNIT2_ITE_EXP_TEN_MILLISECONDS (4) #define MPI3_SASIOUNIT2_ITE_EXP_ONE_MILLISECOND (3) #define MPI3_SASIOUNIT2_ITE_EXP_HUNDRED_MICROSECONDS (2) #define MPI3_SASIOUNIT2_ITE_EXP_TEN_MICROSECONDS (1) #define MPI3_SASIOUNIT2_ITE_EXP_ONE_MICROSECOND (0) /***************************************************************************** * SAS IO Unit Page 3 * ****************************************************************************/ typedef struct _MPI3_SAS_IO_UNIT_PAGE3 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U32 PowerManagementCapabilities; /* 0x0C */ } MPI3_SAS_IO_UNIT_PAGE3, MPI3_POINTER PTR_MPI3_SAS_IO_UNIT_PAGE3, Mpi3SasIOUnitPage3_t, MPI3_POINTER pMpi3SasIOUnitPage3_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASIOUNIT3_PAGEVERSION (0x00) /**** Defines for the PowerManagementCapabilities field ****/ #define MPI3_SASIOUNIT3_PM_HOST_SAS_SLUMBER_MODE (0x00000800) #define MPI3_SASIOUNIT3_PM_HOST_SAS_PARTIAL_MODE (0x00000400) #define MPI3_SASIOUNIT3_PM_HOST_SATA_SLUMBER_MODE (0x00000200) #define MPI3_SASIOUNIT3_PM_HOST_SATA_PARTIAL_MODE (0x00000100) #define MPI3_SASIOUNIT3_PM_IOUNIT_SAS_SLUMBER_MODE (0x00000008) #define MPI3_SASIOUNIT3_PM_IOUNIT_SAS_PARTIAL_MODE (0x00000004) #define MPI3_SASIOUNIT3_PM_IOUNIT_SATA_SLUMBER_MODE (0x00000002) #define MPI3_SASIOUNIT3_PM_IOUNIT_SATA_PARTIAL_MODE (0x00000001) /***************************************************************************** * SAS Expander Configuration Pages * ****************************************************************************/ /***************************************************************************** * SAS Expander Page 0 * ****************************************************************************/ typedef struct _MPI3_SAS_EXPANDER_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 IOUnitPort; /* 0x08 */ U8 ReportGenLength; /* 0x09 */ U16 EnclosureHandle; /* 0x0A */ U32 Reserved0C; /* 0x0C */ U64 SASAddress; /* 0x10 */ U32 DiscoveryStatus; /* 0x18 */ U16 DevHandle; /* 0x1C */ U16 ParentDevHandle; /* 0x1E */ U16 ExpanderChangeCount; /* 0x20 */ U16 ExpanderRouteIndexes; /* 0x22 */ U8 NumPhys; /* 0x24 */ U8 SASLevel; /* 0x25 */ U16 Flags; /* 0x26 */ U16 STPBusInactivityTimeLimit; /* 0x28 */ U16 STPMaxConnectTimeLimit; /* 0x2A */ U16 STP_SMP_NexusLossTime; /* 0x2C */ U16 MaxNumRoutedSASAddresses; /* 0x2E */ U64 ActiveZoneManagerSASAddress; /* 0x30 */ U16 ZoneLockInactivityLimit; /* 0x38 */ U16 Reserved3A; /* 0x3A */ U8 TimeToReducedFunc; /* 0x3C */ U8 InitialTimeToReducedFunc; /* 0x3D */ U8 MaxReducedFuncTime; /* 0x3E */ U8 ExpStatus; /* 0x3F */ } MPI3_SAS_EXPANDER_PAGE0, MPI3_POINTER PTR_MPI3_SAS_EXPANDER_PAGE0, Mpi3SasExpanderPage0_t, MPI3_POINTER pMpi3SasExpanderPage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASEXPANDER0_PAGEVERSION (0x00) /**** Use MPI3_SAS_DISC_STATUS_ defines (see mpi30_ioc.h) for the DiscoveryStatus field ****/ /**** Defines for the Flags field ****/ #define MPI3_SASEXPANDER0_FLAGS_REDUCED_FUNCTIONALITY (0x2000) #define MPI3_SASEXPANDER0_FLAGS_ZONE_LOCKED (0x1000) #define MPI3_SASEXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800) #define MPI3_SASEXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400) #define MPI3_SASEXPANDER0_FLAGS_ZONING_SUPPORT (0x0200) #define MPI3_SASEXPANDER0_FLAGS_ENABLED_ZONING (0x0100) #define MPI3_SASEXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT (0x0080) #define MPI3_SASEXPANDER0_FLAGS_CONNECTOR_END_DEVICE (0x0010) #define MPI3_SASEXPANDER0_FLAGS_OTHERS_CONFIG (0x0004) #define MPI3_SASEXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x0002) #define MPI3_SASEXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x0001) /**** Defines for the ExpStatus field ****/ #define MPI3_SASEXPANDER0_ES_NOT_RESPONDING (0x02) #define MPI3_SASEXPANDER0_ES_RESPONDING (0x03) #define MPI3_SASEXPANDER0_ES_DELAY_NOT_RESPONDING (0x04) /***************************************************************************** * SAS Expander Page 1 * ****************************************************************************/ typedef struct _MPI3_SAS_EXPANDER_PAGE1 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 IOUnitPort; /* 0x08 */ U8 Reserved09[3]; /* 0x09 */ U8 NumPhys; /* 0x0C */ U8 Phy; /* 0x0D */ U16 NumTableEntriesProgrammed; /* 0x0E */ U8 ProgrammedLinkRate; /* 0x10 */ U8 HwLinkRate; /* 0x11 */ U16 AttachedDevHandle; /* 0x12 */ U32 PhyInfo; /* 0x14 */ U16 AttachedDeviceInfo; /* 0x18 */ U16 Reserved1A; /* 0x1A */ U16 ExpanderDevHandle; /* 0x1C */ U8 ChangeCount; /* 0x1E */ U8 NegotiatedLinkRate; /* 0x1F */ U8 PhyIdentifier; /* 0x20 */ U8 AttachedPhyIdentifier; /* 0x21 */ U8 Reserved22; /* 0x22 */ U8 DiscoveryInfo; /* 0x23 */ U32 AttachedPhyInfo; /* 0x24 */ U8 ZoneGroup; /* 0x28 */ U8 SelfConfigStatus; /* 0x29 */ U16 Reserved2A; /* 0x2A */ U16 Slot; /* 0x2C */ U16 SlotIndex; /* 0x2E */ } MPI3_SAS_EXPANDER_PAGE1, MPI3_POINTER PTR_MPI3_SAS_EXPANDER_PAGE1, Mpi3SasExpanderPage1_t, MPI3_POINTER pMpi3SasExpanderPage1_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASEXPANDER1_PAGEVERSION (0x00) /**** Defines for the ProgrammedLinkRate field - use MPI3_SAS_PRATE_ defines ****/ /**** Defines for the HwLinkRate field - use MPI3_SAS_HWRATE_ defines ****/ /**** Defines for the PhyInfo field - use MPI3_SAS_PHYINFO_ defines ****/ /**** Defines for the AttachedDeviceInfo field - use MPI3_SAS_DEVICE_INFO_ defines ****/ /**** Defines for the NegotiatedLinkRate field - use use MPI3_SAS_NEG_LINK_RATE_ defines ****/ /**** Defines for the DiscoveryInfo field ****/ #define MPI3_SASEXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04) #define MPI3_SASEXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02) #define MPI3_SASEXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01) /**** Defines for the AttachedPhyInfo field - use MPI3_SAS_APHYINFO_ defines ****/ /**** Defines for the Slot field - use MPI3_SLOT_ defines ****/ /**** Defines for the SlotIndex field - use MPI3_SLOT_INDEX_ ****/ /***************************************************************************** * SAS Expander Page 2 * ****************************************************************************/ #ifndef MPI3_SASEXPANDER2_MAX_NUM_PHYS #define MPI3_SASEXPANDER2_MAX_NUM_PHYS (1) #endif /* MPI3_SASEXPANDER2_MAX_NUM_PHYS */ typedef struct _MPI3_SASEXPANDER2_PHY_ELEMENT { U8 LinkChangeCount; /* 0x00 */ U8 Reserved01; /* 0x01 */ U16 RateChangeCount; /* 0x02 */ U32 Reserved04; /* 0x04 */ } MPI3_SASEXPANDER2_PHY_ELEMENT, MPI3_POINTER PTR_MPI3_SASEXPANDER2_PHY_ELEMENT, Mpi3SasExpander2PhyElement_t, MPI3_POINTER pMpi3SasExpander2PhyElement_t; typedef struct _MPI3_SAS_EXPANDER_PAGE2 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 NumPhys; /* 0x08 */ U8 Reserved09; /* 0x09 */ U16 DevHandle; /* 0x0A */ U32 Reserved0C; /* 0x0C */ MPI3_SASEXPANDER2_PHY_ELEMENT Phy[MPI3_SASEXPANDER2_MAX_NUM_PHYS]; /* 0x10 */ /* variable length */ } MPI3_SAS_EXPANDER_PAGE2, MPI3_POINTER PTR_MPI3_SAS_EXPANDER_PAGE2, Mpi3SasExpanderPage2_t, MPI3_POINTER pMpi3SasExpanderPage2_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASEXPANDER2_PAGEVERSION (0x00) /***************************************************************************** * SAS Port Configuration Pages * ****************************************************************************/ /***************************************************************************** * SAS Port Page 0 * ****************************************************************************/ typedef struct _MPI3_SAS_PORT_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 PortNumber; /* 0x08 */ U8 Reserved09; /* 0x09 */ U8 PortWidth; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U8 ZoneGroup; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ U64 SASAddress; /* 0x10 */ U16 DeviceInfo; /* 0x18 */ U16 Reserved1A; /* 0x1A */ U32 Reserved1C; /* 0x1C */ } MPI3_SAS_PORT_PAGE0, MPI3_POINTER PTR_MPI3_SAS_PORT_PAGE0, Mpi3SasPortPage0_t, MPI3_POINTER pMpi3SasPortPage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASPORT0_PAGEVERSION (0x00) /**** Defines for the DeviceInfo field - use MPI3_SAS_DEVICE_INFO_ defines ****/ /***************************************************************************** * SAS PHY Configuration Pages * ****************************************************************************/ /***************************************************************************** * SAS PHY Page 0 * ****************************************************************************/ typedef struct _MPI3_SAS_PHY_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U16 OwnerDevHandle; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U16 AttachedDevHandle; /* 0x0C */ U8 AttachedPhyIdentifier; /* 0x0E */ U8 Reserved0F; /* 0x0F */ U32 AttachedPhyInfo; /* 0x10 */ U8 ProgrammedLinkRate; /* 0x14 */ U8 HwLinkRate; /* 0x15 */ U8 ChangeCount; /* 0x16 */ U8 Flags; /* 0x17 */ U32 PhyInfo; /* 0x18 */ U8 NegotiatedLinkRate; /* 0x1C */ U8 Reserved1D[3]; /* 0x1D */ U16 Slot; /* 0x20 */ U16 SlotIndex; /* 0x22 */ } MPI3_SAS_PHY_PAGE0, MPI3_POINTER PTR_MPI3_SAS_PHY_PAGE0, Mpi3SasPhyPage0_t, MPI3_POINTER pMpi3SasPhyPage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASPHY0_PAGEVERSION (0x00) /**** Defines for the AttachedPhyInfo field - use MPI3_SAS_APHYINFO_ defines ****/ /**** Defines for the ProgrammedLinkRate field - use MPI3_SAS_PRATE_ defines ****/ /**** Defines for the HwLinkRate field - use MPI3_SAS_HWRATE_ defines ****/ /**** Defines for the Flags field ****/ #define MPI3_SASPHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01) /**** Defines for the PhyInfo field - use MPI3_SAS_PHYINFO_ defines ****/ /**** Defines for the NegotiatedLinkRate field - use MPI3_SAS_NEG_LINK_RATE_ defines ****/ /**** Defines for the Slot field - use MPI3_SLOT_ defines ****/ /**** Defines for the SlotIndex field - use MPI3_SLOT_INDEX_ ****/ /***************************************************************************** * SAS PHY Page 1 * ****************************************************************************/ typedef struct _MPI3_SAS_PHY_PAGE1 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U32 InvalidDwordCount; /* 0x0C */ U32 RunningDisparityErrorCount; /* 0x10 */ U32 LossDwordSynchCount; /* 0x14 */ U32 PhyResetProblemCount; /* 0x18 */ } MPI3_SAS_PHY_PAGE1, MPI3_POINTER PTR_MPI3_SAS_PHY_PAGE1, Mpi3SasPhyPage1_t, MPI3_POINTER pMpi3SasPhyPage1_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASPHY1_PAGEVERSION (0x00) /***************************************************************************** * SAS PHY Page 2 * ****************************************************************************/ typedef struct _MPI3_SAS_PHY2_PHY_EVENT { U8 PhyEventCode; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ U32 PhyEventInfo; /* 0x04 */ } MPI3_SAS_PHY2_PHY_EVENT, MPI3_POINTER PTR_MPI3_SAS_PHY2_PHY_EVENT, Mpi3SasPhy2PhyEvent_t, MPI3_POINTER pMpi3SasPhy2PhyEvent_t; /**** Defines for the PhyEventCode field - use MPI3_SASPHY3_EVENT_CODE_ defines */ #ifndef MPI3_SAS_PHY2_PHY_EVENT_MAX #define MPI3_SAS_PHY2_PHY_EVENT_MAX (1) #endif /* MPI3_SAS_PHY2_PHY_EVENT_MAX */ typedef struct _MPI3_SAS_PHY_PAGE2 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumPhyEvents; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_SAS_PHY2_PHY_EVENT PhyEvent[MPI3_SAS_PHY2_PHY_EVENT_MAX]; /* 0x10 */ } MPI3_SAS_PHY_PAGE2, MPI3_POINTER PTR_MPI3_SAS_PHY_PAGE2, Mpi3SasPhyPage2_t, MPI3_POINTER pMpi3SasPhyPage2_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASPHY2_PAGEVERSION (0x00) /***************************************************************************** * SAS PHY Page 3 * ****************************************************************************/ typedef struct _MPI3_SAS_PHY3_PHY_EVENT_CONFIG { U8 PhyEventCode; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ U8 CounterType; /* 0x04 */ U8 ThresholdWindow; /* 0x05 */ U8 TimeUnits; /* 0x06 */ U8 Reserved07; /* 0x07 */ U32 EventThreshold; /* 0x08 */ U16 ThresholdFlags; /* 0x0C */ U16 Reserved0E; /* 0x0E */ } MPI3_SAS_PHY3_PHY_EVENT_CONFIG, MPI3_POINTER PTR_MPI3_SAS_PHY3_PHY_EVENT_CONFIG, Mpi3SasPhy3PhyEventConfig_t, MPI3_POINTER pMpi3SasPhy3PhyEventConfig_t; /**** Defines for the PhyEventCode field ****/ #define MPI3_SASPHY3_EVENT_CODE_NO_EVENT (0x00) #define MPI3_SASPHY3_EVENT_CODE_INVALID_DWORD (0x01) #define MPI3_SASPHY3_EVENT_CODE_RUNNING_DISPARITY_ERROR (0x02) #define MPI3_SASPHY3_EVENT_CODE_LOSS_DWORD_SYNC (0x03) #define MPI3_SASPHY3_EVENT_CODE_PHY_RESET_PROBLEM (0x04) #define MPI3_SASPHY3_EVENT_CODE_ELASTICITY_BUF_OVERFLOW (0x05) #define MPI3_SASPHY3_EVENT_CODE_RX_ERROR (0x06) #define MPI3_SASPHY3_EVENT_CODE_INV_SPL_PACKETS (0x07) #define MPI3_SASPHY3_EVENT_CODE_LOSS_SPL_PACKET_SYNC (0x08) #define MPI3_SASPHY3_EVENT_CODE_RX_ADDR_FRAME_ERROR (0x20) #define MPI3_SASPHY3_EVENT_CODE_TX_AC_OPEN_REJECT (0x21) #define MPI3_SASPHY3_EVENT_CODE_RX_AC_OPEN_REJECT (0x22) #define MPI3_SASPHY3_EVENT_CODE_TX_RC_OPEN_REJECT (0x23) #define MPI3_SASPHY3_EVENT_CODE_RX_RC_OPEN_REJECT (0x24) #define MPI3_SASPHY3_EVENT_CODE_RX_AIP_PARTIAL_WAITING_ON (0x25) #define MPI3_SASPHY3_EVENT_CODE_RX_AIP_CONNECT_WAITING_ON (0x26) #define MPI3_SASPHY3_EVENT_CODE_TX_BREAK (0x27) #define MPI3_SASPHY3_EVENT_CODE_RX_BREAK (0x28) #define MPI3_SASPHY3_EVENT_CODE_BREAK_TIMEOUT (0x29) #define MPI3_SASPHY3_EVENT_CODE_CONNECTION (0x2A) #define MPI3_SASPHY3_EVENT_CODE_PEAKTX_PATHWAY_BLOCKED (0x2B) #define MPI3_SASPHY3_EVENT_CODE_PEAKTX_ARB_WAIT_TIME (0x2C) #define MPI3_SASPHY3_EVENT_CODE_PEAK_ARB_WAIT_TIME (0x2D) #define MPI3_SASPHY3_EVENT_CODE_PEAK_CONNECT_TIME (0x2E) #define MPI3_SASPHY3_EVENT_CODE_PERSIST_CONN (0x2F) #define MPI3_SASPHY3_EVENT_CODE_TX_SSP_FRAMES (0x40) #define MPI3_SASPHY3_EVENT_CODE_RX_SSP_FRAMES (0x41) #define MPI3_SASPHY3_EVENT_CODE_TX_SSP_ERROR_FRAMES (0x42) #define MPI3_SASPHY3_EVENT_CODE_RX_SSP_ERROR_FRAMES (0x43) #define MPI3_SASPHY3_EVENT_CODE_TX_CREDIT_BLOCKED (0x44) #define MPI3_SASPHY3_EVENT_CODE_RX_CREDIT_BLOCKED (0x45) #define MPI3_SASPHY3_EVENT_CODE_TX_SATA_FRAMES (0x50) #define MPI3_SASPHY3_EVENT_CODE_RX_SATA_FRAMES (0x51) #define MPI3_SASPHY3_EVENT_CODE_SATA_OVERFLOW (0x52) #define MPI3_SASPHY3_EVENT_CODE_TX_SMP_FRAMES (0x60) #define MPI3_SASPHY3_EVENT_CODE_RX_SMP_FRAMES (0x61) #define MPI3_SASPHY3_EVENT_CODE_RX_SMP_ERROR_FRAMES (0x63) #define MPI3_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT (0xD0) #define MPI3_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE (0xD1) #define MPI3_SASPHY3_EVENT_CODE_RX_AIP (0xD2) #define MPI3_SASPHY3_EVENT_CODE_LCARB_WAIT_TIME (0xD3) #define MPI3_SASPHY3_EVENT_CODE_RCVD_CONN_RESP_WAIT_TIME (0xD4) #define MPI3_SASPHY3_EVENT_CODE_LCCONN_TIME (0xD5) #define MPI3_SASPHY3_EVENT_CODE_SSP_TX_START_TRANSMIT (0xD6) #define MPI3_SASPHY3_EVENT_CODE_SATA_TX_START (0xD7) #define MPI3_SASPHY3_EVENT_CODE_SMP_TX_START_TRANSMT (0xD8) #define MPI3_SASPHY3_EVENT_CODE_TX_SMP_BREAK_CONN (0xD9) #define MPI3_SASPHY3_EVENT_CODE_SSP_RX_START_RECEIVE (0xDA) #define MPI3_SASPHY3_EVENT_CODE_SATA_RX_START_RECEIVE (0xDB) #define MPI3_SASPHY3_EVENT_CODE_SMP_RX_START_RECEIVE (0xDC) /**** Defines for the CounterType field ****/ #define MPI3_SASPHY3_COUNTER_TYPE_WRAPPING (0x00) #define MPI3_SASPHY3_COUNTER_TYPE_SATURATING (0x01) #define MPI3_SASPHY3_COUNTER_TYPE_PEAK_VALUE (0x02) /**** Defines for the TimeUnits field ****/ #define MPI3_SASPHY3_TIME_UNITS_10_MICROSECONDS (0x00) #define MPI3_SASPHY3_TIME_UNITS_100_MICROSECONDS (0x01) #define MPI3_SASPHY3_TIME_UNITS_1_MILLISECOND (0x02) #define MPI3_SASPHY3_TIME_UNITS_10_MILLISECONDS (0x03) /**** Defines for the ThresholdFlags field ****/ #define MPI3_SASPHY3_TFLAGS_PHY_RESET (0x0002) #define MPI3_SASPHY3_TFLAGS_EVENT_NOTIFY (0x0001) #ifndef MPI3_SAS_PHY3_PHY_EVENT_MAX #define MPI3_SAS_PHY3_PHY_EVENT_MAX (1) #endif /* MPI3_SAS_PHY3_PHY_EVENT_MAX */ typedef struct _MPI3_SAS_PHY_PAGE3 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumPhyEvents; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_SAS_PHY3_PHY_EVENT_CONFIG PhyEventConfig[MPI3_SAS_PHY3_PHY_EVENT_MAX]; /* 0x10 */ } MPI3_SAS_PHY_PAGE3, MPI3_POINTER PTR_MPI3_SAS_PHY_PAGE3, Mpi3SasPhyPage3_t, MPI3_POINTER pMpi3SasPhyPage3_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASPHY3_PAGEVERSION (0x00) /***************************************************************************** * SAS PHY Page 4 * ****************************************************************************/ typedef struct _MPI3_SAS_PHY_PAGE4 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 Reserved08[3]; /* 0x08 */ U8 Flags; /* 0x0B */ U8 InitialFrame[28]; /* 0x0C */ } MPI3_SAS_PHY_PAGE4, MPI3_POINTER PTR_MPI3_SAS_PHY_PAGE4, Mpi3SasPhyPage4_t, MPI3_POINTER pMpi3SasPhyPage4_t; /**** Defines for the PageVersion field ****/ #define MPI3_SASPHY4_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_SASPHY4_FLAGS_FRAME_VALID (0x02) #define MPI3_SASPHY4_FLAGS_SATA_FRAME (0x01) /***************************************************************************** * Common definitions used by PCIe Configuration Pages * ****************************************************************************/ -/**** Defines for Negotiated Link Rates ****/ +/**** Defines for NegotiatedLinkRates ****/ #define MPI3_PCIE_LINK_RETIMERS_MASK (0x30) #define MPI3_PCIE_LINK_RETIMERS_SHIFT (4) #define MPI3_PCIE_NEG_LINK_RATE_MASK (0x0F) #define MPI3_PCIE_NEG_LINK_RATE_UNKNOWN (0x00) #define MPI3_PCIE_NEG_LINK_RATE_PHY_DISABLED (0x01) #define MPI3_PCIE_NEG_LINK_RATE_2_5 (0x02) #define MPI3_PCIE_NEG_LINK_RATE_5_0 (0x03) #define MPI3_PCIE_NEG_LINK_RATE_8_0 (0x04) #define MPI3_PCIE_NEG_LINK_RATE_16_0 (0x05) #define MPI3_PCIE_NEG_LINK_RATE_32_0 (0x06) /**** Defines for Enabled ASPM States ****/ #define MPI3_PCIE_ASPM_ENABLE_NONE (0x0) #define MPI3_PCIE_ASPM_ENABLE_L0s (0x1) #define MPI3_PCIE_ASPM_ENABLE_L1 (0x2) #define MPI3_PCIE_ASPM_ENABLE_L0s_L1 (0x3) /**** Defines for Enabled ASPM States ****/ #define MPI3_PCIE_ASPM_SUPPORT_NONE (0x0) #define MPI3_PCIE_ASPM_SUPPORT_L0s (0x1) #define MPI3_PCIE_ASPM_SUPPORT_L1 (0x2) #define MPI3_PCIE_ASPM_SUPPORT_L0s_L1 (0x3) /***************************************************************************** * PCIe IO Unit Configuration Pages * ****************************************************************************/ /***************************************************************************** * PCIe IO Unit Page 0 * ****************************************************************************/ typedef struct _MPI3_PCIE_IO_UNIT0_PHY_DATA { U8 Link; /* 0x00 */ U8 LinkFlags; /* 0x01 */ U8 PhyFlags; /* 0x02 */ U8 NegotiatedLinkRate; /* 0x03 */ U16 AttachedDevHandle; /* 0x04 */ U16 ControllerDevHandle; /* 0x06 */ U32 EnumerationStatus; /* 0x08 */ U8 IOUnitPort; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ } MPI3_PCIE_IO_UNIT0_PHY_DATA, MPI3_POINTER PTR_MPI3_PCIE_IO_UNIT0_PHY_DATA, Mpi3PcieIOUnit0PhyData_t, MPI3_POINTER pMpi3PcieIOUnit0PhyData_t; /**** Defines for the LinkFlags field ****/ #define MPI3_PCIEIOUNIT0_LINKFLAGS_CONFIG_SOURCE_MASK (0x10) #define MPI3_PCIEIOUNIT0_LINKFLAGS_CONFIG_SOURCE_IOUNIT1 (0x00) #define MPI3_PCIEIOUNIT0_LINKFLAGS_CONFIG_SOURCE_BKPLANE (0x10) #define MPI3_PCIEIOUNIT0_LINKFLAGS_ENUM_IN_PROGRESS (0x08) /**** Defines for the PhyFlags field ****/ #define MPI3_PCIEIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08) #define MPI3_PCIEIOUNIT0_PHYFLAGS_HOST_PHY (0x01) /**** Defines for the NegotiatedLinkRate field - use MPI3_PCIE_NEG_LINK_RATE_ defines ****/ /**** Defines for the EnumerationStatus field ****/ #define MPI3_PCIEIOUNIT0_ES_MAX_SWITCH_DEPTH_EXCEEDED (0x80000000) #define MPI3_PCIEIOUNIT0_ES_MAX_SWITCHES_EXCEEDED (0x40000000) #define MPI3_PCIEIOUNIT0_ES_MAX_ENDPOINTS_EXCEEDED (0x20000000) #define MPI3_PCIEIOUNIT0_ES_INSUFFICIENT_RESOURCES (0x10000000) #ifndef MPI3_PCIE_IO_UNIT0_PHY_MAX #define MPI3_PCIE_IO_UNIT0_PHY_MAX (1) #endif /* MPI3_PCIE_IO_UNIT0_PHY_MAX */ typedef struct _MPI3_PCIE_IO_UNIT_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 NumPhys; /* 0x0C */ U8 InitStatus; /* 0x0D */ U8 ASPM; /* 0x0E */ U8 Reserved0F; /* 0x0F */ MPI3_PCIE_IO_UNIT0_PHY_DATA PhyData[MPI3_PCIE_IO_UNIT0_PHY_MAX]; /* 0x10 */ } MPI3_PCIE_IO_UNIT_PAGE0, MPI3_POINTER PTR_MPI3_PCIE_IO_UNIT_PAGE0, Mpi3PcieIOUnitPage0_t, MPI3_POINTER pMpi3PcieIOUnitPage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_PCIEIOUNIT0_PAGEVERSION (0x00) /**** Defines for the InitStatus field ****/ #define MPI3_PCIEIOUNIT0_INITSTATUS_NO_ERRORS (0x00) #define MPI3_PCIEIOUNIT0_INITSTATUS_NEEDS_INITIALIZATION (0x01) #define MPI3_PCIEIOUNIT0_INITSTATUS_NO_TARGETS_ALLOCATED (0x02) #define MPI3_PCIEIOUNIT0_INITSTATUS_RESOURCE_ALLOC_FAILED (0x03) #define MPI3_PCIEIOUNIT0_INITSTATUS_BAD_NUM_PHYS (0x04) #define MPI3_PCIEIOUNIT0_INITSTATUS_UNSUPPORTED_CONFIG (0x05) #define MPI3_PCIEIOUNIT0_INITSTATUS_HOST_PORT_MISMATCH (0x06) #define MPI3_PCIEIOUNIT0_INITSTATUS_PHYS_NOT_CONSECUTIVE (0x07) #define MPI3_PCIEIOUNIT0_INITSTATUS_BAD_CLOCKING_MODE (0x08) #define MPI3_PCIEIOUNIT0_INITSTATUS_PROD_SPEC_START (0xF0) #define MPI3_PCIEIOUNIT0_INITSTATUS_PROD_SPEC_END (0xFF) /**** Defines for the ASPM field ****/ #define MPI3_PCIEIOUNIT0_ASPM_SWITCH_STATES_MASK (0xC0) #define MPI3_PCIEIOUNIT0_ASPM_SWITCH_STATES_SHIFT (6) #define MPI3_PCIEIOUNIT0_ASPM_DIRECT_STATES_MASK (0x30) #define MPI3_PCIEIOUNIT0_ASPM_DIRECT_STATES_SHIFT (4) /*** use MPI3_PCIE_ASPM_ENABLE_ defines for field values ***/ #define MPI3_PCIEIOUNIT0_ASPM_SWITCH_SUPPORT_MASK (0x0C) #define MPI3_PCIEIOUNIT0_ASPM_SWITCH_SUPPORT_SHIFT (2) #define MPI3_PCIEIOUNIT0_ASPM_DIRECT_SUPPORT_MASK (0x03) #define MPI3_PCIEIOUNIT0_ASPM_DIRECT_SUPPORT_SHIFT (0) /*** use MPI3_PCIE_ASPM_SUPPORT_ defines for field values ***/ /***************************************************************************** * PCIe IO Unit Page 1 * ****************************************************************************/ typedef struct _MPI3_PCIE_IO_UNIT1_PHY_DATA { U8 Link; /* 0x00 */ U8 LinkFlags; /* 0x01 */ U8 PhyFlags; /* 0x02 */ U8 MaxMinLinkRate; /* 0x03 */ U32 Reserved04; /* 0x04 */ U32 Reserved08; /* 0x08 */ } MPI3_PCIE_IO_UNIT1_PHY_DATA, MPI3_POINTER PTR_MPI3_PCIE_IO_UNIT1_PHY_DATA, Mpi3PcieIOUnit1PhyData_t, MPI3_POINTER pMpi3PcieIOUnit1PhyData_t; /**** Defines for the LinkFlags field ****/ #define MPI3_PCIEIOUNIT1_LINKFLAGS_PCIE_CLK_MODE_MASK (0x03) #define MPI3_PCIEIOUNIT1_LINKFLAGS_PCIE_CLK_MODE_DIS_SEPARATE_REFCLK (0x00) #define MPI3_PCIEIOUNIT1_LINKFLAGS_PCIE_CLK_MODE_EN_SRIS (0x01) #define MPI3_PCIEIOUNIT1_LINKFLAGS_PCIE_CLK_MODE_EN_SRNS (0x02) /**** Defines for the PhyFlags field ****/ #define MPI3_PCIEIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08) /**** Defines for the MaxMinLinkRate ****/ #define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_MASK (0xF0) #define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_SHIFT (4) #define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_2_5 (0x20) #define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_5_0 (0x30) #define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_8_0 (0x40) #define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_16_0 (0x50) #define MPI3_PCIEIOUNIT1_MMLR_MAX_RATE_32_0 (0x60) #ifndef MPI3_PCIE_IO_UNIT1_PHY_MAX #define MPI3_PCIE_IO_UNIT1_PHY_MAX (1) #endif /* MPI3_PCIE_IO_UNIT1_PHY_MAX */ typedef struct _MPI3_PCIE_IO_UNIT_PAGE1 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U32 ControlFlags; /* 0x08 */ U32 Reserved0C; /* 0x0C */ U8 NumPhys; /* 0x10 */ U8 Reserved11; /* 0x11 */ U8 ASPM; /* 0x12 */ U8 Reserved13; /* 0x13 */ MPI3_PCIE_IO_UNIT1_PHY_DATA PhyData[MPI3_PCIE_IO_UNIT1_PHY_MAX]; /* 0x14 */ } MPI3_PCIE_IO_UNIT_PAGE1, MPI3_POINTER PTR_MPI3_PCIE_IO_UNIT_PAGE1, Mpi3PcieIOUnitPage1_t, MPI3_POINTER pMpi3PcieIOUnitPage1_t; /**** Defines for the PageVersion field ****/ #define MPI3_PCIEIOUNIT1_PAGEVERSION (0x00) /**** Defines for the ControlFlags field ****/ #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_PERST_OVERRIDE_MASK (0xE0000000) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_PERST_OVERRIDE_NONE (0x00000000) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_PERST_OVERRIDE_DEASSERT (0x20000000) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_PERST_OVERRIDE_ASSERT (0x40000000) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_PERST_OVERRIDE_BACKPLANE_ERROR (0x60000000) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_REFCLK_OVERRIDE_MASK (0x1C000000) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_REFCLK_OVERRIDE_NONE (0x00000000) -#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_REFCLK_OVERRIDE_DEASSERT (0x04000000) -#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_REFCLK_OVERRIDE_ASSERT (0x08000000) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_REFCLK_OVERRIDE_ENABLE (0x04000000) +#define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_REFCLK_OVERRIDE_DISABLE (0x08000000) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_REFCLK_OVERRIDE_BACKPLANE_ERROR (0x0C000000) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_PARTIAL_CAPACITY_ENABLE (0x00000100) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_OVERRIDE_DISABLE (0x00000080) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_DISABLE (0x00000040) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_MASK (0x00000030) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SHIFT (4) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SRIS_SRNS_DISABLED (0x00000000) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SRIS_ENABLED (0x00000010) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_CLOCK_OVERRIDE_MODE_SRNS_ENABLED (0x00000020) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MASK (0x0000000F) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_USE_BACKPLANE (0x00000000) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_2_5 (0x00000002) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_5_0 (0x00000003) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_8_0 (0x00000004) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_16_0 (0x00000005) #define MPI3_PCIEIOUNIT1_CONTROL_FLAGS_LINK_RATE_OVERRIDE_MAX_32_0 (0x00000006) /**** Defines for the ASPM field ****/ #define MPI3_PCIEIOUNIT1_ASPM_SWITCH_MASK (0x0C) #define MPI3_PCIEIOUNIT1_ASPM_SWITCH_SHIFT (2) #define MPI3_PCIEIOUNIT1_ASPM_DIRECT_MASK (0x03) #define MPI3_PCIEIOUNIT1_ASPM_DIRECT_SHIFT (0) /*** use MPI3_PCIE_ASPM_ENABLE_ defines for ASPM field values ***/ /***************************************************************************** * PCIe IO Unit Page 2 * ****************************************************************************/ typedef struct _MPI3_PCIE_IO_UNIT_PAGE2 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U16 NVMeMaxQDx1; /* 0x08 */ U16 NVMeMaxQDx2; /* 0x0A */ U8 NVMeAbortTO; /* 0x0C */ U8 Reserved0D; /* 0x0D */ U16 NVMeMaxQDx4; /* 0x0E */ } MPI3_PCIE_IO_UNIT_PAGE2, MPI3_POINTER PTR_MPI3_PCIE_IO_UNIT_PAGE2, Mpi3PcieIOUnitPage2_t, MPI3_POINTER pMpi3PcieIOUnitPage2_t; /**** Defines for the PageVersion field ****/ #define MPI3_PCIEIOUNIT2_PAGEVERSION (0x00) /***************************************************************************** * PCIe IO Unit Page 3 * ****************************************************************************/ /**** Defines for Error Indexes ****/ #define MPI3_PCIEIOUNIT3_ERROR_RECEIVER_ERROR (0) #define MPI3_PCIEIOUNIT3_ERROR_RECOVERY (1) #define MPI3_PCIEIOUNIT3_ERROR_CORRECTABLE_ERROR_MSG (2) #define MPI3_PCIEIOUNIT3_ERROR_BAD_DLLP (3) #define MPI3_PCIEIOUNIT3_ERROR_BAD_TLP (4) #define MPI3_PCIEIOUNIT3_NUM_ERROR_INDEX (5) typedef struct _MPI3_PCIE_IO_UNIT3_ERROR { U16 ThresholdCount; /* 0x00 */ U16 Reserved02; /* 0x02 */ } MPI3_PCIE_IO_UNIT3_ERROR, MPI3_POINTER PTR_MPI3_PCIE_IO_UNIT3_ERROR, Mpi3PcieIOUnit3Error_t, MPI3_POINTER pMpi3PcieIOUnit3Error_t; typedef struct _MPI3_PCIE_IO_UNIT_PAGE3 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 ThresholdWindow; /* 0x08 */ U8 ThresholdAction; /* 0x09 */ U8 EscalationCount; /* 0x0A */ U8 EscalationAction; /* 0x0B */ U8 NumErrors; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ MPI3_PCIE_IO_UNIT3_ERROR Error[MPI3_PCIEIOUNIT3_NUM_ERROR_INDEX]; /* 0x10 */ } MPI3_PCIE_IO_UNIT_PAGE3, MPI3_POINTER PTR_MPI3_PCIE_IO_UNIT_PAGE3, Mpi3PcieIOUnitPage3_t, MPI3_POINTER pMpi3PcieIOUnitPage3_t; /**** Defines for the PageVersion field ****/ #define MPI3_PCIEIOUNIT3_PAGEVERSION (0x00) /**** Defines for the ThresholdAction and EscalationAction fields ****/ #define MPI3_PCIEIOUNIT3_ACTION_NO_ACTION (0x00) #define MPI3_PCIEIOUNIT3_ACTION_HOT_RESET (0x01) #define MPI3_PCIEIOUNIT3_ACTION_REDUCE_LINK_RATE_ONLY (0x02) #define MPI3_PCIEIOUNIT3_ACTION_REDUCE_LINK_RATE_NO_ACCESS (0x03) /**** Defines for Error Indexes - use MPI3_PCIEIOUNIT3_ERROR_ defines ****/ /***************************************************************************** * PCIe Switch Configuration Pages * ****************************************************************************/ /***************************************************************************** * PCIe Switch Page 0 * ****************************************************************************/ typedef struct _MPI3_PCIE_SWITCH_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 IOUnitPort; /* 0x08 */ U8 SwitchStatus; /* 0x09 */ U8 Reserved0A[2]; /* 0x0A */ U16 DevHandle; /* 0x0C */ U16 ParentDevHandle; /* 0x0E */ U8 NumPorts; /* 0x10 */ U8 PCIeLevel; /* 0x11 */ U16 Reserved12; /* 0x12 */ U32 Reserved14; /* 0x14 */ U32 Reserved18; /* 0x18 */ U32 Reserved1C; /* 0x1C */ } MPI3_PCIE_SWITCH_PAGE0, MPI3_POINTER PTR_MPI3_PCIE_SWITCH_PAGE0, Mpi3PcieSwitchPage0_t, MPI3_POINTER pMpi3PcieSwitchPage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_PCIESWITCH0_PAGEVERSION (0x00) /**** Defines for the SwitchStatus field ****/ #define MPI3_PCIESWITCH0_SS_NOT_RESPONDING (0x02) #define MPI3_PCIESWITCH0_SS_RESPONDING (0x03) #define MPI3_PCIESWITCH0_SS_DELAY_NOT_RESPONDING (0x04) /***************************************************************************** * PCIe Switch Page 1 * ****************************************************************************/ typedef struct _MPI3_PCIE_SWITCH_PAGE1 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 IOUnitPort; /* 0x08 */ U8 Flags; /* 0x09 */ U16 Reserved0A; /* 0x0A */ U8 NumPorts; /* 0x0C */ U8 PortNum; /* 0x0D */ U16 AttachedDevHandle; /* 0x0E */ U16 SwitchDevHandle; /* 0x10 */ U8 NegotiatedPortWidth; /* 0x12 */ U8 NegotiatedLinkRate; /* 0x13 */ U16 Slot; /* 0x14 */ U16 SlotIndex; /* 0x16 */ U32 Reserved18; /* 0x18 */ } MPI3_PCIE_SWITCH_PAGE1, MPI3_POINTER PTR_MPI3_PCIE_SWITCH_PAGE1, Mpi3PcieSwitchPage1_t, MPI3_POINTER pMpi3PcieSwitchPage1_t; /**** Defines for the PageVersion field ****/ #define MPI3_PCIESWITCH1_PAGEVERSION (0x00) -/**** Defines for the FLAGS field ****/ +/**** Defines for the Flags field ****/ #define MPI3_PCIESWITCH1_FLAGS_ASPMSTATE_MASK (0x0C) #define MPI3_PCIESWITCH1_FLAGS_ASPMSTATE_SHIFT (2) + /*** use MPI3_PCIE_ASPM_ENABLE_ defines for ASPMState field values ***/ #define MPI3_PCIESWITCH1_FLAGS_ASPMSUPPORT_MASK (0x03) #define MPI3_PCIESWITCH1_FLAGS_ASPMSUPPORT_SHIFT (0) + /*** use MPI3_PCIE_ASPM_SUPPORT_ defines for ASPMSupport field values ***/ /**** Defines for the NegotiatedLinkRate field - use MPI3_PCIE_NEG_LINK_RATE_ defines ****/ /**** Defines for the Slot field - use MPI3_SLOT_ defines ****/ /**** Defines for the SlotIndex field - use MPI3_SLOT_INDEX_ ****/ /***************************************************************************** * PCIe Switch Page 2 * ****************************************************************************/ #ifndef MPI3_PCIESWITCH2_MAX_NUM_PORTS #define MPI3_PCIESWITCH2_MAX_NUM_PORTS (1) #endif /* MPI3_PCIESWITCH2_MAX_NUM_PORTS */ typedef struct _MPI3_PCIESWITCH2_PORT_ELEMENT { U16 LinkChangeCount; /* 0x00 */ U16 RateChangeCount; /* 0x02 */ U32 Reserved04; /* 0x04 */ } MPI3_PCIESWITCH2_PORT_ELEMENT, MPI3_POINTER PTR_MPI3_PCIESWITCH2_PORT_ELEMENT, Mpi3PcieSwitch2PortElement_t, MPI3_POINTER pMpi3PcieSwitch2PortElement_t; typedef struct _MPI3_PCIE_SWITCH_PAGE2 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 NumPorts; /* 0x08 */ U8 Reserved09; /* 0x09 */ U16 DevHandle; /* 0x0A */ U32 Reserved0C; /* 0x0C */ MPI3_PCIESWITCH2_PORT_ELEMENT Port[MPI3_PCIESWITCH2_MAX_NUM_PORTS]; /* 0x10 */ /* variable length */ } MPI3_PCIE_SWITCH_PAGE2, MPI3_POINTER PTR_MPI3_PCIE_SWITCH_PAGE2, Mpi3PcieSwitchPage2_t, MPI3_POINTER pMpi3PcieSwitchPage2_t; /**** Defines for the PageVersion field ****/ #define MPI3_PCIESWITCH2_PAGEVERSION (0x00) /***************************************************************************** * PCIe Link Configuration Pages * ****************************************************************************/ /***************************************************************************** * PCIe Link Page 0 * ****************************************************************************/ typedef struct _MPI3_PCIE_LINK_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U8 Link; /* 0x08 */ U8 Reserved09[3]; /* 0x09 */ U32 Reserved0C; /* 0x0C */ U32 ReceiverErrorCount; /* 0x10 */ U32 RecoveryCount; /* 0x14 */ U32 CorrErrorMsgCount; /* 0x18 */ U32 NonFatalErrorMsgCount; /* 0x1C */ U32 FatalErrorMsgCount; /* 0x20 */ U32 NonFatalErrorCount; /* 0x24 */ U32 FatalErrorCount; /* 0x28 */ U32 BadDLLPCount; /* 0x2C */ U32 BadTLPCount; /* 0x30 */ } MPI3_PCIE_LINK_PAGE0, MPI3_POINTER PTR_MPI3_PCIE_LINK_PAGE0, Mpi3PcieLinkPage0_t, MPI3_POINTER pMpi3PcieLinkPage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_PCIELINK0_PAGEVERSION (0x00) /***************************************************************************** * Enclosure Configuration Pages * ****************************************************************************/ /***************************************************************************** * Enclosure Page 0 * ****************************************************************************/ typedef struct _MPI3_ENCLOSURE_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U64 EnclosureLogicalID; /* 0x08 */ U16 Flags; /* 0x10 */ U16 EnclosureHandle; /* 0x12 */ U16 NumSlots; /* 0x14 */ U16 Reserved16; /* 0x16 */ U8 IOUnitPort; /* 0x18 */ U8 EnclosureLevel; /* 0x19 */ U16 SEPDevHandle; /* 0x1A */ U8 ChassisSlot; /* 0x1C */ U8 Reserved1D[3]; /* 0x1D */ + U32 ReceptacleIDs; /* 0x20 */ + U32 Reserved24; /* 0x24 */ } MPI3_ENCLOSURE_PAGE0, MPI3_POINTER PTR_MPI3_ENCLOSURE_PAGE0, Mpi3EnclosurePage0_t, MPI3_POINTER pMpi3EnclosurePage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_ENCLOSURE0_PAGEVERSION (0x00) /**** Defines for the Flags field ****/ #define MPI3_ENCLS0_FLAGS_ENCL_TYPE_MASK (0xC000) #define MPI3_ENCLS0_FLAGS_ENCL_TYPE_VIRTUAL (0x0000) #define MPI3_ENCLS0_FLAGS_ENCL_TYPE_SAS (0x4000) #define MPI3_ENCLS0_FLAGS_ENCL_TYPE_PCIE (0x8000) #define MPI3_ENCLS0_FLAGS_CHASSIS_SLOT_VALID (0x0020) #define MPI3_ENCLS0_FLAGS_ENCL_DEV_PRESENT_MASK (0x0010) #define MPI3_ENCLS0_FLAGS_ENCL_DEV_NOT_FOUND (0x0000) #define MPI3_ENCLS0_FLAGS_ENCL_DEV_PRESENT (0x0010) #define MPI3_ENCLS0_FLAGS_MNG_MASK (0x000F) #define MPI3_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000) #define MPI3_ENCLS0_FLAGS_MNG_IOC_SES (0x0001) #define MPI3_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0002) -/**** Defines for the PhysicalPort field - use MPI3_DEVICE0_PHYPORT_ defines ****/ +/**** Defines for the ReceptacleIDs field ****/ +#define MPI3_ENCLS0_RECEPTACLEIDS_NOT_REPORTED (0x00000000) /***************************************************************************** * Device Configuration Pages * ****************************************************************************/ /***************************************************************************** * Common definitions used by Device Configuration Pages * ****************************************************************************/ /**** Defines for the DeviceForm field ****/ #define MPI3_DEVICE_DEVFORM_SAS_SATA (0x00) #define MPI3_DEVICE_DEVFORM_PCIE (0x01) #define MPI3_DEVICE_DEVFORM_VD (0x02) /***************************************************************************** * Device Page 0 * ****************************************************************************/ typedef struct _MPI3_DEVICE0_SAS_SATA_FORMAT { U64 SASAddress; /* 0x00 */ U16 Flags; /* 0x08 */ U16 DeviceInfo; /* 0x0A */ U8 PhyNum; /* 0x0C */ U8 AttachedPhyIdentifier; /* 0x0D */ U8 MaxPortConnections; /* 0x0E */ U8 ZoneGroup; /* 0x0F */ } MPI3_DEVICE0_SAS_SATA_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE0_SAS_SATA_FORMAT, Mpi3Device0SasSataFormat_t, MPI3_POINTER pMpi3Device0SasSataFormat_t; /**** Defines for the Flags field ****/ #define MPI3_DEVICE0_SASSATA_FLAGS_WRITE_SAME_UNMAP_NCQ (0x0400) #define MPI3_DEVICE0_SASSATA_FLAGS_SLUMBER_CAP (0x0200) #define MPI3_DEVICE0_SASSATA_FLAGS_PARTIAL_CAP (0x0100) #define MPI3_DEVICE0_SASSATA_FLAGS_ASYNC_NOTIFY (0x0080) #define MPI3_DEVICE0_SASSATA_FLAGS_SW_PRESERVE (0x0040) #define MPI3_DEVICE0_SASSATA_FLAGS_UNSUPP_DEV (0x0020) #define MPI3_DEVICE0_SASSATA_FLAGS_48BIT_LBA (0x0010) #define MPI3_DEVICE0_SASSATA_FLAGS_SMART_SUPP (0x0008) #define MPI3_DEVICE0_SASSATA_FLAGS_NCQ_SUPP (0x0004) #define MPI3_DEVICE0_SASSATA_FLAGS_FUA_SUPP (0x0002) #define MPI3_DEVICE0_SASSATA_FLAGS_PERSIST_CAP (0x0001) /**** Defines for the DeviceInfo field - use MPI3_SAS_DEVICE_INFO_ defines (see mpi30_sas.h) ****/ typedef struct _MPI3_DEVICE0_PCIE_FORMAT { U8 SupportedLinkRates; /* 0x00 */ U8 MaxPortWidth; /* 0x01 */ U8 NegotiatedPortWidth; /* 0x02 */ U8 NegotiatedLinkRate; /* 0x03 */ U8 PortNum; /* 0x04 */ U8 ControllerResetTO; /* 0x05 */ U16 DeviceInfo; /* 0x06 */ U32 MaximumDataTransferSize; /* 0x08 */ U32 Capabilities; /* 0x0C */ U16 NOIOB; /* 0x10 */ U8 NVMeAbortTO; /* 0x12 */ U8 PageSize; /* 0x13 */ U16 ShutdownLatency; /* 0x14 */ U8 RecoveryInfo; /* 0x16 */ U8 Reserved17; /* 0x17 */ } MPI3_DEVICE0_PCIE_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE0_PCIE_FORMAT, Mpi3Device0PcieFormat_t, MPI3_POINTER pMpi3Device0PcieFormat_t; /**** Defines for the SupportedLinkRates field ****/ #define MPI3_DEVICE0_PCIE_LINK_RATE_32_0_SUPP (0x10) #define MPI3_DEVICE0_PCIE_LINK_RATE_16_0_SUPP (0x08) #define MPI3_DEVICE0_PCIE_LINK_RATE_8_0_SUPP (0x04) #define MPI3_DEVICE0_PCIE_LINK_RATE_5_0_SUPP (0x02) #define MPI3_DEVICE0_PCIE_LINK_RATE_2_5_SUPP (0x01) /**** Defines for the NegotiatedLinkRate field - use MPI3_PCIE_NEG_LINK_RATE_ defines ****/ /**** Defines for DeviceInfo bitfield ****/ #define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK (0x0007) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NO_DEVICE (0x0000) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE (0x0001) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_SWITCH_DEVICE (0x0002) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_SCSI_DEVICE (0x0003) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_ASPM_MASK (0x0030) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_ASPM_SHIFT (4) /*** use MPI3_PCIE_ASPM_ENABLE_ defines for ASPM field values ***/ #define MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_MASK (0x00C0) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_SHIFT (6) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_0 (0x0000) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_1 (0x0040) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_2 (0x0080) #define MPI3_DEVICE0_PCIE_DEVICE_INFO_PITYPE_3 (0x00C0) /**** Defines for the Capabilities field ****/ #define MPI3_DEVICE0_PCIE_CAP_SGL_EXTRA_LENGTH_SUPPORTED (0x00000020) #define MPI3_DEVICE0_PCIE_CAP_METADATA_SEPARATED (0x00000010) #define MPI3_DEVICE0_PCIE_CAP_SGL_DWORD_ALIGN_REQUIRED (0x00000008) #define MPI3_DEVICE0_PCIE_CAP_SGL_FORMAT_SGL (0x00000004) #define MPI3_DEVICE0_PCIE_CAP_SGL_FORMAT_PRP (0x00000000) #define MPI3_DEVICE0_PCIE_CAP_BIT_BUCKET_SGL_SUPP (0x00000002) #define MPI3_DEVICE0_PCIE_CAP_SGL_SUPP (0x00000001) #define MPI3_DEVICE0_PCIE_CAP_ASPM_MASK (0x000000C0) #define MPI3_DEVICE0_PCIE_CAP_ASPM_SHIFT (6) /*** use MPI3_PCIE_ASPM_SUPPORT_ defines for ASPM field values ***/ -/**** Defines for the RecoverMethod field ****/ +/**** Defines for the RecoveryInfo field ****/ #define MPI3_DEVICE0_PCIE_RECOVER_METHOD_MASK (0xE0) #define MPI3_DEVICE0_PCIE_RECOVER_METHOD_NS_MGMT (0x00) #define MPI3_DEVICE0_PCIE_RECOVER_METHOD_FORMAT (0x20) #define MPI3_DEVICE0_PCIE_RECOVER_REASON_MASK (0x1F) #define MPI3_DEVICE0_PCIE_RECOVER_REASON_NO_NS (0x00) #define MPI3_DEVICE0_PCIE_RECOVER_REASON_NO_NSID_1 (0x01) #define MPI3_DEVICE0_PCIE_RECOVER_REASON_TOO_MANY_NS (0x02) #define MPI3_DEVICE0_PCIE_RECOVER_REASON_PROTECTION (0x03) #define MPI3_DEVICE0_PCIE_RECOVER_REASON_METADATA_SZ (0x04) #define MPI3_DEVICE0_PCIE_RECOVER_REASON_LBA_DATA_SZ (0x05) #define MPI3_DEVICE0_PCIE_RECOVER_REASON_PARTIAL_CAP (0x06) typedef struct _MPI3_DEVICE0_VD_FORMAT { U8 VdState; /* 0x00 */ U8 RAIDLevel; /* 0x01 */ U16 DeviceInfo; /* 0x02 */ U16 Flags; /* 0x04 */ U16 IOThrottleGroup; /* 0x06 */ U16 IOThrottleGroupLow; /* 0x08 */ U16 IOThrottleGroupHigh; /* 0x0A */ U32 Reserved0C; /* 0x0C */ } MPI3_DEVICE0_VD_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE0_VD_FORMAT, Mpi3Device0VdFormat_t, MPI3_POINTER pMpi3Device0VdFormat_t; /**** Defines for the VdState field ****/ #define MPI3_DEVICE0_VD_STATE_OFFLINE (0x00) #define MPI3_DEVICE0_VD_STATE_PARTIALLY_DEGRADED (0x01) #define MPI3_DEVICE0_VD_STATE_DEGRADED (0x02) #define MPI3_DEVICE0_VD_STATE_OPTIMAL (0x03) /**** Defines for RAIDLevel field ****/ #define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_0 (0) #define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_1 (1) #define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_5 (5) #define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_6 (6) #define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_10 (10) #define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_50 (50) #define MPI3_DEVICE0_VD_RAIDLEVEL_RAID_60 (60) /**** Defines for DeviceInfo field ****/ #define MPI3_DEVICE0_VD_DEVICE_INFO_HDD (0x0010) #define MPI3_DEVICE0_VD_DEVICE_INFO_SSD (0x0008) #define MPI3_DEVICE0_VD_DEVICE_INFO_NVME (0x0004) #define MPI3_DEVICE0_VD_DEVICE_INFO_SATA (0x0002) #define MPI3_DEVICE0_VD_DEVICE_INFO_SAS (0x0001) /**** Defines for the Flags field ****/ #define MPI3_DEVICE0_VD_FLAGS_IO_THROTTLE_GROUP_QD_MASK (0xF000) #define MPI3_DEVICE0_VD_FLAGS_IO_THROTTLE_GROUP_QD_SHIFT (12) typedef union _MPI3_DEVICE0_DEV_SPEC_FORMAT { MPI3_DEVICE0_SAS_SATA_FORMAT SasSataFormat; MPI3_DEVICE0_PCIE_FORMAT PcieFormat; MPI3_DEVICE0_VD_FORMAT VdFormat; } MPI3_DEVICE0_DEV_SPEC_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE0_DEV_SPEC_FORMAT, Mpi3Device0DevSpecFormat_t, MPI3_POINTER pMpi3Device0DevSpecFormat_t; typedef struct _MPI3_DEVICE_PAGE0 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U16 DevHandle; /* 0x08 */ U16 ParentDevHandle; /* 0x0A */ U16 Slot; /* 0x0C */ U16 EnclosureHandle; /* 0x0E */ U64 WWID; /* 0x10 */ U16 PersistentID; /* 0x18 */ U8 IOUnitPort; /* 0x1A */ U8 AccessStatus; /* 0x1B */ U16 Flags; /* 0x1C */ U16 Reserved1E; /* 0x1E */ U16 SlotIndex; /* 0x20 */ U16 QueueDepth; /* 0x22 */ U8 Reserved24[3]; /* 0x24 */ U8 DeviceForm; /* 0x27 */ MPI3_DEVICE0_DEV_SPEC_FORMAT DeviceSpecific; /* 0x28 */ } MPI3_DEVICE_PAGE0, MPI3_POINTER PTR_MPI3_DEVICE_PAGE0, Mpi3DevicePage0_t, MPI3_POINTER pMpi3DevicePage0_t; /**** Defines for the PageVersion field ****/ #define MPI3_DEVICE0_PAGEVERSION (0x00) /**** Defines for the ParentDevHandle field ****/ #define MPI3_DEVICE0_PARENT_INVALID (0xFFFF) /**** Defines for the Slot field - use MPI3_SLOT_ defines ****/ /**** Defines for the EnclosureHandle field ****/ #define MPI3_DEVICE0_ENCLOSURE_HANDLE_NO_ENCLOSURE (0x0000) /**** Defines for the WWID field ****/ #define MPI3_DEVICE0_WWID_INVALID (0xFFFFFFFFFFFFFFFF) /**** Defines for the PersistentID field ****/ #define MPI3_DEVICE0_PERSISTENTID_INVALID (0xFFFF) /**** Defines for the IOUnitPort field ****/ #define MPI3_DEVICE0_IOUNITPORT_INVALID (0xFF) /**** Defines for the AccessStatus field ****/ /* Generic Access Status Codes */ #define MPI3_DEVICE0_ASTATUS_NO_ERRORS (0x00) #define MPI3_DEVICE0_ASTATUS_NEEDS_INITIALIZATION (0x01) #define MPI3_DEVICE0_ASTATUS_CAP_UNSUPPORTED (0x02) #define MPI3_DEVICE0_ASTATUS_DEVICE_BLOCKED (0x03) #define MPI3_DEVICE0_ASTATUS_UNAUTHORIZED (0x04) #define MPI3_DEVICE0_ASTATUS_DEVICE_MISSING_DELAY (0x05) #define MPI3_DEVICE0_ASTATUS_PREPARE (0x06) #define MPI3_DEVICE0_ASTATUS_SAFE_MODE (0x07) #define MPI3_DEVICE0_ASTATUS_GENERIC_MAX (0x0F) /* SAS Access Status Codes */ #define MPI3_DEVICE0_ASTATUS_SAS_UNKNOWN (0x10) #define MPI3_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE (0x11) #define MPI3_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE (0x12) #define MPI3_DEVICE0_ASTATUS_SAS_MAX (0x1F) /* SATA Access Status Codes */ #define MPI3_DEVICE0_ASTATUS_SIF_UNKNOWN (0x20) #define MPI3_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x21) #define MPI3_DEVICE0_ASTATUS_SIF_DIAG (0x22) #define MPI3_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x23) #define MPI3_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x24) #define MPI3_DEVICE0_ASTATUS_SIF_PIO_SN (0x25) #define MPI3_DEVICE0_ASTATUS_SIF_MDMA_SN (0x26) #define MPI3_DEVICE0_ASTATUS_SIF_UDMA_SN (0x27) #define MPI3_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x28) #define MPI3_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x29) #define MPI3_DEVICE0_ASTATUS_SIF_MAX (0x2F) /* PCIe Access Status Codes */ #define MPI3_DEVICE0_ASTATUS_PCIE_UNKNOWN (0x30) #define MPI3_DEVICE0_ASTATUS_PCIE_MEM_SPACE_ACCESS (0x31) #define MPI3_DEVICE0_ASTATUS_PCIE_UNSUPPORTED (0x32) #define MPI3_DEVICE0_ASTATUS_PCIE_MSIX_REQUIRED (0x33) #define MPI3_DEVICE0_ASTATUS_PCIE_ECRC_REQUIRED (0x34) #define MPI3_DEVICE0_ASTATUS_PCIE_MAX (0x3F) /* NVMe Access Status Codes */ #define MPI3_DEVICE0_ASTATUS_NVME_UNKNOWN (0x40) #define MPI3_DEVICE0_ASTATUS_NVME_READY_TIMEOUT (0x41) #define MPI3_DEVICE0_ASTATUS_NVME_DEVCFG_UNSUPPORTED (0x42) #define MPI3_DEVICE0_ASTATUS_NVME_IDENTIFY_FAILED (0x43) #define MPI3_DEVICE0_ASTATUS_NVME_QCONFIG_FAILED (0x44) #define MPI3_DEVICE0_ASTATUS_NVME_QCREATION_FAILED (0x45) #define MPI3_DEVICE0_ASTATUS_NVME_EVENTCFG_FAILED (0x46) #define MPI3_DEVICE0_ASTATUS_NVME_GET_FEATURE_STAT_FAILED (0x47) #define MPI3_DEVICE0_ASTATUS_NVME_IDLE_TIMEOUT (0x48) #define MPI3_DEVICE0_ASTATUS_NVME_CTRL_FAILURE_STATUS (0x49) #define MPI3_DEVICE0_ASTATUS_NVME_INSUFFICIENT_POWER (0x4A) #define MPI3_DEVICE0_ASTATUS_NVME_DOORBELL_STRIDE (0x4B) #define MPI3_DEVICE0_ASTATUS_NVME_MEM_PAGE_MIN_SIZE (0x4C) #define MPI3_DEVICE0_ASTATUS_NVME_MEMORY_ALLOCATION (0x4D) #define MPI3_DEVICE0_ASTATUS_NVME_COMPLETION_TIME (0x4E) #define MPI3_DEVICE0_ASTATUS_NVME_BAR (0x4F) #define MPI3_DEVICE0_ASTATUS_NVME_NS_DESCRIPTOR (0x50) #define MPI3_DEVICE0_ASTATUS_NVME_INCOMPATIBLE_SETTINGS (0x51) #define MPI3_DEVICE0_ASTATUS_NVME_TOO_MANY_ERRORS (0x52) #define MPI3_DEVICE0_ASTATUS_NVME_MAX (0x5F) /* Virtual Device Access Status Codes */ #define MPI3_DEVICE0_ASTATUS_VD_UNKNOWN (0x80) #define MPI3_DEVICE0_ASTATUS_VD_MAX (0x8F) /**** Defines for the Flags field ****/ #define MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_MASK (0xE000) #define MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_NO_LIMIT (0x0000) #define MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_256_LB (0x2000) #define MPI3_DEVICE0_FLAGS_MAX_WRITE_SAME_2048_LB (0x4000) #define MPI3_DEVICE0_FLAGS_CONTROLLER_DEV_HANDLE (0x0080) #define MPI3_DEVICE0_FLAGS_IO_THROTTLING_REQUIRED (0x0010) #define MPI3_DEVICE0_FLAGS_HIDDEN (0x0008) #define MPI3_DEVICE0_FLAGS_ATT_METHOD_VIRTUAL (0x0004) #define MPI3_DEVICE0_FLAGS_ATT_METHOD_DIR_ATTACHED (0x0002) #define MPI3_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) /**** Defines for the SlotIndex field - use MPI3_SLOT_INDEX_ defines ****/ /**** Defines for the DeviceForm field - use MPI3_DEVICE_DEVFORM_ defines ****/ /**** Defines for the QueueDepth field ****/ #define MPI3_DEVICE0_QUEUE_DEPTH_NOT_APPLICABLE (0x0000) /***************************************************************************** * Device Page 1 * ****************************************************************************/ typedef struct _MPI3_DEVICE1_SAS_SATA_FORMAT { U32 Reserved00; /* 0x00 */ } MPI3_DEVICE1_SAS_SATA_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE1_SAS_SATA_FORMAT, Mpi3Device1SasSataFormat_t, MPI3_POINTER pMpi3Device1SasSataFormat_t; typedef struct _MPI3_DEVICE1_PCIE_FORMAT { U16 VendorID; /* 0x00 */ U16 DeviceID; /* 0x02 */ U16 SubsystemVendorID; /* 0x04 */ U16 SubsystemID; /* 0x06 */ U32 Reserved08; /* 0x08 */ U8 RevisionID; /* 0x0C */ U8 Reserved0D; /* 0x0D */ U16 PCIParameters; /* 0x0E */ } MPI3_DEVICE1_PCIE_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE1_PCIE_FORMAT, Mpi3Device1PcieFormat_t, MPI3_POINTER pMpi3Device1PcieFormat_t; /**** Defines for the PCIParameters field ****/ #define MPI3_DEVICE1_PCIE_PARAMS_DATA_SIZE_128B (0x0) #define MPI3_DEVICE1_PCIE_PARAMS_DATA_SIZE_256B (0x1) #define MPI3_DEVICE1_PCIE_PARAMS_DATA_SIZE_512B (0x2) #define MPI3_DEVICE1_PCIE_PARAMS_DATA_SIZE_1024B (0x3) #define MPI3_DEVICE1_PCIE_PARAMS_DATA_SIZE_2048B (0x4) #define MPI3_DEVICE1_PCIE_PARAMS_DATA_SIZE_4096B (0x5) /*** MaxReadRequestSize, CurrentMaxPayloadSize, and MaxPayloadSizeSupported ***/ /*** all use the size definitions above - shifted to the proper position ***/ #define MPI3_DEVICE1_PCIE_PARAMS_MAX_READ_REQ_MASK (0x01C0) #define MPI3_DEVICE1_PCIE_PARAMS_MAX_READ_REQ_SHIFT (6) #define MPI3_DEVICE1_PCIE_PARAMS_CURR_MAX_PAYLOAD_MASK (0x0038) #define MPI3_DEVICE1_PCIE_PARAMS_CURR_MAX_PAYLOAD_SHIFT (3) #define MPI3_DEVICE1_PCIE_PARAMS_SUPP_MAX_PAYLOAD_MASK (0x0007) #define MPI3_DEVICE1_PCIE_PARAMS_SUPP_MAX_PAYLOAD_SHIFT (0) typedef struct _MPI3_DEVICE1_VD_FORMAT { U32 Reserved00; /* 0x00 */ } MPI3_DEVICE1_VD_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE1_VD_FORMAT, Mpi3Device1VdFormat_t, MPI3_POINTER pMpi3Device1VdFormat_t; typedef union _MPI3_DEVICE1_DEV_SPEC_FORMAT { MPI3_DEVICE1_SAS_SATA_FORMAT SasSataFormat; MPI3_DEVICE1_PCIE_FORMAT PcieFormat; MPI3_DEVICE1_VD_FORMAT VdFormat; } MPI3_DEVICE1_DEV_SPEC_FORMAT, MPI3_POINTER PTR_MPI3_DEVICE1_DEV_SPEC_FORMAT, Mpi3Device1DevSpecFormat_t, MPI3_POINTER pMpi3Device1DevSpecFormat_t; typedef struct _MPI3_DEVICE_PAGE1 { MPI3_CONFIG_PAGE_HEADER Header; /* 0x00 */ U16 DevHandle; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U16 LinkChangeCount; /* 0x0C */ U16 RateChangeCount; /* 0x0E */ U16 TMCount; /* 0x10 */ U16 Reserved12; /* 0x12 */ U32 Reserved14[10]; /* 0x14 */ U8 Reserved3C[3]; /* 0x3C */ U8 DeviceForm; /* 0x3F */ MPI3_DEVICE1_DEV_SPEC_FORMAT DeviceSpecific; /* 0x40 */ } MPI3_DEVICE_PAGE1, MPI3_POINTER PTR_MPI3_DEVICE_PAGE1, Mpi3DevicePage1_t, MPI3_POINTER pMpi3DevicePage1_t; /**** Defines for the PageVersion field ****/ #define MPI3_DEVICE1_PAGEVERSION (0x00) /**** Defines for the LinkChangeCount, RateChangeCount, TMCount fields ****/ #define MPI3_DEVICE1_COUNTER_MAX (0xFFFE) #define MPI3_DEVICE1_COUNTER_INVALID (0xFFFF) /**** Defines for the DeviceForm field - use MPI3_DEVICE_DEVFORM_ defines ****/ #endif /* MPI30_CNFG_H */ diff --git a/sys/dev/mpi3mr/mpi/mpi30_image.h b/sys/dev/mpi3mr/mpi/mpi30_image.h index 7b953cb3b1a6..917763b3e921 100644 --- a/sys/dev/mpi3mr/mpi/mpi30_image.h +++ b/sys/dev/mpi3mr/mpi/mpi30_image.h @@ -1,426 +1,421 @@ /* - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. + * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved. * Support: * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD * */ - #ifndef MPI30_IMAGE_H #define MPI30_IMAGE_H 1 /* Component Image Version */ typedef struct _MPI3_COMP_IMAGE_VERSION { U16 BuildNum; /* 0x00 */ U16 CustomerID; /* 0x02 */ U8 PhaseMinor; /* 0x04 */ U8 PhaseMajor; /* 0x05 */ U8 GenMinor; /* 0x06 */ U8 GenMajor; /* 0x07 */ } MPI3_COMP_IMAGE_VERSION, MPI3_POINTER PTR_MPI3_COMP_IMAGE_VERSION, Mpi3CompImageVersion_t, MPI3_POINTER pMpi3CompImageVersion_t; /* Hash Exclusion Format */ typedef struct _MPI3_HASH_EXCLUSION_FORMAT { U32 Offset; /* 0x00 */ U32 Size; /* 0x04 */ } MPI3_HASH_EXCLUSION_FORMAT, MPI3_POINTER PTR_MPI3_HASH_EXCLUSION_FORMAT, Mpi3HashSxclusionFormat_t, MPI3_POINTER pMpi3HashExclusionFormat_t; #define MPI3_IMAGE_HASH_EXCUSION_NUM (4) /* FW Image Header */ typedef struct _MPI3_COMPONENT_IMAGE_HEADER { U32 Signature0; /* 0x00 */ U32 LoadAddress; /* 0x04 */ U32 DataSize; /* 0x08 */ U32 StartOffset; /* 0x0C */ U32 Signature1; /* 0x10 */ U32 FlashOffset; /* 0x14 */ U32 ImageSize; /* 0x18 */ U32 VersionStringOffset; /* 0x1C */ U32 BuildDateStringOffset; /* 0x20 */ U32 BuildTimeStringOffset; /* 0x24 */ U32 EnvironmentVariableOffset; /* 0x28 */ U32 ApplicationSpecific; /* 0x2C */ U32 Signature2; /* 0x30 */ U32 HeaderSize; /* 0x34 */ U32 Crc; /* 0x38 */ U32 Flags; /* 0x3C */ U32 SecondaryFlashOffset; /* 0x40 */ U32 ETPOffset; /* 0x44 */ U32 ETPSize; /* 0x48 */ MPI3_VERSION_UNION RMCInterfaceVersion; /* 0x4C */ MPI3_VERSION_UNION ETPInterfaceVersion; /* 0x50 */ MPI3_COMP_IMAGE_VERSION ComponentImageVersion; /* 0x54 */ MPI3_HASH_EXCLUSION_FORMAT HashExclusion[MPI3_IMAGE_HASH_EXCUSION_NUM]; /* 0x5C */ U32 NextImageHeaderOffset; /* 0x7C */ MPI3_VERSION_UNION SecurityVersion; /* 0x80 */ U32 Reserved84[31]; /* 0x84 -- 0xFC */ } MPI3_COMPONENT_IMAGE_HEADER, MPI3_POINTER PTR_MPI3_COMPONENT_IMAGE_HEADER, Mpi3ComponentImageHeader_t, MPI3_POINTER pMpi3ComponentImageHeader_t; /**** Definitions for Signature0 field ****/ #define MPI3_IMAGE_HEADER_SIGNATURE0_MPI3 (0xEB00003E) /**** Definitions for LoadAddress field ****/ #define MPI3_IMAGE_HEADER_LOAD_ADDRESS_INVALID (0x00000000) /**** Definitions for Signature1 field ****/ #define MPI3_IMAGE_HEADER_SIGNATURE1_APPLICATION (0x20505041) /* string "APP " */ #define MPI3_IMAGE_HEADER_SIGNATURE1_FIRST_MUTABLE (0x20434D46) /* string "FMC " */ #define MPI3_IMAGE_HEADER_SIGNATURE1_BSP (0x20505342) /* string "BSP " */ #define MPI3_IMAGE_HEADER_SIGNATURE1_ROM_BIOS (0x534F4942) /* string "BIOS" */ #define MPI3_IMAGE_HEADER_SIGNATURE1_HII_X64 (0x4D494948) /* string "HIIM" */ #define MPI3_IMAGE_HEADER_SIGNATURE1_HII_ARM (0x41494948) /* string "HIIA" */ #define MPI3_IMAGE_HEADER_SIGNATURE1_CPLD (0x444C5043) /* string "CPLD" */ #define MPI3_IMAGE_HEADER_SIGNATURE1_SPD (0x20445053) /* string "SPD " */ #define MPI3_IMAGE_HEADER_SIGNATURE1_GAS_GAUGE (0x20534147) /* string "GAS " */ #define MPI3_IMAGE_HEADER_SIGNATURE1_PBLP (0x504C4250) /* string "PBLP" */ #define MPI3_IMAGE_HEADER_SIGNATURE1_MANIFEST (0x464E414D) /* string "MANF" */ #define MPI3_IMAGE_HEADER_SIGNATURE1_OEM (0x204D454F) /* string "OEM " */ #define MPI3_IMAGE_HEADER_SIGNATURE1_RMC (0x20434D52) /* string "RMC " */ #define MPI3_IMAGE_HEADER_SIGNATURE1_SMM (0x204D4D53) /* string "SMM " */ #define MPI3_IMAGE_HEADER_SIGNATURE1_PSW (0x20575350) /* string "PSW " */ - +#define MPI3_IMAGE_HEADER_SIGNATURE1_CSW (0x20575343) /* string "CSW " */ /**** Definitions for Signature2 field ****/ #define MPI3_IMAGE_HEADER_SIGNATURE2_VALUE (0x50584546) /**** Definitions for Flags field ****/ +#define MPI3_IMAGE_HEADER_FLAGS_SIGNED_UEFI_MASK (0x00000300) +#define MPI3_IMAGE_HEADER_FLAGS_SIGNED_UEFI_UNSPECIFIED (0x00000000) +#define MPI3_IMAGE_HEADER_FLAGS_SIGNED_UEFI_NOT_SIGNED (0x00000100) +#define MPI3_IMAGE_HEADER_FLAGS_SIGNED_UEFI_MICROSOFT_SIGNED (0x00000200) +#define MPI3_IMAGE_HEADER_FLAGS_CERT_CHAIN_FORMAT_MASK (0x000000C0) +#define MPI3_IMAGE_HEADER_FLAGS_CERT_CHAIN_FORMAT_DEVICE_CERT (0x00000000) +#define MPI3_IMAGE_HEADER_FLAGS_CERT_CHAIN_FORMAT_ALIAS_CERT (0x00000040) #define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_MASK (0x00000030) #define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_CDI (0x00000000) #define MPI3_IMAGE_HEADER_FLAGS_DEVICE_KEY_BASIS_DI (0x00000010) #define MPI3_IMAGE_HEADER_FLAGS_SIGNED_NVDATA (0x00000008) #define MPI3_IMAGE_HEADER_FLAGS_REQUIRES_ACTIVATION (0x00000004) #define MPI3_IMAGE_HEADER_FLAGS_COMPRESSED (0x00000002) #define MPI3_IMAGE_HEADER_FLAGS_FLASH (0x00000001) /**** Offsets for Image Header Fields ****/ #define MPI3_IMAGE_HEADER_SIGNATURE0_OFFSET (0x00) #define MPI3_IMAGE_HEADER_LOAD_ADDRESS_OFFSET (0x04) #define MPI3_IMAGE_HEADER_DATA_SIZE_OFFSET (0x08) #define MPI3_IMAGE_HEADER_START_OFFSET_OFFSET (0x0C) #define MPI3_IMAGE_HEADER_SIGNATURE1_OFFSET (0x10) #define MPI3_IMAGE_HEADER_FLASH_OFFSET_OFFSET (0x14) #define MPI3_IMAGE_HEADER_FLASH_SIZE_OFFSET (0x18) #define MPI3_IMAGE_HEADER_VERSION_STRING_OFFSET_OFFSET (0x1C) #define MPI3_IMAGE_HEADER_BUILD_DATE_STRING_OFFSET_OFFSET (0x20) #define MPI3_IMAGE_HEADER_BUILD_TIME_OFFSET_OFFSET (0x24) #define MPI3_IMAGE_HEADER_ENVIROMENT_VAR_OFFSET_OFFSET (0x28) #define MPI3_IMAGE_HEADER_APPLICATION_SPECIFIC_OFFSET (0x2C) #define MPI3_IMAGE_HEADER_SIGNATURE2_OFFSET (0x30) #define MPI3_IMAGE_HEADER_HEADER_SIZE_OFFSET (0x34) #define MPI3_IMAGE_HEADER_CRC_OFFSET (0x38) #define MPI3_IMAGE_HEADER_FLAGS_OFFSET (0x3C) #define MPI3_IMAGE_HEADER_SECONDARY_FLASH_OFFSET_OFFSET (0x40) #define MPI3_IMAGE_HEADER_ETP_OFFSET_OFFSET (0x44) #define MPI3_IMAGE_HEADER_ETP_SIZE_OFFSET (0x48) #define MPI3_IMAGE_HEADER_RMC_INTERFACE_VER_OFFSET (0x4C) #define MPI3_IMAGE_HEADER_ETP_INTERFACE_VER_OFFSET (0x50) #define MPI3_IMAGE_HEADER_COMPONENT_IMAGE_VER_OFFSET (0x54) #define MPI3_IMAGE_HEADER_HASH_EXCLUSION_OFFSET (0x5C) #define MPI3_IMAGE_HEADER_NEXT_IMAGE_HEADER_OFFSET_OFFSET (0x7C) #define MPI3_IMAGE_HEADER_SIZE (0x100) /***************************************************************************** * Component Image Data * *****************************************************************************/ /* Package Manifest Data */ #ifndef MPI3_CI_MANIFEST_MPI_MAX #define MPI3_CI_MANIFEST_MPI_MAX (1) #endif /* MPI3_CI_MANIFEST_MPI_MAX */ typedef struct _MPI3_CI_MANIFEST_MPI_COMP_IMAGE_REF { U32 Signature1; /* 0x00 */ U32 Reserved04[3]; /* 0x04 */ MPI3_COMP_IMAGE_VERSION ComponentImageVersion; /* 0x10 */ U32 ComponentImageVersionStringOffset; /* 0x18 */ U32 CRC; /* 0x1C */ } MPI3_CI_MANIFEST_MPI_COMP_IMAGE_REF, MPI3_POINTER PTR_MPI3_CI_MANIFEST_MPI_COMP_IMAGE_REF, Mpi3CIManifestMpiCompImageRef_t, MPI3_POINTER pMpi3CIManifestMpiCompImageRef_t; typedef struct _MPI3_CI_MANIFEST_MPI { U8 ManifestType; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ U32 Reserved04[3]; /* 0x04 */ U8 NumImageReferences; /* 0x10 */ U8 ReleaseLevel; /* 0x11 */ U16 Reserved12; /* 0x12 */ U16 Reserved14; /* 0x14 */ U16 Flags; /* 0x16 */ U32 Reserved18[2]; /* 0x18 */ U16 VendorID; /* 0x20 */ U16 DeviceID; /* 0x22 */ U16 SubsystemVendorID; /* 0x24 */ U16 SubsystemID; /* 0x26 */ U32 Reserved28[2]; /* 0x28 */ MPI3_VERSION_UNION PackageSecurityVersion; /* 0x30 */ U32 Reserved34; /* 0x34 */ MPI3_COMP_IMAGE_VERSION PackageVersion; /* 0x38 */ U32 PackageVersionStringOffset; /* 0x40 */ U32 PackageBuildDateStringOffset; /* 0x44 */ U32 PackageBuildTimeStringOffset; /* 0x48 */ U32 Reserved4C; /* 0x4C */ U32 DiagAuthorizationIdentifier[16]; /* 0x50 */ MPI3_CI_MANIFEST_MPI_COMP_IMAGE_REF ComponentImageRef[MPI3_CI_MANIFEST_MPI_MAX]; /* 0x90 */ /* variable length */ /* StringData - offset of this field must be calculated */ /* variable length */ } MPI3_CI_MANIFEST_MPI, MPI3_POINTER PTR_MPI3_CI_MANIFEST_MPI, Mpi3CIManifestMpi_t, MPI3_POINTER pMpi3CIManifestMpi_t; /* defines for the ReleaseLevel field */ #define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_DEV (0x00) +#define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_PRE_PRODUCTION (0x08) #define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_PREALPHA (0x10) #define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_ALPHA (0x20) #define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_BETA (0x30) #define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_RC (0x40) #define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_GCA (0x50) #define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_POINT (0x60) +#define MPI3_CI_MANIFEST_MPI_RELEASE_LEVEL_DIAG (0xF0) /* defines for the Flags field */ #define MPI3_CI_MANIFEST_MPI_FLAGS_DIAG_AUTHORIZATION (0x01) /* defines for the SubsystemID field */ #define MPI3_CI_MANIFEST_MPI_SUBSYSTEMID_IGNORED (0xFFFF) /* defines for the PackageVersionStringOffset field */ #define MPI3_CI_MANIFEST_MPI_PKG_VER_STR_OFF_UNSPECIFIED (0x00000000) /* defines for the PackageBuildDateStringOffset field */ #define MPI3_CI_MANIFEST_MPI_PKG_BUILD_DATE_STR_OFF_UNSPECIFIED (0x00000000) /* defines for the PackageBuildTimeStringOffset field */ #define MPI3_CI_MANIFEST_MPI_PKG_BUILD_TIME_STR_OFF_UNSPECIFIED (0x00000000) typedef union _MPI3_CI_MANIFEST { MPI3_CI_MANIFEST_MPI Mpi; U32 Dword[1]; } MPI3_CI_MANIFEST, MPI3_POINTER PTR_MPI3_CI_MANIFEST, Mpi3CIManifest_t, MPI3_POINTER pMpi3CIManifest_t; /* defines for ManifestType field */ #define MPI3_CI_MANIFEST_TYPE_MPI (0x00) /***************************************************************************** * Extended Image Data * *****************************************************************************/ /* Extended Image Header */ typedef struct _MPI3_EXTENDED_IMAGE_HEADER { U8 ImageType; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ U32 Checksum; /* 0x04 */ U32 ImageSize; /* 0x08 */ U32 NextImageHeaderOffset; /* 0x0C */ U32 Reserved10[4]; /* 0x10 */ U32 IdentifyString[8]; /* 0x20 */ } MPI3_EXTENDED_IMAGE_HEADER, MPI3_POINTER PTR_MPI3_EXTENDED_IMAGE_HEADER, Mpi3ExtendedImageHeader_t, MPI3_POINTER pMpi3ExtendedImageHeader_t; /* useful offsets */ #define MPI3_EXT_IMAGE_IMAGETYPE_OFFSET (0x00) #define MPI3_EXT_IMAGE_IMAGESIZE_OFFSET (0x08) #define MPI3_EXT_IMAGE_NEXTIMAGE_OFFSET (0x0C) #define MPI3_EXT_IMAGE_HEADER_SIZE (0x40) /* defines for the ImageType field */ #define MPI3_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) #define MPI3_EXT_IMAGE_TYPE_NVDATA (0x03) #define MPI3_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07) #define MPI3_EXT_IMAGE_TYPE_ENCRYPTED_HASH (0x09) #define MPI3_EXT_IMAGE_TYPE_RDE (0x0A) #define MPI3_EXT_IMAGE_TYPE_AUXILIARY_PROCESSOR (0x0B) #define MPI3_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC (0x80) #define MPI3_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC (0xFF) /* Supported Device Data Format */ typedef struct _MPI3_SUPPORTED_DEVICE { U16 DeviceID; /* 0x00 */ U16 VendorID; /* 0x02 */ U16 DeviceIDMask; /* 0x04 */ U16 Reserved06; /* 0x06 */ U8 LowPCIRev; /* 0x08 */ U8 HighPCIRev; /* 0x09 */ U16 Reserved0A; /* 0x0A */ U32 Reserved0C; /* 0x0C */ } MPI3_SUPPORTED_DEVICE, MPI3_POINTER PTR_MPI3_SUPPORTED_DEVICE, Mpi3SupportedDevice_t, MPI3_POINTER pMpi3SupportedDevice_t; #ifndef MPI3_SUPPORTED_DEVICE_MAX #define MPI3_SUPPORTED_DEVICE_MAX (1) #endif /* MPI3_SUPPORTED_DEVICE_MAX */ /* Supported Devices Extended Image Data */ typedef struct _MPI3_SUPPORTED_DEVICES_DATA { U8 ImageVersion; /* 0x00 */ U8 Reserved01; /* 0x01 */ U8 NumDevices; /* 0x02 */ U8 Reserved03; /* 0x03 */ U32 Reserved04; /* 0x04 */ MPI3_SUPPORTED_DEVICE SupportedDevice[MPI3_SUPPORTED_DEVICE_MAX]; /* 0x08 */ /* variable length */ } MPI3_SUPPORTED_DEVICES_DATA, MPI3_POINTER PTR_MPI3_SUPPORTED_DEVICES_DATA, Mpi3SupportedDevicesData_t, MPI3_POINTER pMpi3SupportedDevicesData_t; -#ifndef MPI3_ENCRYPTED_HASH_MAX -#define MPI3_ENCRYPTED_HASH_MAX (1) -#endif /* MPI3_ENCRYPTED_HASH_MAX */ +#ifndef MPI3_PUBLIC_KEY_MAX +#define MPI3_PUBLIC_KEY_MAX (1) +#endif /* MPI3_PUBLIC_KEY_MAX */ /* Encrypted Hash Entry Format */ typedef struct _MPI3_ENCRYPTED_HASH_ENTRY { U8 HashImageType; /* 0x00 */ U8 HashAlgorithm; /* 0x01 */ U8 EncryptionAlgorithm; /* 0x02 */ U8 Reserved03; /* 0x03 */ - U32 Reserved04; /* 0x04 */ - U32 EncryptedHash[MPI3_ENCRYPTED_HASH_MAX]; /* 0x08 */ /* variable length */ + U16 PublicKeySize; /* 0x04 */ + U16 SignatureSize; /* 0x06 */ + U32 PublicKey[MPI3_PUBLIC_KEY_MAX]; /* 0x08 */ /* variable length */ + /* Signature - offset of this field must be calculated */ /* variable length */ } MPI3_ENCRYPTED_HASH_ENTRY, MPI3_POINTER PTR_MPI3_ENCRYPTED_HASH_ENTRY, Mpi3EncryptedHashEntry_t, MPI3_POINTER pMpi3EncryptedHashEntry_t; /* defines for the HashImageType field */ #define MPI3_HASH_IMAGE_TYPE_KEY_WITH_SIGNATURE (0x03) /* defines for the HashAlgorithm field */ #define MPI3_HASH_ALGORITHM_VERSION_MASK (0xE0) #define MPI3_HASH_ALGORITHM_VERSION_NONE (0x00) #define MPI3_HASH_ALGORITHM_VERSION_SHA1 (0x20) /* Obsolete */ #define MPI3_HASH_ALGORITHM_VERSION_SHA2 (0x40) #define MPI3_HASH_ALGORITHM_VERSION_SHA3 (0x60) #define MPI3_HASH_ALGORITHM_SIZE_MASK (0x1F) #define MPI3_HASH_ALGORITHM_SIZE_UNUSED (0x00) #define MPI3_HASH_ALGORITHM_SIZE_SHA256 (0x01) #define MPI3_HASH_ALGORITHM_SIZE_SHA512 (0x02) #define MPI3_HASH_ALGORITHM_SIZE_SHA384 (0x03) /* defines for the EncryptionAlgorithm field */ #define MPI3_ENCRYPTION_ALGORITHM_UNUSED (0x00) #define MPI3_ENCRYPTION_ALGORITHM_RSA256 (0x01) /* Obsolete */ #define MPI3_ENCRYPTION_ALGORITHM_RSA512 (0x02) /* Obsolete */ #define MPI3_ENCRYPTION_ALGORITHM_RSA1024 (0x03) /* Obsolete */ #define MPI3_ENCRYPTION_ALGORITHM_RSA2048 (0x04) #define MPI3_ENCRYPTION_ALGORITHM_RSA4096 (0x05) #define MPI3_ENCRYPTION_ALGORITHM_RSA3072 (0x06) #define MPI3_ENCRYPTION_ALGORITHM_ECDSA_P256 (0x07) /* NIST secp256r1 curve */ #define MPI3_ENCRYPTION_ALGORITHM_ECDSA_P384 (0x08) /* NIST secp384r1 curve */ #define MPI3_ENCRYPTION_ALGORITHM_ECDSA_P521 (0x09) /* NIST secp521r1 curve */ - - -#ifndef MPI3_PUBLIC_KEY_MAX -#define MPI3_PUBLIC_KEY_MAX (1) -#endif /* MPI3_PUBLIC_KEY_MAX */ - -/* Encrypted Key with Hash Entry Format */ -typedef struct _MPI3_ENCRYPTED_KEY_WITH_HASH_ENTRY -{ - U8 HashImageType; /* 0x00 */ - U8 HashAlgorithm; /* 0x01 */ - U8 EncryptionAlgorithm; /* 0x02 */ - U8 Reserved03; /* 0x03 */ - U32 Reserved04; /* 0x04 */ - U32 PublicKey[MPI3_PUBLIC_KEY_MAX]; /* 0x08 */ /* variable length */ - /* EncryptedHash - offset of this field must be calculated */ /* variable length */ -} MPI3_ENCRYPTED_KEY_WITH_HASH_ENTRY, MPI3_POINTER PTR_MPI3_ENCRYPTED_KEY_WITH_HASH_ENTRY, - Mpi3EncryptedKeyWithHashEntry_t, MPI3_POINTER pMpi3EncryptedKeyWithHashEntry_t; +#define MPI3_ENCRYPTION_ALGORITHM_LMS_HSS (0x0A) /* Leighton-Micali Signature (LMS) - + * Hierarchical Signature System (HSS) + */ #ifndef MPI3_ENCRYPTED_HASH_ENTRY_MAX #define MPI3_ENCRYPTED_HASH_ENTRY_MAX (1) #endif /* MPI3_ENCRYPTED_HASH_ENTRY_MAX */ /* Encrypted Hash Image Data */ typedef struct _MPI3_ENCRYPTED_HASH_DATA { U8 ImageVersion; /* 0x00 */ U8 NumHash; /* 0x01 */ U16 Reserved02; /* 0x02 */ U32 Reserved04; /* 0x04 */ MPI3_ENCRYPTED_HASH_ENTRY EncryptedHashEntry[MPI3_ENCRYPTED_HASH_ENTRY_MAX]; /* 0x08 */ /* variable length */ } MPI3_ENCRYPTED_HASH_DATA, MPI3_POINTER PTR_MPI3_ENCRYPTED_HASH_DATA, Mpi3EncryptedHashData_t, MPI3_POINTER pMpi3EncryptedHashData_t; #ifndef MPI3_AUX_PROC_DATA_MAX #define MPI3_AUX_PROC_DATA_MAX (1) #endif /* MPI3_ENCRYPTED_HASH_ENTRY_MAX */ /* Auxiliary Processor Extended Image Data */ typedef struct _MPI3_AUX_PROCESSOR_DATA { U8 BootMethod; /* 0x00 */ U8 NumLoadAddr; /* 0x01 */ U8 Reserved02; /* 0x02 */ U8 Type; /* 0x03 */ U32 Version; /* 0x04 */ U32 LoadAddress[8]; /* 0x08 */ U32 Reserved28[22]; /* 0x28 */ U32 AuxProcessorData[MPI3_AUX_PROC_DATA_MAX]; /* 0x80 */ /* variable length */ } MPI3_AUX_PROCESSOR_DATA, MPI3_POINTER PTR_MPI3_AUX_PROCESSOR_DATA, Mpi3AuxProcessorData_t, MPI3_POINTER pMpi3AuxProcessorData_t; #define MPI3_AUX_PROC_DATA_OFFSET (0x80) /* defines for the BootMethod field */ #define MPI3_AUXPROCESSOR_BOOT_METHOD_MO_MSG (0x00) #define MPI3_AUXPROCESSOR_BOOT_METHOD_MO_DOORBELL (0x01) #define MPI3_AUXPROCESSOR_BOOT_METHOD_COMPONENT (0x02) /* defines for the Type field */ #define MPI3_AUXPROCESSOR_TYPE_ARM_A15 (0x00) #define MPI3_AUXPROCESSOR_TYPE_ARM_M0 (0x01) #define MPI3_AUXPROCESSOR_TYPE_ARM_R4 (0x02) #endif /* MPI30_IMAGE_H */ diff --git a/sys/dev/mpi3mr/mpi/mpi30_init.h b/sys/dev/mpi3mr/mpi/mpi30_init.h index c0ba14909ac1..361fb690fbe6 100644 --- a/sys/dev/mpi3mr/mpi/mpi30_init.h +++ b/sys/dev/mpi3mr/mpi/mpi30_init.h @@ -1,265 +1,266 @@ /* - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. + * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved. * Support: * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD * */ - #ifndef MPI30_INIT_H #define MPI30_INIT_H 1 /***************************************************************************** * SCSI Initiator Messages * ****************************************************************************/ /***************************************************************************** * SCSI IO Request Message * ****************************************************************************/ typedef struct _MPI3_SCSI_IO_CDB_EEDP32 { U8 CDB[20]; /* 0x00 */ U32 PrimaryReferenceTag; /* 0x14 */ U16 PrimaryApplicationTag; /* 0x18 */ U16 PrimaryApplicationTagMask; /* 0x1A */ U32 TransferLength; /* 0x1C */ } MPI3_SCSI_IO_CDB_EEDP32, MPI3_POINTER PTR_MPI3_SCSI_IO_CDB_EEDP32, Mpi3ScsiIoCdbEedp32_t, MPI3_POINTER pMpi3ScsiIoCdbEedp32_t; typedef union _MPI3_SCSI_IO_CDB_UNION { U8 CDB32[32]; MPI3_SCSI_IO_CDB_EEDP32 EEDP32; MPI3_SGE_SIMPLE SGE; } MPI3_SCSI_IO_CDB_UNION, MPI3_POINTER PTR_MPI3_SCSI_IO_CDB_UNION, Mpi3ScsiIoCdb_t, MPI3_POINTER pMpi3ScsiIoCdb_t; typedef struct _MPI3_SCSI_IO_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 DevHandle; /* 0x0A */ U32 Flags; /* 0x0C */ - U32 SkipCount; /* 0x10 */ + U32 IOCUseOnly10; /* 0x10 */ U32 DataLength; /* 0x14 */ U8 LUN[8]; /* 0x18 */ MPI3_SCSI_IO_CDB_UNION CDB; /* 0x20 */ MPI3_SGE_UNION SGL[4]; /* 0x40 */ } MPI3_SCSI_IO_REQUEST, MPI3_POINTER PTR_MPI3_SCSI_IO_REQUEST, Mpi3SCSIIORequest_t, MPI3_POINTER pMpi3SCSIIORequest_t; /**** Defines for the MsgFlags field ****/ #define MPI3_SCSIIO_MSGFLAGS_METASGL_VALID (0x80) #define MPI3_SCSIIO_MSGFLAGS_DIVERT_TO_FIRMWARE (0x40) /**** Defines for the Flags field ****/ -#define MPI3_SCSIIO_FLAGS_LARGE_CDB (0x60000000) +#define MPI3_SCSIIO_FLAGS_LARGE_CDB_MASK (0x60000000) #define MPI3_SCSIIO_FLAGS_CDB_16_OR_LESS (0x00000000) #define MPI3_SCSIIO_FLAGS_CDB_GREATER_THAN_16 (0x20000000) #define MPI3_SCSIIO_FLAGS_CDB_IN_SEPARATE_BUFFER (0x40000000) +#define MPI3_SCSIIO_FLAGS_CDB_PRODUCT_SPECIFIC (0x60000000) +#define MPI3_SCSIIO_FLAGS_IOC_USE_ONLY_27_MASK (0x18000000) #define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_MASK (0x07000000) #define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_SIMPLEQ (0x00000000) #define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_HEADOFQ (0x01000000) #define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_ORDEREDQ (0x02000000) #define MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_ACAQ (0x04000000) #define MPI3_SCSIIO_FLAGS_CMDPRI_MASK (0x00F00000) #define MPI3_SCSIIO_FLAGS_CMDPRI_SHIFT (20) #define MPI3_SCSIIO_FLAGS_DATADIRECTION_MASK (0x000C0000) #define MPI3_SCSIIO_FLAGS_DATADIRECTION_NO_DATA_TRANSFER (0x00000000) #define MPI3_SCSIIO_FLAGS_DATADIRECTION_WRITE (0x00040000) #define MPI3_SCSIIO_FLAGS_DATADIRECTION_READ (0x00080000) #define MPI3_SCSIIO_FLAGS_DMAOPERATION_MASK (0x00030000) #define MPI3_SCSIIO_FLAGS_DMAOPERATION_HOST_PI (0x00010000) #define MPI3_SCSIIO_FLAGS_DIVERT_REASON_MASK (0x000000F0) #define MPI3_SCSIIO_FLAGS_DIVERT_REASON_IO_THROTTLING (0x00000010) #define MPI3_SCSIIO_FLAGS_DIVERT_REASON_WRITE_SAME_TOO_LARGE (0x00000020) #define MPI3_SCSIIO_FLAGS_DIVERT_REASON_PROD_SPECIFIC (0x00000080) /**** Defines for the SGL field ****/ #define MPI3_SCSIIO_METASGL_INDEX (3) /***************************************************************************** * SCSI IO Error Reply Message * ****************************************************************************/ typedef struct _MPI3_SCSI_IO_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U8 SCSIStatus; /* 0x10 */ U8 SCSIState; /* 0x11 */ U16 DevHandle; /* 0x12 */ U32 TransferCount; /* 0x14 */ U32 SenseCount; /* 0x18 */ U32 ResponseData; /* 0x1C */ U16 TaskTag; /* 0x20 */ U16 SCSIStatusQualifier; /* 0x22 */ U32 EEDPErrorOffset; /* 0x24 */ U16 EEDPObservedAppTag; /* 0x28 */ U16 EEDPObservedGuard; /* 0x2A */ U32 EEDPObservedRefTag; /* 0x2C */ U64 SenseDataBufferAddress; /* 0x30 */ } MPI3_SCSI_IO_REPLY, MPI3_POINTER PTR_MPI3_SCSI_IO_REPLY, Mpi3SCSIIOReply_t, MPI3_POINTER pMpi3SCSIIOReply_t; /**** Defines for the MsgFlags field ****/ #define MPI3_SCSIIO_REPLY_MSGFLAGS_REFTAG_OBSERVED_VALID (0x01) #define MPI3_SCSIIO_REPLY_MSGFLAGS_APPTAG_OBSERVED_VALID (0x02) #define MPI3_SCSIIO_REPLY_MSGFLAGS_GUARD_OBSERVED_VALID (0x04) /**** Defines for the SCSIStatus field ****/ #define MPI3_SCSI_STATUS_GOOD (0x00) #define MPI3_SCSI_STATUS_CHECK_CONDITION (0x02) #define MPI3_SCSI_STATUS_CONDITION_MET (0x04) #define MPI3_SCSI_STATUS_BUSY (0x08) #define MPI3_SCSI_STATUS_INTERMEDIATE (0x10) #define MPI3_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14) #define MPI3_SCSI_STATUS_RESERVATION_CONFLICT (0x18) #define MPI3_SCSI_STATUS_COMMAND_TERMINATED (0x22) #define MPI3_SCSI_STATUS_TASK_SET_FULL (0x28) #define MPI3_SCSI_STATUS_ACA_ACTIVE (0x30) #define MPI3_SCSI_STATUS_TASK_ABORTED (0x40) /**** Defines for the SCSIState field ****/ #define MPI3_SCSI_STATE_SENSE_MASK (0x03) #define MPI3_SCSI_STATE_SENSE_VALID (0x00) #define MPI3_SCSI_STATE_SENSE_FAILED (0x01) #define MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY (0x02) #define MPI3_SCSI_STATE_SENSE_NOT_AVAILABLE (0x03) #define MPI3_SCSI_STATE_NO_SCSI_STATUS (0x04) #define MPI3_SCSI_STATE_TERMINATED (0x08) #define MPI3_SCSI_STATE_RESPONSE_DATA_VALID (0x10) /**** Defines for the ResponseData field ****/ #define MPI3_SCSI_RSP_RESPONSECODE_MASK (0x000000FF) #define MPI3_SCSI_RSP_RESPONSECODE_SHIFT (0) #define MPI3_SCSI_RSP_ARI2_MASK (0x0000FF00) #define MPI3_SCSI_RSP_ARI2_SHIFT (8) #define MPI3_SCSI_RSP_ARI1_MASK (0x00FF0000) #define MPI3_SCSI_RSP_ARI1_SHIFT (16) #define MPI3_SCSI_RSP_ARI0_MASK (0xFF000000) #define MPI3_SCSI_RSP_ARI0_SHIFT (24) /**** Defines for the TaskTag field ****/ #define MPI3_SCSI_TASKTAG_UNKNOWN (0xFFFF) /***************************************************************************** * SCSI Task Management Request Message * ****************************************************************************/ typedef struct _MPI3_SCSI_TASK_MGMT_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 DevHandle; /* 0x0A */ U16 TaskHostTag; /* 0x0C */ U8 TaskType; /* 0x0E */ U8 Reserved0F; /* 0x0F */ U16 TaskRequestQueueID; /* 0x10 */ U8 IOCUseOnly12; /* 0x12 */ U8 Reserved13; /* 0x13 */ U32 Reserved14; /* 0x14 */ U8 LUN[8]; /* 0x18 */ } MPI3_SCSI_TASK_MGMT_REQUEST, MPI3_POINTER PTR_MPI3_SCSI_TASK_MGMT_REQUEST, Mpi3SCSITaskMgmtRequest_t, MPI3_POINTER pMpi3SCSITaskMgmtRequest_t; /**** Defines for the MsgFlags field ****/ #define MPI3_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x08) /**** Defines for the TaskType field ****/ #define MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01) #define MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK_SET (0x02) #define MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03) #define MPI3_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) #define MPI3_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) #define MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) #define MPI3_SCSITASKMGMT_TASKTYPE_CLEAR_ACA (0x08) #define MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK_SET (0x09) #define MPI3_SCSITASKMGMT_TASKTYPE_QUERY_ASYNC_EVENT (0x0A) #define MPI3_SCSITASKMGMT_TASKTYPE_I_T_NEXUS_RESET (0x0B) /***************************************************************************** * SCSI Task Management Reply Message * ****************************************************************************/ typedef struct _MPI3_SCSI_TASK_MGMT_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U32 TerminationCount; /* 0x10 */ U32 ResponseData; /* 0x14 */ U32 Reserved18; /* 0x18 */ } MPI3_SCSI_TASK_MGMT_REPLY, MPI3_POINTER PTR_MPI3_SCSI_TASK_MGMT_REPLY, Mpi3SCSITaskMgmtReply_t, MPI3_POINTER pMpi3SCSITaskMgmtReply_t; /**** Defines for the ResponseData field - use MPI3_SCSI_RSP_ defines ****/ /**** Defines for the ResponseCode field - Byte 0 of ResponseData ****/ #define MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE (0x00) #define MPI3_SCSITASKMGMT_RSPCODE_INVALID_FRAME (0x02) #define MPI3_SCSITASKMGMT_RSPCODE_TM_FUNCTION_NOT_SUPPORTED (0x04) #define MPI3_SCSITASKMGMT_RSPCODE_TM_FAILED (0x05) #define MPI3_SCSITASKMGMT_RSPCODE_TM_SUCCEEDED (0x08) #define MPI3_SCSITASKMGMT_RSPCODE_TM_INVALID_LUN (0x09) #define MPI3_SCSITASKMGMT_RSPCODE_TM_OVERLAPPED_TAG (0x0A) #define MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC (0x80) #define MPI3_SCSITASKMGMT_RSPCODE_TM_NVME_DENIED (0x81) #endif /* MPI30_INIT_H */ diff --git a/sys/dev/mpi3mr/mpi/mpi30_ioc.h b/sys/dev/mpi3mr/mpi/mpi30_ioc.h index 77f6be5b2694..2d45a55b89e8 100644 --- a/sys/dev/mpi3mr/mpi/mpi30_ioc.h +++ b/sys/dev/mpi3mr/mpi/mpi30_ioc.h @@ -1,1615 +1,1625 @@ /* - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. + * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved. * Support: * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD * */ - #ifndef MPI30_IOC_H #define MPI30_IOC_H 1 /***************************************************************************** * IOC Messages * ****************************************************************************/ /***************************************************************************** * IOCInit Request Message * ****************************************************************************/ typedef struct _MPI3_IOC_INIT_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 Reserved0A; /* 0x0A */ MPI3_VERSION_UNION MPIVersion; /* 0x0C */ U64 TimeStamp; /* 0x10 */ U8 Reserved18; /* 0x18 */ U8 WhoInit; /* 0x19 */ U16 Reserved1A; /* 0x1A */ U16 ReplyFreeQueueDepth; /* 0x1C */ U16 Reserved1E; /* 0x1E */ U64 ReplyFreeQueueAddress; /* 0x20 */ U32 Reserved28; /* 0x28 */ U16 SenseBufferFreeQueueDepth; /* 0x2C */ U16 SenseBufferLength; /* 0x2E */ U64 SenseBufferFreeQueueAddress; /* 0x30 */ U64 DriverInformationAddress; /* 0x38 */ } MPI3_IOC_INIT_REQUEST, MPI3_POINTER PTR_MPI3_IOC_INIT_REQUEST, Mpi3IOCInitRequest_t, MPI3_POINTER pMpi3IOCInitRequest_t; /**** Defines for the MsgFlags field ****/ -#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_MASK (0x03) -#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_NOT_USED (0x00) -#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_SEPARATED (0x01) -#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_INLINE (0x02) -#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_BOTH (0x03) +#define MPI3_IOCINIT_MSGFLAGS_WRITESAMEDIVERT_SUPPORTED (0x08) +#define MPI3_IOCINIT_MSGFLAGS_SCSIIOSTATUSREPLY_SUPPORTED (0x04) +#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_MASK (0x03) +#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_NOT_USED (0x00) +#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_SEPARATED (0x01) +#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_INLINE (0x02) +#define MPI3_IOCINIT_MSGFLAGS_HOSTMETADATA_BOTH (0x03) /**** Defines for the WhoInit field ****/ -#define MPI3_WHOINIT_NOT_INITIALIZED (0x00) -#define MPI3_WHOINIT_ROM_BIOS (0x02) -#define MPI3_WHOINIT_HOST_DRIVER (0x03) -#define MPI3_WHOINIT_MANUFACTURER (0x04) +#define MPI3_WHOINIT_NOT_INITIALIZED (0x00) +#define MPI3_WHOINIT_ROM_BIOS (0x02) +#define MPI3_WHOINIT_HOST_DRIVER (0x03) +#define MPI3_WHOINIT_MANUFACTURER (0x04) /**** Defines for the DriverInformationAddress field */ typedef struct _MPI3_DRIVER_INFO_LAYOUT { U32 InformationLength; /* 0x00 */ U8 DriverSignature[12]; /* 0x04 */ U8 OsName[16]; /* 0x10 */ U8 OsVersion[12]; /* 0x20 */ U8 DriverName[20]; /* 0x2C */ U8 DriverVersion[32]; /* 0x40 */ U8 DriverReleaseDate[20]; /* 0x60 */ U32 DriverCapabilities; /* 0x74 */ } MPI3_DRIVER_INFO_LAYOUT, MPI3_POINTER PTR_MPI3_DRIVER_INFO_LAYOUT, Mpi3DriverInfoLayout_t, MPI3_POINTER pMpi3DriverInfoLayout_t; /***************************************************************************** * IOCFacts Request Message * ****************************************************************************/ typedef struct _MPI3_IOC_FACTS_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U32 Reserved0C; /* 0x0C */ MPI3_SGE_UNION SGL; /* 0x10 */ } MPI3_IOC_FACTS_REQUEST, MPI3_POINTER PTR_MPI3_IOC_FACTS_REQUEST, Mpi3IOCFactsRequest_t, MPI3_POINTER pMpi3IOCFactsRequest_t; /***************************************************************************** * IOCFacts Data * ****************************************************************************/ typedef struct _MPI3_IOC_FACTS_DATA { U16 IOCFactsDataLength; /* 0x00 */ U16 Reserved02; /* 0x02 */ MPI3_VERSION_UNION MPIVersion; /* 0x04 */ MPI3_COMP_IMAGE_VERSION FWVersion; /* 0x08 */ U32 IOCCapabilities; /* 0x10 */ U8 IOCNumber; /* 0x14 */ U8 WhoInit; /* 0x15 */ U16 MaxMSIxVectors; /* 0x16 */ U16 MaxOutstandingRequests; /* 0x18 */ U16 ProductID; /* 0x1A */ U16 IOCRequestFrameSize; /* 0x1C */ U16 ReplyFrameSize; /* 0x1E */ U16 IOCExceptions; /* 0x20 */ U16 MaxPersistentID; /* 0x22 */ U8 SGEModifierMask; /* 0x24 */ U8 SGEModifierValue; /* 0x25 */ U8 SGEModifierShift; /* 0x26 */ U8 ProtocolFlags; /* 0x27 */ U16 MaxSASInitiators; /* 0x28 */ U16 MaxDataLength; /* 0x2A */ U16 MaxSASExpanders; /* 0x2C */ U16 MaxEnclosures; /* 0x2E */ U16 MinDevHandle; /* 0x30 */ U16 MaxDevHandle; /* 0x32 */ U16 MaxPCIeSwitches; /* 0x34 */ U16 MaxNVMe; /* 0x36 */ U16 Reserved38; /* 0x38 */ U16 MaxVDs; /* 0x3A */ U16 MaxHostPDs; /* 0x3C */ U16 MaxAdvHostPDs; /* 0x3E */ U16 MaxRAIDPDs; /* 0x40 */ U16 MaxPostedCmdBuffers; /* 0x42 */ U32 Flags; /* 0x44 */ U16 MaxOperationalRequestQueues; /* 0x48 */ U16 MaxOperationalReplyQueues; /* 0x4A */ U16 ShutdownTimeout; /* 0x4C */ U16 Reserved4E; /* 0x4E */ U32 DiagTraceSize; /* 0x50 */ U32 DiagFwSize; /* 0x54 */ U32 DiagDriverSize; /* 0x58 */ U8 MaxHostPDNsCount; /* 0x5C */ U8 MaxAdvHostPDNsCount; /* 0x5D */ U8 MaxRAIDPDNsCount; /* 0x5E */ U8 MaxDevicesPerThrottleGroup; /* 0x5F */ U16 IOThrottleDataLength; /* 0x60 */ U16 MaxIOThrottleGroup; /* 0x62 */ U16 IOThrottleLow; /* 0x64 */ U16 IOThrottleHigh; /* 0x66 */ + U32 DiagFdlSize; /* 0x68 */ + U32 DiagTtySize; /* 0x6C */ } MPI3_IOC_FACTS_DATA, MPI3_POINTER PTR_MPI3_IOC_FACTS_DATA, Mpi3IOCFactsData_t, MPI3_POINTER pMpi3IOCFactsData_t; /**** Defines for the IOCCapabilities field ****/ #define MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_MASK (0x80000000) #define MPI3_IOCFACTS_CAPABILITY_SUPERVISOR_IOC (0x00000000) #define MPI3_IOCFACTS_CAPABILITY_NON_SUPERVISOR_IOC (0x80000000) #define MPI3_IOCFACTS_CAPABILITY_INT_COALESCE_MASK (0x00000600) #define MPI3_IOCFACTS_CAPABILITY_INT_COALESCE_FIXED_THRESHOLD (0x00000000) #define MPI3_IOCFACTS_CAPABILITY_INT_COALESCE_OUTSTANDING_IO (0x00000200) -#define MPI3_IOCFACTS_CAPABILITY_COMPLETE_RESET_CAPABLE (0x00000100) -#define MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_TRACE_ENABLED (0x00000080) -#define MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_FW_ENABLED (0x00000040) -#define MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_DRIVER_ENABLED (0x00000020) -#define MPI3_IOCFACTS_CAPABILITY_ADVANCED_HOST_PD_ENABLED (0x00000010) -#define MPI3_IOCFACTS_CAPABILITY_RAID_CAPABLE (0x00000008) -#define MPI3_IOCFACTS_CAPABILITY_MULTIPATH_ENABLED (0x00000002) +#define MPI3_IOCFACTS_CAPABILITY_COMPLETE_RESET_SUPPORTED (0x00000100) +#define MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_TRACE_SUPPORTED (0x00000080) +#define MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_FW_SUPPORTED (0x00000040) +#define MPI3_IOCFACTS_CAPABILITY_SEG_DIAG_DRIVER_SUPPORTED (0x00000020) +#define MPI3_IOCFACTS_CAPABILITY_ADVANCED_HOST_PD_SUPPORTED (0x00000010) +#define MPI3_IOCFACTS_CAPABILITY_RAID_SUPPORTED (0x00000008) +#define MPI3_IOCFACTS_CAPABILITY_MULTIPATH_SUPPORTED (0x00000002) #define MPI3_IOCFACTS_CAPABILITY_COALESCE_CTRL_SUPPORTED (0x00000001) /**** WhoInit values are defined under IOCInit Request Message definition ****/ /**** Defines for the ProductID field ****/ #define MPI3_IOCFACTS_PID_TYPE_MASK (0xF000) #define MPI3_IOCFACTS_PID_TYPE_SHIFT (12) #define MPI3_IOCFACTS_PID_PRODUCT_MASK (0x0F00) #define MPI3_IOCFACTS_PID_PRODUCT_SHIFT (8) #define MPI3_IOCFACTS_PID_FAMILY_MASK (0x00FF) #define MPI3_IOCFACTS_PID_FAMILY_SHIFT (0) /**** Defines for the IOCExceptions field ****/ #define MPI3_IOCFACTS_EXCEPT_SECURITY_REKEY (0x2000) #define MPI3_IOCFACTS_EXCEPT_SAS_DISABLED (0x1000) #define MPI3_IOCFACTS_EXCEPT_SAFE_MODE (0x0800) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_MASK (0x0700) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_NONE (0x0000) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_LOCAL_VIA_MGMT (0x0100) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_EXT_VIA_MGMT (0x0200) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_DRIVE_EXT_VIA_MGMT (0x0300) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_LOCAL_VIA_OOB (0x0400) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_EXT_VIA_OOB (0x0500) #define MPI3_IOCFACTS_EXCEPT_SECURITY_KEY_DRIVE_EXT_VIA_OOB (0x0600) #define MPI3_IOCFACTS_EXCEPT_PCIE_DISABLED (0x0080) #define MPI3_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE (0x0040) #define MPI3_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0020) #define MPI3_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0010) #define MPI3_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0008) #define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x0001) #define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_PRIMARY (0x0000) #define MPI3_IOCFACTS_EXCEPT_BOOTSTAT_SECONDARY (0x0001) /**** Defines for the ProtocolFlags field ****/ #define MPI3_IOCFACTS_PROTOCOL_SAS (0x0010) #define MPI3_IOCFACTS_PROTOCOL_SATA (0x0008) #define MPI3_IOCFACTS_PROTOCOL_NVME (0x0004) #define MPI3_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002) #define MPI3_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001) /**** Defines for the MaxDataLength field ****/ #define MPI3_IOCFACTS_MAX_DATA_LENGTH_NOT_REPORTED (0x0000) /**** Defines for the Flags field ****/ -#define MPI3_IOCFACTS_FLAGS_SIGNED_NVDATA_REQUIRED (0x00010000) -#define MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK (0x0000FF00) -#define MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT (8) -#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_MASK (0x00000030) -#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_NOT_STARTED (0x00000000) -#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_IN_PROGRESS (0x00000010) -#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_COMPLETE (0x00000020) -#define MPI3_IOCFACTS_FLAGS_PERSONALITY_MASK (0x0000000F) -#define MPI3_IOCFACTS_FLAGS_PERSONALITY_EHBA (0x00000000) -#define MPI3_IOCFACTS_FLAGS_PERSONALITY_RAID_DDR (0x00000002) +#define MPI3_IOCFACTS_FLAGS_SIGNED_NVDATA_REQUIRED (0x00010000) +#define MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK (0x0000FF00) +#define MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT (8) +#define MPI3_IOCFACTS_FLAGS_MAX_REQ_PER_REPLY_QUEUE_LIMIT (0x00000040) +#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_MASK (0x00000030) +#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_NOT_STARTED (0x00000000) +#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_IN_PROGRESS (0x00000010) +#define MPI3_IOCFACTS_FLAGS_INITIAL_PORT_ENABLE_COMPLETE (0x00000020) +#define MPI3_IOCFACTS_FLAGS_PERSONALITY_MASK (0x0000000F) +#define MPI3_IOCFACTS_FLAGS_PERSONALITY_EHBA (0x00000000) +#define MPI3_IOCFACTS_FLAGS_PERSONALITY_RAID_DDR (0x00000002) /**** Defines for the IOThrottleDataLength field ****/ -#define MPI3_IOCFACTS_IO_THROTTLE_DATA_LENGTH_NOT_REQUIRED (0x0000) +#define MPI3_IOCFACTS_IO_THROTTLE_DATA_LENGTH_NOT_REQUIRED (0x0000) -/**** Defines for the IOThrottleDataLength field ****/ -#define MPI3_IOCFACTS_MAX_IO_THROTTLE_GROUP_NOT_REQUIRED (0x0000) +/**** Defines for the MaxIOThrottleGroup field ****/ +#define MPI3_IOCFACTS_MAX_IO_THROTTLE_GROUP_NOT_REQUIRED (0x0000) + +/**** Defines for the DiagFdlSize field ****/ +#define MPI3_IOCFACTS_DIAGFDLSIZE_NOT_SUPPORTED (0x00000000) + +/**** Defines for the DiagTtySize field ****/ +#define MPI3_IOCFACTS_DIAGTTYSIZE_NOT_SUPPORTED (0x00000000) /***************************************************************************** * Management Passthrough Request Message * ****************************************************************************/ typedef struct _MPI3_MGMT_PASSTHROUGH_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U32 Reserved0C[5]; /* 0x0C */ MPI3_SGE_UNION CommandSGL; /* 0x20 */ MPI3_SGE_UNION ResponseSGL; /* 0x30 */ } MPI3_MGMT_PASSTHROUGH_REQUEST, MPI3_POINTER PTR_MPI3_MGMT_PASSTHROUGH_REQUEST, Mpi3MgmtPassthroughRequest_t, MPI3_POINTER pMpi3MgmtPassthroughRequest_t; /***************************************************************************** * CreateRequestQueue Request Message * ****************************************************************************/ typedef struct _MPI3_CREATE_REQUEST_QUEUE_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Flags; /* 0x0A */ U8 Burst; /* 0x0B */ U16 Size; /* 0x0C */ U16 QueueID; /* 0x0E */ U16 ReplyQueueID; /* 0x10 */ U16 Reserved12; /* 0x12 */ U32 Reserved14; /* 0x14 */ U64 BaseAddress; /* 0x18 */ } MPI3_CREATE_REQUEST_QUEUE_REQUEST, MPI3_POINTER PTR_MPI3_CREATE_REQUEST_QUEUE_REQUEST, Mpi3CreateRequestQueueRequest_t, MPI3_POINTER pMpi3CreateRequestQueueRequest_t; /**** Defines for the Flags field ****/ #define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_MASK (0x80) #define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_SEGMENTED (0x80) #define MPI3_CREATE_REQUEST_QUEUE_FLAGS_SEGMENTED_CONTIGUOUS (0x00) /**** Defines for the Size field ****/ #define MPI3_CREATE_REQUEST_QUEUE_SIZE_MINIMUM (2) /***************************************************************************** * DeleteRequestQueue Request Message * ****************************************************************************/ typedef struct _MPI3_DELETE_REQUEST_QUEUE_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 QueueID; /* 0x0A */ } MPI3_DELETE_REQUEST_QUEUE_REQUEST, MPI3_POINTER PTR_MPI3_DELETE_REQUEST_QUEUE_REQUEST, Mpi3DeleteRequestQueueRequest_t, MPI3_POINTER pMpi3DeleteRequestQueueRequest_t; /***************************************************************************** * CreateReplyQueue Request Message * ****************************************************************************/ typedef struct _MPI3_CREATE_REPLY_QUEUE_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Flags; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U16 Size; /* 0x0C */ U16 QueueID; /* 0x0E */ U16 MSIxIndex; /* 0x10 */ U16 Reserved12; /* 0x12 */ U32 Reserved14; /* 0x14 */ U64 BaseAddress; /* 0x18 */ } MPI3_CREATE_REPLY_QUEUE_REQUEST, MPI3_POINTER PTR_MPI3_CREATE_REPLY_QUEUE_REQUEST, Mpi3CreateReplyQueueRequest_t, MPI3_POINTER pMpi3CreateReplyQueueRequest_t; /**** Defines for the Flags field ****/ #define MPI3_CREATE_REPLY_QUEUE_FLAGS_SEGMENTED_MASK (0x80) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_SEGMENTED_SEGMENTED (0x80) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_SEGMENTED_CONTIGUOUS (0x00) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_COALESCE_DISABLE (0x02) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_MASK (0x01) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_DISABLE (0x00) #define MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_ENABLE (0x01) /**** Defines for the Size field ****/ #define MPI3_CREATE_REPLY_QUEUE_SIZE_MINIMUM (2) /***************************************************************************** * DeleteReplyQueue Request Message * ****************************************************************************/ typedef struct _MPI3_DELETE_REPLY_QUEUE_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 QueueID; /* 0x0A */ } MPI3_DELETE_REPLY_QUEUE_REQUEST, MPI3_POINTER PTR_MPI3_DELETE_REPLY_QUEUE_REQUEST, Mpi3DeleteReplyQueueRequest_t, MPI3_POINTER pMpi3DeleteReplyQueueRequest_t; /***************************************************************************** * PortEnable Request Message * ****************************************************************************/ typedef struct _MPI3_PORT_ENABLE_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 Reserved0A; /* 0x0A */ } MPI3_PORT_ENABLE_REQUEST, MPI3_POINTER PTR_MPI3_PORT_ENABLE_REQUEST, Mpi3PortEnableRequest_t, MPI3_POINTER pMpi3PortEnableRequest_t; /***************************************************************************** * IOC Events and Event Management * ****************************************************************************/ #define MPI3_EVENT_LOG_DATA (0x01) #define MPI3_EVENT_CHANGE (0x02) #define MPI3_EVENT_GPIO_INTERRUPT (0x04) #define MPI3_EVENT_CABLE_MGMT (0x06) #define MPI3_EVENT_DEVICE_ADDED (0x07) #define MPI3_EVENT_DEVICE_INFO_CHANGED (0x08) #define MPI3_EVENT_PREPARE_FOR_RESET (0x09) #define MPI3_EVENT_COMP_IMAGE_ACT_START (0x0A) #define MPI3_EVENT_ENCL_DEVICE_ADDED (0x0B) #define MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE (0x0C) #define MPI3_EVENT_DEVICE_STATUS_CHANGE (0x0D) #define MPI3_EVENT_ENERGY_PACK_CHANGE (0x0E) #define MPI3_EVENT_SAS_DISCOVERY (0x11) #define MPI3_EVENT_SAS_BROADCAST_PRIMITIVE (0x12) #define MPI3_EVENT_SAS_NOTIFY_PRIMITIVE (0x13) #define MPI3_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x14) #define MPI3_EVENT_SAS_INIT_TABLE_OVERFLOW (0x15) #define MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x16) #define MPI3_EVENT_SAS_PHY_COUNTER (0x18) #define MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR (0x19) #define MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST (0x20) #define MPI3_EVENT_PCIE_ENUMERATION (0x22) #define MPI3_EVENT_PCIE_ERROR_THRESHOLD (0x23) #define MPI3_EVENT_HARD_RESET_RECEIVED (0x40) #define MPI3_EVENT_DIAGNOSTIC_BUFFER_STATUS_CHANGE (0x50) #define MPI3_EVENT_MIN_PRODUCT_SPECIFIC (0x60) #define MPI3_EVENT_MAX_PRODUCT_SPECIFIC (0x7F) /***************************************************************************** * Event Notification Request Message * ****************************************************************************/ #define MPI3_EVENT_NOTIFY_EVENTMASK_WORDS (4) typedef struct _MPI3_EVENT_NOTIFICATION_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U16 SASBroadcastPrimitiveMasks; /* 0x0C */ U16 SASNotifyPrimitiveMasks; /* 0x0E */ U32 EventMasks[MPI3_EVENT_NOTIFY_EVENTMASK_WORDS]; /* 0x10 */ } MPI3_EVENT_NOTIFICATION_REQUEST, MPI3_POINTER PTR_MPI3_EVENT_NOTIFICATION_REQUEST, Mpi3EventNotificationRequest_t, MPI3_POINTER pMpi3EventNotificationRequest_t; -/**** Defines for the SASBroadcastPrimitiveMasks field - use MPI3_EVENT_PRIMITIVE_ values ****/ +/**** Defines for the SASBroadcastPrimitiveMasks field - use MPI3_EVENT_BROADCAST_PRIMITIVE_ values ****/ -/**** Defines for the SASNotifyPrimitiveMasks field - use MPI3_EVENT_NOTIFY_ values ****/ +/**** Defines for the SASNotifyPrimitiveMasks field - use MPI3_EVENT_NOTIFY_PRIMITIVE_ values ****/ /**** Defines for the EventMasks field - use MPI3_EVENT_ values ****/ /***************************************************************************** * Event Notification Reply Message * ****************************************************************************/ typedef struct _MPI3_EVENT_NOTIFICATION_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U8 EventDataLength; /* 0x10 */ U8 Event; /* 0x11 */ U16 IOCChangeCount; /* 0x12 */ U32 EventContext; /* 0x14 */ U32 EventData[1]; /* 0x18 */ } MPI3_EVENT_NOTIFICATION_REPLY, MPI3_POINTER PTR_MPI3_EVENT_NOTIFICATION_REPLY, Mpi3EventNotificationReply_t, MPI3_POINTER pMpi3EventNotificationReply_t; /**** Defines for the MsgFlags field ****/ #define MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK (0x01) #define MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED (0x01) #define MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_NOT_REQUIRED (0x00) #define MPI3_EVENT_NOTIFY_MSGFLAGS_EVENT_ORIGINALITY_MASK (0x02) #define MPI3_EVENT_NOTIFY_MSGFLAGS_EVENT_ORIGINALITY_ORIGINAL (0x00) #define MPI3_EVENT_NOTIFY_MSGFLAGS_EVENT_ORIGINALITY_REPLAY (0x02) /**** Defines for the Event field - use MPI3_EVENT_ values ****/ /***************************************************************************** * GPIO Interrupt Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_GPIO_INTERRUPT { U8 GPIONum; /* 0x00 */ U8 Reserved01[3]; /* 0x01 */ } MPI3_EVENT_DATA_GPIO_INTERRUPT, MPI3_POINTER PTR_MPI3_EVENT_DATA_GPIO_INTERRUPT, Mpi3EventDataGpioInterrupt_t, MPI3_POINTER pMpi3EventDataGpioInterrupt_t; /***************************************************************************** * Cable Management Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_CABLE_MANAGEMENT { U32 ActiveCablePowerRequirement; /* 0x00 */ U8 Status; /* 0x04 */ U8 ReceptacleID; /* 0x05 */ U16 Reserved06; /* 0x06 */ } MPI3_EVENT_DATA_CABLE_MANAGEMENT, MPI3_POINTER PTR_MPI3_EVENT_DATA_CABLE_MANAGEMENT, Mpi3EventDataCableManagement_t, MPI3_POINTER pMpi3EventDataCableManagement_t; /**** Defines for the ActiveCablePowerRequirement field ****/ #define MPI3_EVENT_CABLE_MGMT_ACT_CABLE_PWR_INVALID (0xFFFFFFFF) /**** Defines for the Status field ****/ #define MPI3_EVENT_CABLE_MGMT_STATUS_INSUFFICIENT_POWER (0x00) #define MPI3_EVENT_CABLE_MGMT_STATUS_PRESENT (0x01) #define MPI3_EVENT_CABLE_MGMT_STATUS_DEGRADED (0x02) /***************************************************************************** * Event Ack Request Message * ****************************************************************************/ typedef struct _MPI3_EVENT_ACK_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U8 Event; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ U32 EventContext; /* 0x10 */ } MPI3_EVENT_ACK_REQUEST, MPI3_POINTER PTR_MPI3_EVENT_ACK_REQUEST, Mpi3EventAckRequest_t, MPI3_POINTER pMpi3EventAckRequest_t; /**** Defines for the Event field - use MPI3_EVENT_ values ****/ /***************************************************************************** * Prepare for Reset Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_PREPARE_FOR_RESET { U8 ReasonCode; /* 0x00 */ U8 Reserved01; /* 0x01 */ U16 Reserved02; /* 0x02 */ } MPI3_EVENT_DATA_PREPARE_FOR_RESET, MPI3_POINTER PTR_MPI3_EVENT_DATA_PREPARE_FOR_RESET, Mpi3EventDataPrepareForReset_t, MPI3_POINTER pMpi3EventDataPrepareForReset_t; /**** Defines for the ReasonCode field ****/ #define MPI3_EVENT_PREPARE_RESET_RC_START (0x01) #define MPI3_EVENT_PREPARE_RESET_RC_ABORT (0x02) /***************************************************************************** * Component Image Activation Start Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_COMP_IMAGE_ACTIVATION { U32 Reserved00; /* 0x00 */ } MPI3_EVENT_DATA_COMP_IMAGE_ACTIVATION, MPI3_POINTER PTR_MPI3_EVENT_DATA_COMP_IMAGE_ACTIVATION, Mpi3EventDataCompImageActivation_t, MPI3_POINTER pMpi3EventDataCompImageActivation_t; /***************************************************************************** * Device Added Event * ****************************************************************************/ /* * The Device Added Event Data is exactly the same as Device Page 0 data * (including the Configuration Page header). So, please use/refer to * MPI3_DEVICE_PAGE0 structure for Device Added Event data. */ /**************************************************************************** * Device Info Changed Event * ****************************************************************************/ /* * The Device Info Changed Event Data is exactly the same as Device Page 0 data * (including the Configuration Page header). So, please use/refer to * MPI3_DEVICE_PAGE0 structure for Device Added Event data. */ /***************************************************************************** * Device Status Change Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_DEVICE_STATUS_CHANGE { U16 TaskTag; /* 0x00 */ U8 ReasonCode; /* 0x02 */ U8 IOUnitPort; /* 0x03 */ U16 ParentDevHandle; /* 0x04 */ U16 DevHandle; /* 0x06 */ U64 WWID; /* 0x08 */ U8 LUN[8]; /* 0x10 */ } MPI3_EVENT_DATA_DEVICE_STATUS_CHANGE, MPI3_POINTER PTR_MPI3_EVENT_DATA_DEVICE_STATUS_CHANGE, Mpi3EventDataDeviceStatusChange_t, MPI3_POINTER pMpi3EventDataDeviceStatusChange_t; /**** Defines for the ReasonCode field ****/ #define MPI3_EVENT_DEV_STAT_RC_MOVED (0x01) #define MPI3_EVENT_DEV_STAT_RC_HIDDEN (0x02) #define MPI3_EVENT_DEV_STAT_RC_NOT_HIDDEN (0x03) #define MPI3_EVENT_DEV_STAT_RC_ASYNC_NOTIFICATION (0x04) #define MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_STRT (0x20) #define MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_CMP (0x21) #define MPI3_EVENT_DEV_STAT_RC_INT_TASK_ABORT_STRT (0x22) #define MPI3_EVENT_DEV_STAT_RC_INT_TASK_ABORT_CMP (0x23) #define MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_STRT (0x24) #define MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_CMP (0x25) #define MPI3_EVENT_DEV_STAT_RC_PCIE_HOT_RESET_FAILED (0x30) #define MPI3_EVENT_DEV_STAT_RC_EXPANDER_REDUCED_FUNC_STRT (0x40) #define MPI3_EVENT_DEV_STAT_RC_EXPANDER_REDUCED_FUNC_CMP (0x41) #define MPI3_EVENT_DEV_STAT_RC_VD_NOT_RESPONDING (0x50) /***************************************************************************** * Energy Pack Change Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_ENERGY_PACK_CHANGE { U32 Reserved00; /* 0x00 */ U16 ShutdownTimeout; /* 0x04 */ U16 Reserved06; /* 0x06 */ } MPI3_EVENT_DATA_ENERGY_PACK_CHANGE, MPI3_POINTER PTR_MPI3_EVENT_DATA_ENERGY_PACK_CHANGE, Mpi3EventDataEnergyPackChange_t, MPI3_POINTER pMpi3EventDataEnergyPackChange_t; /***************************************************************************** * SAS Discovery Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_SAS_DISCOVERY { U8 Flags; /* 0x00 */ U8 ReasonCode; /* 0x01 */ U8 IOUnitPort; /* 0x02 */ U8 Reserved03; /* 0x03 */ U32 DiscoveryStatus; /* 0x04 */ } MPI3_EVENT_DATA_SAS_DISCOVERY, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_DISCOVERY, Mpi3EventDataSasDiscovery_t, MPI3_POINTER pMpi3EventDataSasDiscovery_t; /**** Defines for the Flags field ****/ #define MPI3_EVENT_SAS_DISC_FLAGS_DEVICE_CHANGE (0x02) #define MPI3_EVENT_SAS_DISC_FLAGS_IN_PROGRESS (0x01) /**** Defines for the ReasonCode field ****/ #define MPI3_EVENT_SAS_DISC_RC_STARTED (0x01) #define MPI3_EVENT_SAS_DISC_RC_COMPLETED (0x02) /**** Defines for the DiscoveryStatus field ****/ #define MPI3_SAS_DISC_STATUS_MAX_ENCLOSURES_EXCEED (0x80000000) #define MPI3_SAS_DISC_STATUS_MAX_EXPANDERS_EXCEED (0x40000000) #define MPI3_SAS_DISC_STATUS_MAX_DEVICES_EXCEED (0x20000000) #define MPI3_SAS_DISC_STATUS_MAX_TOPO_PHYS_EXCEED (0x10000000) #define MPI3_SAS_DISC_STATUS_INVALID_CEI (0x00010000) #define MPI3_SAS_DISC_STATUS_FECEI_MISMATCH (0x00008000) #define MPI3_SAS_DISC_STATUS_MULTIPLE_DEVICES_IN_SLOT (0x00004000) #define MPI3_SAS_DISC_STATUS_NECEI_MISMATCH (0x00002000) #define MPI3_SAS_DISC_STATUS_TOO_MANY_SLOTS (0x00001000) #define MPI3_SAS_DISC_STATUS_EXP_MULTI_SUBTRACTIVE (0x00000800) #define MPI3_SAS_DISC_STATUS_MULTI_PORT_DOMAIN (0x00000400) #define MPI3_SAS_DISC_STATUS_TABLE_TO_SUBTRACTIVE_LINK (0x00000200) #define MPI3_SAS_DISC_STATUS_UNSUPPORTED_DEVICE (0x00000100) #define MPI3_SAS_DISC_STATUS_TABLE_LINK (0x00000080) #define MPI3_SAS_DISC_STATUS_SUBTRACTIVE_LINK (0x00000040) #define MPI3_SAS_DISC_STATUS_SMP_CRC_ERROR (0x00000020) #define MPI3_SAS_DISC_STATUS_SMP_FUNCTION_FAILED (0x00000010) #define MPI3_SAS_DISC_STATUS_SMP_TIMEOUT (0x00000008) #define MPI3_SAS_DISC_STATUS_MULTIPLE_PORTS (0x00000004) #define MPI3_SAS_DISC_STATUS_INVALID_SAS_ADDRESS (0x00000002) #define MPI3_SAS_DISC_STATUS_LOOP_DETECTED (0x00000001) /***************************************************************************** * SAS Broadcast Primitive Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_SAS_BROADCAST_PRIMITIVE { U8 PhyNum; /* 0x00 */ U8 IOUnitPort; /* 0x01 */ U8 PortWidth; /* 0x02 */ U8 Primitive; /* 0x03 */ } MPI3_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, Mpi3EventDataSasBroadcastPrimitive_t, MPI3_POINTER pMpi3EventDataSasBroadcastPrimitive_t; /**** Defines for the Primitive field ****/ #define MPI3_EVENT_BROADCAST_PRIMITIVE_CHANGE (0x01) #define MPI3_EVENT_BROADCAST_PRIMITIVE_SES (0x02) #define MPI3_EVENT_BROADCAST_PRIMITIVE_EXPANDER (0x03) #define MPI3_EVENT_BROADCAST_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04) #define MPI3_EVENT_BROADCAST_PRIMITIVE_RESERVED3 (0x05) #define MPI3_EVENT_BROADCAST_PRIMITIVE_RESERVED4 (0x06) #define MPI3_EVENT_BROADCAST_PRIMITIVE_CHANGE0_RESERVED (0x07) #define MPI3_EVENT_BROADCAST_PRIMITIVE_CHANGE1_RESERVED (0x08) /***************************************************************************** * SAS Notify Primitive Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_SAS_NOTIFY_PRIMITIVE { U8 PhyNum; /* 0x00 */ U8 IOUnitPort; /* 0x01 */ U8 Reserved02; /* 0x02 */ U8 Primitive; /* 0x03 */ } MPI3_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, Mpi3EventDataSasNotifyPrimitive_t, MPI3_POINTER pMpi3EventDataSasNotifyPrimitive_t; /**** Defines for the Primitive field ****/ #define MPI3_EVENT_NOTIFY_PRIMITIVE_ENABLE_SPINUP (0x01) #define MPI3_EVENT_NOTIFY_PRIMITIVE_POWER_LOSS_EXPECTED (0x02) #define MPI3_EVENT_NOTIFY_PRIMITIVE_RESERVED1 (0x03) #define MPI3_EVENT_NOTIFY_PRIMITIVE_RESERVED2 (0x04) /***************************************************************************** * SAS Topology Change List Event * ****************************************************************************/ #ifndef MPI3_EVENT_SAS_TOPO_PHY_COUNT #define MPI3_EVENT_SAS_TOPO_PHY_COUNT (1) #endif /* MPI3_EVENT_SAS_TOPO_PHY_COUNT */ typedef struct _MPI3_EVENT_SAS_TOPO_PHY_ENTRY { U16 AttachedDevHandle; /* 0x00 */ U8 LinkRate; /* 0x02 */ - U8 Status; /* 0x03 */ + U8 PhyStatus; /* 0x03 */ } MPI3_EVENT_SAS_TOPO_PHY_ENTRY, MPI3_POINTER PTR_MPI3_EVENT_SAS_TOPO_PHY_ENTRY, Mpi3EventSasTopoPhyEntry_t, MPI3_POINTER pMpi3EventSasTopoPhyEntry_t; /**** Defines for the LinkRate field ****/ #define MPI3_EVENT_SAS_TOPO_LR_CURRENT_MASK (0xF0) #define MPI3_EVENT_SAS_TOPO_LR_CURRENT_SHIFT (4) #define MPI3_EVENT_SAS_TOPO_LR_PREV_MASK (0x0F) #define MPI3_EVENT_SAS_TOPO_LR_PREV_SHIFT (0) #define MPI3_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE (0x00) #define MPI3_EVENT_SAS_TOPO_LR_PHY_DISABLED (0x01) #define MPI3_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED (0x02) #define MPI3_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03) #define MPI3_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04) #define MPI3_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05) #define MPI3_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY (0x06) #define MPI3_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A) #define MPI3_EVENT_SAS_TOPO_LR_RATE_12_0 (0x0B) #define MPI3_EVENT_SAS_TOPO_LR_RATE_22_5 (0x0C) /**** Defines for the PhyStatus field ****/ #define MPI3_EVENT_SAS_TOPO_PHY_STATUS_MASK (0xC0) #define MPI3_EVENT_SAS_TOPO_PHY_STATUS_SHIFT (6) #define MPI3_EVENT_SAS_TOPO_PHY_STATUS_ACCESSIBLE (0x00) #define MPI3_EVENT_SAS_TOPO_PHY_STATUS_NO_EXIST (0x40) #define MPI3_EVENT_SAS_TOPO_PHY_STATUS_VACANT (0x80) #define MPI3_EVENT_SAS_TOPO_PHY_RC_MASK (0x0F) #define MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING (0x02) #define MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED (0x03) #define MPI3_EVENT_SAS_TOPO_PHY_RC_NO_CHANGE (0x04) #define MPI3_EVENT_SAS_TOPO_PHY_RC_DELAY_NOT_RESPONDING (0x05) #define MPI3_EVENT_SAS_TOPO_PHY_RC_RESPONDING (0x06) typedef struct _MPI3_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST { U16 EnclosureHandle; /* 0x00 */ U16 ExpanderDevHandle; /* 0x02 */ U8 NumPhys; /* 0x04 */ U8 Reserved05[3]; /* 0x05 */ U8 NumEntries; /* 0x08 */ U8 StartPhyNum; /* 0x09 */ U8 ExpStatus; /* 0x0A */ U8 IOUnitPort; /* 0x0B */ MPI3_EVENT_SAS_TOPO_PHY_ENTRY PhyEntry[MPI3_EVENT_SAS_TOPO_PHY_COUNT]; /* 0x0C */ } MPI3_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, Mpi3EventDataSasTopologyChangeList_t, MPI3_POINTER pMpi3EventDataSasTopologyChangeList_t; /**** Defines for the ExpStatus field ****/ #define MPI3_EVENT_SAS_TOPO_ES_NO_EXPANDER (0x00) #define MPI3_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02) #define MPI3_EVENT_SAS_TOPO_ES_RESPONDING (0x03) #define MPI3_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04) /***************************************************************************** * SAS PHY Counter Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_SAS_PHY_COUNTER { U64 TimeStamp; /* 0x00 */ U32 Reserved08; /* 0x08 */ U8 PhyEventCode; /* 0x0C */ U8 PhyNum; /* 0x0D */ U16 Reserved0E; /* 0x0E */ U32 PhyEventInfo; /* 0x10 */ U8 CounterType; /* 0x14 */ U8 ThresholdWindow; /* 0x15 */ U8 TimeUnits; /* 0x16 */ U8 Reserved17; /* 0x17 */ U32 EventThreshold; /* 0x18 */ U16 ThresholdFlags; /* 0x1C */ U16 Reserved1E; /* 0x1E */ } MPI3_EVENT_DATA_SAS_PHY_COUNTER, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_PHY_COUNTER, Mpi3EventDataSasPhyCounter_t, MPI3_POINTER pMpi3EventDataSasPhyCounter_t; /**** Defines for the PhyEventCode field - use MPI3_SASPHY3_EVENT_CODE_ defines ****/ /**** Defines for the CounterType field - use MPI3_SASPHY3_COUNTER_TYPE_ defines ****/ /**** Defines for the TimeUnits field - use MPI3_SASPHY3_TIME_UNITS_ defines ****/ /**** Defines for the ThresholdFlags field - use MPI3_SASPHY3_TFLAGS_ defines ****/ /***************************************************************************** * SAS Device Discovery Error Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_SAS_DEVICE_DISC_ERR { U16 DevHandle; /* 0x00 */ U8 ReasonCode; /* 0x02 */ U8 IOUnitPort; /* 0x03 */ U32 Reserved04; /* 0x04 */ U64 SASAddress; /* 0x08 */ } MPI3_EVENT_DATA_SAS_DEVICE_DISC_ERR, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_DEVICE_DISC_ERR, Mpi3EventDataSasDeviceDiscErr_t, MPI3_POINTER pMpi3EventDataSasDeviceDiscErr_t; /**** Defines for the ReasonCode field ****/ #define MPI3_EVENT_SAS_DISC_ERR_RC_SMP_FAILED (0x01) #define MPI3_EVENT_SAS_DISC_ERR_RC_SMP_TIMEOUT (0x02) /***************************************************************************** * PCIe Enumeration Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_PCIE_ENUMERATION { U8 Flags; /* 0x00 */ U8 ReasonCode; /* 0x01 */ U8 IOUnitPort; /* 0x02 */ U8 Reserved03; /* 0x03 */ U32 EnumerationStatus; /* 0x04 */ } MPI3_EVENT_DATA_PCIE_ENUMERATION, MPI3_POINTER PTR_MPI3_EVENT_DATA_PCIE_ENUMERATION, Mpi3EventDataPcieEnumeration_t, MPI3_POINTER pMpi3EventDataPcieEnumeration_t; /**** Defines for the Flags field ****/ #define MPI3_EVENT_PCIE_ENUM_FLAGS_DEVICE_CHANGE (0x02) #define MPI3_EVENT_PCIE_ENUM_FLAGS_IN_PROGRESS (0x01) /**** Defines for the ReasonCode field ****/ #define MPI3_EVENT_PCIE_ENUM_RC_STARTED (0x01) #define MPI3_EVENT_PCIE_ENUM_RC_COMPLETED (0x02) /**** Defines for the EnumerationStatus field ****/ #define MPI3_EVENT_PCIE_ENUM_ES_MAX_SWITCH_DEPTH_EXCEED (0x80000000) #define MPI3_EVENT_PCIE_ENUM_ES_MAX_SWITCHES_EXCEED (0x40000000) #define MPI3_EVENT_PCIE_ENUM_ES_MAX_DEVICES_EXCEED (0x20000000) #define MPI3_EVENT_PCIE_ENUM_ES_RESOURCES_EXHAUSTED (0x10000000) /***************************************************************************** * PCIe Topology Change List Event * ****************************************************************************/ #ifndef MPI3_EVENT_PCIE_TOPO_PORT_COUNT #define MPI3_EVENT_PCIE_TOPO_PORT_COUNT (1) #endif /* MPI3_EVENT_PCIE_TOPO_PORT_COUNT */ typedef struct _MPI3_EVENT_PCIE_TOPO_PORT_ENTRY { U16 AttachedDevHandle; /* 0x00 */ U8 PortStatus; /* 0x02 */ U8 Reserved03; /* 0x03 */ U8 CurrentPortInfo; /* 0x04 */ U8 Reserved05; /* 0x05 */ U8 PreviousPortInfo; /* 0x06 */ U8 Reserved07; /* 0x07 */ } MPI3_EVENT_PCIE_TOPO_PORT_ENTRY, MPI3_POINTER PTR_MPI3_EVENT_PCIE_TOPO_PORT_ENTRY, Mpi3EventPcieTopoPortEntry_t, MPI3_POINTER pMpi3EventPcieTopoPortEntry_t; /**** Defines for the PortStatus field ****/ #define MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING (0x02) #define MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED (0x03) #define MPI3_EVENT_PCIE_TOPO_PS_NO_CHANGE (0x04) #define MPI3_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING (0x05) #define MPI3_EVENT_PCIE_TOPO_PS_RESPONDING (0x06) /**** Defines for the CurrentPortInfo and PreviousPortInfo field ****/ #define MPI3_EVENT_PCIE_TOPO_PI_LANES_MASK (0xF0) #define MPI3_EVENT_PCIE_TOPO_PI_LANES_UNKNOWN (0x00) #define MPI3_EVENT_PCIE_TOPO_PI_LANES_1 (0x10) #define MPI3_EVENT_PCIE_TOPO_PI_LANES_2 (0x20) #define MPI3_EVENT_PCIE_TOPO_PI_LANES_4 (0x30) #define MPI3_EVENT_PCIE_TOPO_PI_LANES_8 (0x40) #define MPI3_EVENT_PCIE_TOPO_PI_LANES_16 (0x50) #define MPI3_EVENT_PCIE_TOPO_PI_RATE_MASK (0x0F) #define MPI3_EVENT_PCIE_TOPO_PI_RATE_UNKNOWN (0x00) #define MPI3_EVENT_PCIE_TOPO_PI_RATE_DISABLED (0x01) #define MPI3_EVENT_PCIE_TOPO_PI_RATE_2_5 (0x02) #define MPI3_EVENT_PCIE_TOPO_PI_RATE_5_0 (0x03) #define MPI3_EVENT_PCIE_TOPO_PI_RATE_8_0 (0x04) #define MPI3_EVENT_PCIE_TOPO_PI_RATE_16_0 (0x05) #define MPI3_EVENT_PCIE_TOPO_PI_RATE_32_0 (0x06) typedef struct _MPI3_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST { U16 EnclosureHandle; /* 0x00 */ U16 SwitchDevHandle; /* 0x02 */ U8 NumPorts; /* 0x04 */ U8 Reserved05[3]; /* 0x05 */ U8 NumEntries; /* 0x08 */ U8 StartPortNum; /* 0x09 */ U8 SwitchStatus; /* 0x0A */ U8 IOUnitPort; /* 0x0B */ U32 Reserved0C; /* 0x0C */ MPI3_EVENT_PCIE_TOPO_PORT_ENTRY PortEntry[MPI3_EVENT_PCIE_TOPO_PORT_COUNT]; /* 0x10 */ } MPI3_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST, MPI3_POINTER PTR_MPI3_EVENT_DATA_PCIE_TOPOLOGY_CHANGE_LIST, Mpi3EventDataPcieTopologyChangeList_t, MPI3_POINTER pMpi3EventDataPcieTopologyChangeList_t; /**** Defines for the SwitchStatus field ****/ #define MPI3_EVENT_PCIE_TOPO_SS_NO_PCIE_SWITCH (0x00) #define MPI3_EVENT_PCIE_TOPO_SS_NOT_RESPONDING (0x02) #define MPI3_EVENT_PCIE_TOPO_SS_RESPONDING (0x03) #define MPI3_EVENT_PCIE_TOPO_SS_DELAY_NOT_RESPONDING (0x04) /***************************************************************************** * PCIe Error Threshold Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_PCIE_ERROR_THRESHOLD { U64 Timestamp; /* 0x00 */ U8 ReasonCode; /* 0x08 */ U8 Port; /* 0x09 */ U16 SwitchDevHandle; /* 0x0A */ U8 Error; /* 0x0C */ U8 Action; /* 0x0D */ U16 ThresholdCount; /* 0x0E */ U16 AttachedDevHandle; /* 0x10 */ U16 Reserved12; /* 0x12 */ U32 Reserved14; /* 0x14 */ } MPI3_EVENT_DATA_PCIE_ERROR_THRESHOLD, MPI3_POINTER PTR_MPI3_EVENT_DATA_PCIE_ERROR_THRESHOLD, Mpi3EventDataPcieErrorThreshold_t, MPI3_POINTER pMpi3EventDataPcieErrorThreshold_t; /**** Defines for the ReasonCode field ****/ #define MPI3_EVENT_PCI_ERROR_RC_THRESHOLD_EXCEEDED (0x00) #define MPI3_EVENT_PCI_ERROR_RC_ESCALATION (0x01) /**** Defines for the Error field - use MPI3_PCIEIOUNIT3_ERROR_ values ****/ /**** Defines for the Action field - use MPI3_PCIEIOUNIT3_ACTION_ values ****/ /**************************************************************************** * Enclosure Device Added Event * ****************************************************************************/ /* * The Enclosure Device Added Event Data is exactly the same as Enclosure * Page 0 data (including the Configuration Page header). So, please * use/refer to MPI3_ENCLOSURE_PAGE0 structure for Enclosure Device Added * Event data. */ /**************************************************************************** * Enclosure Device Changed Event * ****************************************************************************/ /* * The Enclosure Device Change Event Data is exactly the same as Enclosure * Page 0 data (including the Configuration Page header). So, please * use/refer to MPI3_ENCLOSURE_PAGE0 structure for Enclosure Device Change * Event data. */ /***************************************************************************** * SAS Initiator Device Status Change Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE { U8 ReasonCode; /* 0x00 */ U8 IOUnitPort; /* 0x01 */ U16 DevHandle; /* 0x02 */ U32 Reserved04; /* 0x04 */ U64 SASAddress; /* 0x08 */ } MPI3_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, Mpi3EventDataSasInitDevStatusChange_t, MPI3_POINTER pMpi3EventDataSasInitDevStatusChange_t; /**** Defines for the ReasonCode field ****/ #define MPI3_EVENT_SAS_INIT_RC_ADDED (0x01) #define MPI3_EVENT_SAS_INIT_RC_NOT_RESPONDING (0x02) /***************************************************************************** * SAS Initiator Device Table Overflow Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW { U16 MaxInit; /* 0x00 */ U16 CurrentInit; /* 0x02 */ U32 Reserved04; /* 0x04 */ U64 SASAddress; /* 0x08 */ } MPI3_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, MPI3_POINTER PTR_MPI3_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, Mpi3EventDataSasInitTableOverflow_t, MPI3_POINTER pMpi3EventDataSasInitTableOverflow_t; /***************************************************************************** * Hard Reset Received Event * ****************************************************************************/ typedef struct _MPI3_EVENT_DATA_HARD_RESET_RECEIVED { U8 Reserved00; /* 0x00 */ U8 IOUnitPort; /* 0x01 */ U16 Reserved02; /* 0x02 */ } MPI3_EVENT_DATA_HARD_RESET_RECEIVED, MPI3_POINTER PTR_MPI3_EVENT_DATA_HARD_RESET_RECEIVED, Mpi3EventDataHardResetReceived_t, MPI3_POINTER pMpi3EventDataHardResetReceived_t; /***************************************************************************** * Diagnostic Tool Events * *****************************************************************************/ /***************************************************************************** * Diagnostic Buffer Status Change Event * *****************************************************************************/ typedef struct _MPI3_EVENT_DATA_DIAG_BUFFER_STATUS_CHANGE { U8 Type; /* 0x00 */ U8 ReasonCode; /* 0x01 */ U16 Reserved02; /* 0x02 */ U32 Reserved04; /* 0x04 */ } MPI3_EVENT_DATA_DIAG_BUFFER_STATUS_CHANGE, MPI3_POINTER PTR_MPI3_EVENT_DATA_DIAG_BUFFER_STATUS_CHANGE, Mpi3EventDataDiagBufferStatusChange_t, MPI3_POINTER pMpi3EventDataDiagBufferStatusChange_t; /**** Defines for the Type field - use MPI3_DIAG_BUFFER_TYPE_ values ****/ /**** Defines for the ReasonCode field ****/ #define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RELEASED (0x01) #define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_PAUSED (0x02) #define MPI3_EVENT_DIAG_BUFFER_STATUS_CHANGE_RC_RESUMED (0x03) /***************************************************************************** * Persistent Event Logs * ****************************************************************************/ /**** Definitions for the Locale field ****/ #define MPI3_PEL_LOCALE_FLAGS_NON_BLOCKING_BOOT_EVENT (0x0200) #define MPI3_PEL_LOCALE_FLAGS_BLOCKING_BOOT_EVENT (0x0100) #define MPI3_PEL_LOCALE_FLAGS_PCIE (0x0080) #define MPI3_PEL_LOCALE_FLAGS_CONFIGURATION (0x0040) #define MPI3_PEL_LOCALE_FLAGS_CONTROLER (0x0020) #define MPI3_PEL_LOCALE_FLAGS_SAS (0x0010) #define MPI3_PEL_LOCALE_FLAGS_EPACK (0x0008) #define MPI3_PEL_LOCALE_FLAGS_ENCLOSURE (0x0004) #define MPI3_PEL_LOCALE_FLAGS_PD (0x0002) #define MPI3_PEL_LOCALE_FLAGS_VD (0x0001) /**** Definitions for the Class field ****/ #define MPI3_PEL_CLASS_DEBUG (0x00) #define MPI3_PEL_CLASS_PROGRESS (0x01) #define MPI3_PEL_CLASS_INFORMATIONAL (0x02) #define MPI3_PEL_CLASS_WARNING (0x03) #define MPI3_PEL_CLASS_CRITICAL (0x04) #define MPI3_PEL_CLASS_FATAL (0x05) #define MPI3_PEL_CLASS_FAULT (0x06) /**** Definitions for the ClearType field ****/ #define MPI3_PEL_CLEARTYPE_CLEAR (0x00) /**** Definitions for the WaitTime field ****/ #define MPI3_PEL_WAITTIME_INFINITE_WAIT (0x00) /**** Definitions for the Action field ****/ #define MPI3_PEL_ACTION_GET_SEQNUM (0x01) #define MPI3_PEL_ACTION_MARK_CLEAR (0x02) #define MPI3_PEL_ACTION_GET_LOG (0x03) #define MPI3_PEL_ACTION_GET_COUNT (0x04) #define MPI3_PEL_ACTION_WAIT (0x05) #define MPI3_PEL_ACTION_ABORT (0x06) #define MPI3_PEL_ACTION_GET_PRINT_STRINGS (0x07) #define MPI3_PEL_ACTION_ACKNOWLEDGE (0x08) /**** Definitions for the LogStatus field ****/ #define MPI3_PEL_STATUS_SUCCESS (0x00) #define MPI3_PEL_STATUS_NOT_FOUND (0x01) #define MPI3_PEL_STATUS_ABORTED (0x02) #define MPI3_PEL_STATUS_NOT_READY (0x03) /**************************************************************************** * PEL Sequence Numbers * ****************************************************************************/ typedef struct _MPI3_PEL_SEQ { U32 Newest; /* 0x00 */ U32 Oldest; /* 0x04 */ U32 Clear; /* 0x08 */ U32 Shutdown; /* 0x0C */ U32 Boot; /* 0x10 */ U32 LastAcknowledged; /* 0x14 */ } MPI3_PEL_SEQ, MPI3_POINTER PTR_MPI3_PEL_SEQ, Mpi3PELSeq_t, MPI3_POINTER pMpi3PELSeq_t; /**************************************************************************** * PEL Entry * ****************************************************************************/ typedef struct _MPI3_PEL_ENTRY { U64 TimeStamp; /* 0x00 */ U32 SequenceNumber; /* 0x08 */ U16 LogCode; /* 0x0C */ U16 ArgType; /* 0x0E */ U16 Locale; /* 0x10 */ U8 Class; /* 0x12 */ U8 Flags; /* 0x13 */ U8 ExtNum; /* 0x14 */ U8 NumExts; /* 0x15 */ U8 ArgDataSize; /* 0x16 */ U8 FixedFormatStringsSize; /* 0x17 */ U32 Reserved18[2]; /* 0x18 */ U32 PELInfo[24]; /* 0x20 - 0x7F */ } MPI3_PEL_ENTRY, MPI3_POINTER PTR_MPI3_PEL_ENTRY, Mpi3PELEntry_t, MPI3_POINTER pMpi3PELEntry_t; /**** Definitions for the Flags field ****/ #define MPI3_PEL_FLAGS_COMPLETE_RESET_NEEDED (0x02) #define MPI3_PEL_FLAGS_ACK_NEEDED (0x01) /**************************************************************************** * PEL Event List * ****************************************************************************/ typedef struct _MPI3_PEL_LIST { U32 LogCount; /* 0x00 */ U32 Reserved04; /* 0x04 */ MPI3_PEL_ENTRY Entry[1]; /* 0x08 */ /* variable length */ } MPI3_PEL_LIST, MPI3_POINTER PTR_MPI3_PEL_LIST, Mpi3PELList_t, MPI3_POINTER pMpi3PELList_t; /**************************************************************************** * PEL Count Data * ****************************************************************************/ typedef U32 MPI3_PEL_LOG_COUNT, MPI3_POINTER PTR_MPI3_PEL_LOG_COUNT, Mpi3PELLogCount_t, MPI3_POINTER pMpi3PELLogCount_t; /**************************************************************************** * PEL Arg Map * ****************************************************************************/ typedef struct _MPI3_PEL_ARG_MAP { U8 ArgType; /* 0x00 */ U8 Length; /* 0x01 */ U16 StartLocation; /* 0x02 */ } MPI3_PEL_ARG_MAP, MPI3_POINTER PTR_MPI3_PEL_ARG_MAP, Mpi3PELArgMap_t, MPI3_POINTER pMpi3PELArgMap_t; /**** Definitions for the ArgType field ****/ #define MPI3_PEL_ARG_MAP_ARG_TYPE_APPEND_STRING (0x00) #define MPI3_PEL_ARG_MAP_ARG_TYPE_INTEGER (0x01) #define MPI3_PEL_ARG_MAP_ARG_TYPE_STRING (0x02) #define MPI3_PEL_ARG_MAP_ARG_TYPE_BIT_FIELD (0x03) /**************************************************************************** * PEL Print String * ****************************************************************************/ typedef struct _MPI3_PEL_PRINT_STRING { U16 LogCode; /* 0x00 */ U16 StringLength; /* 0x02 */ U8 NumArgMap; /* 0x04 */ U8 Reserved05[3]; /* 0x05 */ MPI3_PEL_ARG_MAP ArgMap[1]; /* 0x08 */ /* variable length */ /* FormatString - offset must be calculated */ /* variable length */ } MPI3_PEL_PRINT_STRING, MPI3_POINTER PTR_MPI3_PEL_PRINT_STRING, Mpi3PELPrintString_t, MPI3_POINTER pMpi3PELPrintString_t; /**************************************************************************** * PEL Print String List * ****************************************************************************/ typedef struct _MPI3_PEL_PRINT_STRING_LIST { U32 NumPrintStrings; /* 0x00 */ U32 ResidualBytesRemain; /* 0x04 */ U32 Reserved08[2]; /* 0x08 */ MPI3_PEL_PRINT_STRING PrintString[1]; /* 0x10 */ /* variable length */ } MPI3_PEL_PRINT_STRING_LIST, MPI3_POINTER PTR_MPI3_PEL_PRINT_STRING_LIST, Mpi3PELPrintStringList_t, MPI3_POINTER pMpi3PELPrintStringList_t; /**************************************************************************** * PEL Request Msg - generic to allow header decoding * ****************************************************************************/ #ifndef MPI3_PEL_ACTION_SPECIFIC_MAX #define MPI3_PEL_ACTION_SPECIFIC_MAX (1) #endif /* MPI3_PEL_ACTION_SPECIFIC_MAX */ typedef struct _MPI3_PEL_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Action; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 ActionSpecific[MPI3_PEL_ACTION_SPECIFIC_MAX]; /* 0x0C */ /* variable length */ } MPI3_PEL_REQUEST, MPI3_POINTER PTR_MPI3_PEL_REQUEST, Mpi3PELRequest_t, MPI3_POINTER pMpi3PELRequest_t; /**************************************************************************** * PEL ACTION Get Sequence Nembers * ****************************************************************************/ typedef struct _MPI3_PEL_REQ_ACTION_GET_SEQUENCE_NUMBERS { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Action; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 Reserved0C[5]; /* 0x0C */ MPI3_SGE_UNION SGL; /* 0x20 */ } MPI3_PEL_REQ_ACTION_GET_SEQUENCE_NUMBERS, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_GET_SEQUENCE_NUMBERS, Mpi3PELReqActionGetSequenceNumbers_t, MPI3_POINTER pMpi3PELReqActionGetSequenceNumbers_t; /**************************************************************************** * PEL ACTION Clear Log * ****************************************************************************/ typedef struct _MPI3_PEL_REQ_ACTION_CLEAR_LOG_MARKER { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Action; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U8 ClearType; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ } MPI3_PEL_REQ_ACTION_CLEAR_LOG_MARKER, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_CLEAR_LOG_MARKER, Mpi3PELReqActionClearLogMMarker_t, MPI3_POINTER pMpi3PELReqActionClearLogMMarker_t; /**************************************************************************** * PEL ACTION Get Log * ****************************************************************************/ typedef struct _MPI3_PEL_REQ_ACTION_GET_LOG { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Action; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 StartingSequenceNumber; /* 0x0C */ U16 Locale; /* 0x10 */ U8 Class; /* 0x12 */ U8 Reserved13; /* 0x13 */ U32 Reserved14[3]; /* 0x14 */ MPI3_SGE_UNION SGL; /* 0x20 */ } MPI3_PEL_REQ_ACTION_GET_LOG, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_GET_LOG, Mpi3PELReqActionGetLog_t, MPI3_POINTER pMpi3PELReqActionGetLog_t; /**************************************************************************** * PEL ACTION Get Count * ****************************************************************************/ typedef struct _MPI3_PEL_REQ_ACTION_GET_COUNT { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Action; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 StartingSequenceNumber; /* 0x0C */ U16 Locale; /* 0x10 */ U8 Class; /* 0x12 */ U8 Reserved13; /* 0x13 */ U32 Reserved14[3]; /* 0x14 */ MPI3_SGE_UNION SGL; /* 0x20 */ } MPI3_PEL_REQ_ACTION_GET_COUNT, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_GET_COUNT, Mpi3PELReqActionGetCount_t, MPI3_POINTER pMpi3PELReqActionGetCount_t; /**************************************************************************** * PEL ACTION Wait * ****************************************************************************/ typedef struct _MPI3_PEL_REQ_ACTION_WAIT { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Action; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 StartingSequenceNumber; /* 0x0C */ U16 Locale; /* 0x10 */ U8 Class; /* 0x12 */ U8 Reserved13; /* 0x13 */ U16 WaitTime; /* 0x14 */ U16 Reserved16; /* 0x16 */ U32 Reserved18[2]; /* 0x18 */ } MPI3_PEL_REQ_ACTION_WAIT, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_WAIT, Mpi3PELReqActionWait_t, MPI3_POINTER pMpi3PELReqActionWait_t; /**************************************************************************** * PEL ACTION Abort * ****************************************************************************/ typedef struct _MPI3_PEL_REQ_ACTION_ABORT { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Action; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 Reserved0C; /* 0x0C */ U16 AbortHostTag; /* 0x10 */ U16 Reserved12; /* 0x12 */ U32 Reserved14; /* 0x14 */ } MPI3_PEL_REQ_ACTION_ABORT, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_ABORT, Mpi3PELReqActionAbort_t, MPI3_POINTER pMpi3PELReqActionAbort_t; /**************************************************************************** * PEL ACTION Get Print Strings * ****************************************************************************/ typedef struct _MPI3_PEL_REQ_ACTION_GET_PRINT_STRINGS { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Action; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 Reserved0C; /* 0x0C */ U16 StartLogCode; /* 0x10 */ U16 Reserved12; /* 0x12 */ U32 Reserved14[3]; /* 0x14 */ MPI3_SGE_UNION SGL; /* 0x20 */ } MPI3_PEL_REQ_ACTION_GET_PRINT_STRINGS, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_GET_PRINT_STRINGS, Mpi3PELReqActionGetPrintStrings_t, MPI3_POINTER pMpi3PELReqActionGetPrintStrings_t; /**************************************************************************** * PEL ACTION Acknowledge * ****************************************************************************/ typedef struct _MPI3_PEL_REQ_ACTION_ACKNOWLEDGE { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Action; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 SequenceNumber; /* 0x0C */ U32 Reserved10; /* 0x10 */ } MPI3_PEL_REQ_ACTION_ACKNOWLEDGE, MPI3_POINTER PTR_MPI3_PEL_REQ_ACTION_ACKNOWLEDGE, Mpi3PELReqActionAcknowledge_t, MPI3_POINTER pMpi3PELReqActionAcknowledge_t; /**** Definitions for the MsgFlags field ****/ #define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_MASK (0x03) #define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_NO_GUIDANCE (0x00) #define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_CONTINUE_OP (0x01) #define MPI3_PELACKNOWLEDGE_MSGFLAGS_SAFE_MODE_EXIT_TRANSITION_TO_FAULT (0x02) /**************************************************************************** * PEL Reply * ****************************************************************************/ typedef struct _MPI3_PEL_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U8 Action; /* 0x10 */ U8 Reserved11; /* 0x11 */ U16 Reserved12; /* 0x12 */ U16 PELogStatus; /* 0x14 */ U16 Reserved16; /* 0x16 */ U32 TransferLength; /* 0x18 */ } MPI3_PEL_REPLY, MPI3_POINTER PTR_MPI3_PEL_REPLY, Mpi3PELReply_t, MPI3_POINTER pMpi3PELReply_t; /***************************************************************************** * Component Image Download * ****************************************************************************/ typedef struct _MPI3_CI_DOWNLOAD_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Action; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 Signature1; /* 0x0C */ U32 TotalImageSize; /* 0x10 */ U32 ImageOffset; /* 0x14 */ U32 SegmentSize; /* 0x18 */ U32 Reserved1C; /* 0x1C */ MPI3_SGE_UNION SGL; /* 0x20 */ } MPI3_CI_DOWNLOAD_REQUEST, MPI3_POINTER PTR_MPI3_CI_DOWNLOAD_REQUEST, Mpi3CIDownloadRequest_t, MPI3_POINTER pMpi3CIDownloadRequest_t; /**** Definitions for the MsgFlags field ****/ #define MPI3_CI_DOWNLOAD_MSGFLAGS_LAST_SEGMENT (0x80) #define MPI3_CI_DOWNLOAD_MSGFLAGS_FORCE_FMC_ENABLE (0x40) #define MPI3_CI_DOWNLOAD_MSGFLAGS_SIGNED_NVDATA (0x20) #define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_MASK (0x03) #define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_FAST (0x00) #define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_MEDIUM (0x01) #define MPI3_CI_DOWNLOAD_MSGFLAGS_WRITE_CACHE_FLUSH_SLOW (0x02) /**** Definitions for the Action field ****/ #define MPI3_CI_DOWNLOAD_ACTION_DOWNLOAD (0x01) #define MPI3_CI_DOWNLOAD_ACTION_ONLINE_ACTIVATION (0x02) #define MPI3_CI_DOWNLOAD_ACTION_OFFLINE_ACTIVATION (0x03) #define MPI3_CI_DOWNLOAD_ACTION_GET_STATUS (0x04) #define MPI3_CI_DOWNLOAD_ACTION_CANCEL_OFFLINE_ACTIVATION (0x05) typedef struct _MPI3_CI_DOWNLOAD_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U8 Flags; /* 0x10 */ U8 CacheDirty; /* 0x11 */ U8 PendingCount; /* 0x12 */ U8 Reserved13; /* 0x13 */ } MPI3_CI_DOWNLOAD_REPLY, MPI3_POINTER PTR_MPI3_CI_DOWNLOAD_REPLY, Mpi3CIDownloadReply_t, MPI3_POINTER pMpi3CIDownloadReply_t; /**** Definitions for the Flags field ****/ #define MPI3_CI_DOWNLOAD_FLAGS_DOWNLOAD_IN_PROGRESS (0x80) #define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_FAILURE (0x40) #define MPI3_CI_DOWNLOAD_FLAGS_OFFLINE_ACTIVATION_REQUIRED (0x20) #define MPI3_CI_DOWNLOAD_FLAGS_KEY_UPDATE_PENDING (0x10) #define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_MASK (0x0E) #define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_NOT_NEEDED (0x00) #define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_AWAITING (0x02) #define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_ONLINE_PENDING (0x04) #define MPI3_CI_DOWNLOAD_FLAGS_ACTIVATION_STATUS_OFFLINE_PENDING (0x06) #define MPI3_CI_DOWNLOAD_FLAGS_COMPATIBLE (0x01) /***************************************************************************** * Component Image Upload * ****************************************************************************/ typedef struct _MPI3_CI_UPLOAD_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U32 Signature1; /* 0x0C */ U32 Reserved10; /* 0x10 */ U32 ImageOffset; /* 0x14 */ U32 SegmentSize; /* 0x18 */ U32 Reserved1C; /* 0x1C */ MPI3_SGE_UNION SGL; /* 0x20 */ } MPI3_CI_UPLOAD_REQUEST, MPI3_POINTER PTR_MPI3_CI_UPLOAD_REQUEST, Mpi3CIUploadRequest_t, MPI3_POINTER pMpi3CIUploadRequest_t; /**** Defines for the MsgFlags field ****/ #define MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_MASK (0x01) #define MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_PRIMARY (0x00) #define MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_SECONDARY (0x01) #define MPI3_CI_UPLOAD_MSGFLAGS_FORMAT_MASK (0x02) #define MPI3_CI_UPLOAD_MSGFLAGS_FORMAT_FLASH (0x00) #define MPI3_CI_UPLOAD_MSGFLAGS_FORMAT_EXECUTABLE (0x02) /**** Defines for Signature1 field - use MPI3_IMAGE_HEADER_SIGNATURE1_ defines */ /***************************************************************************** * IO Unit Control * ****************************************************************************/ /**** Definitions for the Operation field ****/ #define MPI3_CTRL_OP_FORCE_FULL_DISCOVERY (0x01) #define MPI3_CTRL_OP_LOOKUP_MAPPING (0x02) #define MPI3_CTRL_OP_UPDATE_TIMESTAMP (0x04) #define MPI3_CTRL_OP_GET_TIMESTAMP (0x05) #define MPI3_CTRL_OP_GET_IOC_CHANGE_COUNT (0x06) #define MPI3_CTRL_OP_CHANGE_PROFILE (0x07) #define MPI3_CTRL_OP_REMOVE_DEVICE (0x10) #define MPI3_CTRL_OP_CLOSE_PERSISTENT_CONNECTION (0x11) #define MPI3_CTRL_OP_HIDDEN_ACK (0x12) #define MPI3_CTRL_OP_CLEAR_DEVICE_COUNTERS (0x13) #define MPI3_CTRL_OP_SEND_SAS_PRIMITIVE (0x20) #define MPI3_CTRL_OP_SAS_PHY_CONTROL (0x21) #define MPI3_CTRL_OP_READ_INTERNAL_BUS (0x23) #define MPI3_CTRL_OP_WRITE_INTERNAL_BUS (0x24) #define MPI3_CTRL_OP_PCIE_LINK_CONTROL (0x30) /**** Depending on the Operation selected, the various ParamX fields *****/ /**** contain defined data values. These indexes help identify those values *****/ #define MPI3_CTRL_OP_LOOKUP_MAPPING_PARAM8_LOOKUP_METHOD_INDEX (0x00) #define MPI3_CTRL_OP_UPDATE_TIMESTAMP_PARAM64_TIMESTAMP_INDEX (0x00) #define MPI3_CTRL_OP_CHANGE_PROFILE_PARAM8_PROFILE_ID_INDEX (0x00) #define MPI3_CTRL_OP_REMOVE_DEVICE_PARAM16_DEVHANDLE_INDEX (0x00) #define MPI3_CTRL_OP_CLOSE_PERSIST_CONN_PARAM16_DEVHANDLE_INDEX (0x00) #define MPI3_CTRL_OP_HIDDEN_ACK_PARAM16_DEVHANDLE_INDEX (0x00) #define MPI3_CTRL_OP_CLEAR_DEVICE_COUNTERS_PARAM16_DEVHANDLE_INDEX (0x00) #define MPI3_CTRL_OP_SEND_SAS_PRIM_PARAM8_PHY_INDEX (0x00) #define MPI3_CTRL_OP_SEND_SAS_PRIM_PARAM8_PRIMSEQ_INDEX (0x01) #define MPI3_CTRL_OP_SEND_SAS_PRIM_PARAM32_PRIMITIVE_INDEX (0x00) #define MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_ACTION_INDEX (0x00) #define MPI3_CTRL_OP_SAS_PHY_CONTROL_PARAM8_PHY_INDEX (0x01) #define MPI3_CTRL_OP_READ_INTERNAL_BUS_PARAM64_ADDRESS_INDEX (0x00) #define MPI3_CTRL_OP_WRITE_INTERNAL_BUS_PARAM64_ADDRESS_INDEX (0x00) #define MPI3_CTRL_OP_WRITE_INTERNAL_BUS_PARAM32_VALUE_INDEX (0x00) #define MPI3_CTRL_OP_PCIE_LINK_CONTROL_PARAM8_ACTION_INDEX (0x00) #define MPI3_CTRL_OP_PCIE_LINK_CONTROL_PARAM8_LINK_INDEX (0x01) /**** Definitions for the LookupMethod field in LOOKUP_MAPPING reqs ****/ #define MPI3_CTRL_LOOKUP_METHOD_WWID_ADDRESS (0x01) #define MPI3_CTRL_LOOKUP_METHOD_ENCLOSURE_SLOT (0x02) #define MPI3_CTRL_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03) #define MPI3_CTRL_LOOKUP_METHOD_PERSISTENT_ID (0x04) /**** Definitions for IoUnitControl Lookup Mapping Method Parameters ****/ #define MPI3_CTRL_LOOKUP_METHOD_WWIDADDR_PARAM16_DEVH_INDEX (0) #define MPI3_CTRL_LOOKUP_METHOD_WWIDADDR_PARAM64_WWID_INDEX (0) #define MPI3_CTRL_LOOKUP_METHOD_ENCLSLOT_PARAM16_SLOTNUM_INDEX (0) #define MPI3_CTRL_LOOKUP_METHOD_ENCLSLOT_PARAM64_ENCLOSURELID_INDEX (0) #define MPI3_CTRL_LOOKUP_METHOD_SASDEVNAME_PARAM16_DEVH_INDEX (0) #define MPI3_CTRL_LOOKUP_METHOD_SASDEVNAME_PARAM64_DEVNAME_INDEX (0) #define MPI3_CTRL_LOOKUP_METHOD_PERSISTID_PARAM16_DEVH_INDEX (0) #define MPI3_CTRL_LOOKUP_METHOD_PERSISTID_PARAM16_PERSISTENT_ID_INDEX (1) /*** Definitions for IoUnitControl Reply fields ****/ #define MPI3_CTRL_LOOKUP_METHOD_VALUE16_DEVH_INDEX (0) #define MPI3_CTRL_GET_TIMESTAMP_VALUE64_TIMESTAMP_INDEX (0) #define MPI3_CTRL_GET_IOC_CHANGE_COUNT_VALUE16_CHANGECOUNT_INDEX (0) #define MPI3_CTRL_READ_INTERNAL_BUS_VALUE32_VALUE_INDEX (0) /**** Definitions for the PrimSeq field in SEND_SAS_PRIMITIVE reqs ****/ #define MPI3_CTRL_PRIMFLAGS_SINGLE (0x01) #define MPI3_CTRL_PRIMFLAGS_TRIPLE (0x03) #define MPI3_CTRL_PRIMFLAGS_REDUNDANT (0x06) /**** Definitions for the Action field in PCIE_LINK_CONTROL and SAS_PHY_CONTROL reqs ****/ #define MPI3_CTRL_ACTION_NOP (0x00) #define MPI3_CTRL_ACTION_LINK_RESET (0x01) #define MPI3_CTRL_ACTION_HARD_RESET (0x02) #define MPI3_CTRL_ACTION_CLEAR_ERROR_LOG (0x05) typedef struct _MPI3_IOUNIT_CONTROL_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Reserved0A; /* 0x0A */ U8 Operation; /* 0x0B */ U32 Reserved0C; /* 0x0C */ U64 Param64[2]; /* 0x10 */ U32 Param32[4]; /* 0x20 */ U16 Param16[4]; /* 0x30 */ U8 Param8[8]; /* 0x38 */ } MPI3_IOUNIT_CONTROL_REQUEST, MPI3_POINTER PTR_MPI3_IOUNIT_CONTROL_REQUEST, Mpi3IoUnitControlRequest_t, MPI3_POINTER pMpi3IoUnitControlRequest_t; typedef struct _MPI3_IOUNIT_CONTROL_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U64 Value64[2]; /* 0x10 */ U32 Value32[4]; /* 0x20 */ U16 Value16[4]; /* 0x30 */ U8 Value8[8]; /* 0x38 */ } MPI3_IOUNIT_CONTROL_REPLY, MPI3_POINTER PTR_MPI3_IOUNIT_CONTROL_REPLY, Mpi3IoUnitControlReply_t, MPI3_POINTER pMpi3IoUnitControlReply_t; #endif /* MPI30_IOC_H */ diff --git a/sys/dev/mpi3mr/mpi/mpi30_pci.h b/sys/dev/mpi3mr/mpi/mpi30_pci.h index f15dab2a5a9c..008ec7059b76 100644 --- a/sys/dev/mpi3mr/mpi/mpi30_pci.h +++ b/sys/dev/mpi3mr/mpi/mpi30_pci.h @@ -1,97 +1,96 @@ /* - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. + * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved. * Support: * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD * */ - #ifndef MPI30_PCI_H #define MPI30_PCI_H 1 /***************************************************************************** * NVMe Encapsulated Request Message * ****************************************************************************/ #ifndef MPI3_NVME_ENCAP_CMD_MAX #define MPI3_NVME_ENCAP_CMD_MAX (1) #endif /* MPI3_NVME_ENCAP_CMD_MAX */ typedef struct _MPI3_NVME_ENCAPSULATED_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 DevHandle; /* 0x0A */ U16 EncapsulatedCommandLength; /* 0x0C */ U16 Flags; /* 0x0E */ U32 DataLength; /* 0x10 */ U32 Reserved14[3]; /* 0x14 */ U32 Command[MPI3_NVME_ENCAP_CMD_MAX]; /* 0x20 */ /* variable length */ } MPI3_NVME_ENCAPSULATED_REQUEST, MPI3_POINTER PTR_MPI3_NVME_ENCAPSULATED_REQUEST, Mpi3NVMeEncapsulatedRequest_t, MPI3_POINTER pMpi3NVMeEncapsulatedRequest_t; /**** Defines for the Flags field ****/ #define MPI3_NVME_FLAGS_FORCE_ADMIN_ERR_REPLY_MASK (0x0002) #define MPI3_NVME_FLAGS_FORCE_ADMIN_ERR_REPLY_FAIL_ONLY (0x0000) #define MPI3_NVME_FLAGS_FORCE_ADMIN_ERR_REPLY_ALL (0x0002) #define MPI3_NVME_FLAGS_SUBMISSIONQ_MASK (0x0001) #define MPI3_NVME_FLAGS_SUBMISSIONQ_IO (0x0000) #define MPI3_NVME_FLAGS_SUBMISSIONQ_ADMIN (0x0001) /***************************************************************************** * NVMe Encapsulated Error Reply Message * ****************************************************************************/ typedef struct _MPI3_NVME_ENCAPSULATED_ERROR_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U32 NVMeCompletionEntry[4]; /* 0x10 */ } MPI3_NVME_ENCAPSULATED_ERROR_REPLY, MPI3_POINTER PTR_MPI3_NVME_ENCAPSULATED_ERROR_REPLY, Mpi3NVMeEncapsulatedErrorReply_t, MPI3_POINTER pMpi3NVMeEncapsulatedErrorReply_t; #endif /* MPI30_PCI_H */ diff --git a/sys/dev/mpi3mr/mpi/mpi30_raid.h b/sys/dev/mpi3mr/mpi/mpi30_raid.h index fe2c4baffd3c..85941544e8fe 100644 --- a/sys/dev/mpi3mr/mpi/mpi30_raid.h +++ b/sys/dev/mpi3mr/mpi/mpi30_raid.h @@ -1,46 +1,45 @@ /* - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. + * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved. * Support: * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD * */ - #ifndef MPI30_RAID_H #define MPI30_RAID_H 1 #endif /* MPI30_RAID_H */ diff --git a/sys/dev/mpi3mr/mpi/mpi30_sas.h b/sys/dev/mpi3mr/mpi/mpi30_sas.h index c28de07c9fdd..fc55fba4747f 100644 --- a/sys/dev/mpi3mr/mpi/mpi30_sas.h +++ b/sys/dev/mpi3mr/mpi/mpi30_sas.h @@ -1,99 +1,98 @@ /* - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. + * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved. * Support: * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD * */ - #ifndef MPI30_SAS_H #define MPI30_SAS_H 1 /***************************************************************************** * SAS Device Info Definitions * ****************************************************************************/ #define MPI3_SAS_DEVICE_INFO_SSP_TARGET (0x00000100) #define MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET (0x00000080) #define MPI3_SAS_DEVICE_INFO_SMP_TARGET (0x00000040) #define MPI3_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000020) #define MPI3_SAS_DEVICE_INFO_STP_INITIATOR (0x00000010) #define MPI3_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000008) #define MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK (0x00000007) #define MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_NO_DEVICE (0x00000000) #define MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE (0x00000001) #define MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_EXPANDER (0x00000002) /***************************************************************************** * SMP Passthrough Request Message * ****************************************************************************/ typedef struct _MPI3_SMP_PASSTHROUGH_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Reserved0A; /* 0x0A */ U8 IOUnitPort; /* 0x0B */ U32 Reserved0C[3]; /* 0x0C */ U64 SASAddress; /* 0x18 */ MPI3_SGE_SIMPLE RequestSGE; /* 0x20 */ MPI3_SGE_SIMPLE ResponseSGE; /* 0x30 */ } MPI3_SMP_PASSTHROUGH_REQUEST, MPI3_POINTER PTR_MPI3_SMP_PASSTHROUGH_REQUEST, Mpi3SmpPassthroughRequest_t, MPI3_POINTER pMpi3SmpPassthroughRequest_t; /***************************************************************************** * SMP Passthrough Reply Message * ****************************************************************************/ typedef struct _MPI3_SMP_PASSTHROUGH_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U16 ResponseDataLength; /* 0x10 */ U16 Reserved12; /* 0x12 */ } MPI3_SMP_PASSTHROUGH_REPLY, MPI3_POINTER PTR_MPI3_SMP_PASSTHROUGH_REPLY, Mpi3SmpPassthroughReply_t, MPI3_POINTER pMpi3SmpPassthroughReply_t; #endif /* MPI30_SAS_H */ diff --git a/sys/dev/mpi3mr/mpi/mpi30_targ.h b/sys/dev/mpi3mr/mpi/mpi30_targ.h index d9aee48a6437..646b5287d502 100644 --- a/sys/dev/mpi3mr/mpi/mpi30_targ.h +++ b/sys/dev/mpi3mr/mpi/mpi30_targ.h @@ -1,316 +1,318 @@ /* - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. + * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved. * Support: * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD * */ - #ifndef MPI30_TARG_H #define MPI30_TARG_H 1 /***************************************************************************** * Command Buffer Formats * ****************************************************************************/ typedef struct _MPI3_TARGET_SSP_CMD_BUFFER { U8 FrameType; /* 0x00 */ U8 Reserved01; /* 0x01 */ U16 InitiatorConnectionTag; /* 0x02 */ U32 HashedSourceSASAddress; /* 0x04 */ U16 Reserved08; /* 0x08 */ U16 Flags; /* 0x0A */ U32 Reserved0C; /* 0x0C */ U16 Tag; /* 0x10 */ U16 TargetPortTransferTag; /* 0x12 */ U32 DataOffset; /* 0x14 */ U8 LogicalUnitNumber[8]; /* 0x18 */ U8 Reserved20; /* 0x20 */ U8 TaskAttribute; /* 0x21 */ U8 Reserved22; /* 0x22 */ U8 AdditionalCDBLength; /* 0x23 */ U8 CDB[16]; /* 0x24 */ /* AdditionalCDBBytes field starts here */ /* 0x34 */ } MPI3_TARGET_SSP_CMD_BUFFER, MPI3_POINTER PTR_MPI3_TARGET_SSP_CMD_BUFFER, Mpi3TargetSspCmdBuffer_t, MPI3_POINTER pMpi3TargetSspCmdBuffer_t; typedef struct _MPI3_TARGET_SSP_TASK_BUFFER { U8 FrameType; /* 0x00 */ U8 Reserved01; /* 0x01 */ U16 InitiatorConnectionTag; /* 0x02 */ U32 HashedSourceSASAddress; /* 0x04 */ U16 Reserved08; /* 0x08 */ U16 Flags; /* 0x0A */ U32 Reserved0C; /* 0x0C */ U16 Tag; /* 0x10 */ U16 TargetPortTransferTag; /* 0x12 */ U32 DataOffset; /* 0x14 */ U8 LogicalUnitNumber[8]; /* 0x18 */ U16 Reserved20; /* 0x20 */ U8 TaskManagementFunction; /* 0x22 */ U8 Reserved23; /* 0x23 */ U16 ManagedTaskTag; /* 0x24 */ U16 Reserved26; /* 0x26 */ U32 Reserved28[3]; /* 0x28 */ } MPI3_TARGET_SSP_TASK_BUFFER, MPI3_POINTER PTR_MPI3_TARGET_SSP_TASK_BUFFER, Mpi3TargetSspTaskBuffer_t, MPI3_POINTER pMpi3TargetSspTaskBuffer_t; /**** Defines for the FrameType field ****/ #define MPI3_TARGET_FRAME_TYPE_COMMAND (0x06) #define MPI3_TARGET_FRAME_TYPE_TASK (0x16) /**** Defines for the HashedSourceSASAddress field ****/ #define MPI3_TARGET_HASHED_SAS_ADDRESS_MASK (0xFFFFFF00) #define MPI3_TARGET_HASHED_SAS_ADDRESS_SHIFT (8) /***************************************************************************** * Target Command Buffer Post Base Request Message * ****************************************************************************/ typedef struct _MPI3_TARGET_CMD_BUF_POST_BASE_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 BufferPostFlags; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U16 MinReplyQueueID; /* 0x0C */ U16 MaxReplyQueueID; /* 0x0E */ U64 BaseAddress; /* 0x10 */ U16 CmdBufferLength; /* 0x18 */ U16 TotalCmdBuffers; /* 0x1A */ U32 Reserved1C; /* 0x1C */ } MPI3_TARGET_CMD_BUF_POST_BASE_REQUEST, MPI3_POINTER PTR_MPI3_TARGET_CMD_BUF_POST_BASE_REQUEST, Mpi3TargetCmdBufPostBaseRequest_t, MPI3_POINTER pMpi3TargetCmdBufPostBaseRequest_t; /**** Defines for the BufferPostFlags field ****/ #define MPI3_CMD_BUF_POST_BASE_FLAGS_DLAS_MASK (0x0C) #define MPI3_CMD_BUF_POST_BASE_FLAGS_DLAS_SYSTEM (0x00) #define MPI3_CMD_BUF_POST_BASE_FLAGS_DLAS_IOCUDP (0x04) #define MPI3_CMD_BUF_POST_BASE_FLAGS_DLAS_IOCCTL (0x08) #define MPI3_CMD_BUF_POST_BASE_FLAGS_AUTO_POST_ALL (0x01) /**** Defines for the CmdBufferLength field ****/ #define MPI3_CMD_BUF_POST_BASE_MIN_BUF_LENGTH (0x34) #define MPI3_CMD_BUF_POST_BASE_MAX_BUF_LENGTH (0x3FC) /***************************************************************************** * Target Command Buffer Post List Request Message * ****************************************************************************/ typedef struct _MPI3_TARGET_CMD_BUF_POST_LIST_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U8 CmdBufferCount; /* 0x0C */ U8 Reserved0D[3]; /* 0x0D */ U16 IoIndex[2]; /* 0x10 */ } MPI3_TARGET_CMD_BUF_POST_LIST_REQUEST, MPI3_POINTER PTR_MPI3_TARGET_CMD_BUF_POST_LIST_REQUEST, Mpi3TargetCmdBufPostListRequest_t, MPI3_POINTER pMpi3TargetCmdBufPostListRequest_t; /***************************************************************************** * Target Command Buffer Post Base List Reply Message * ****************************************************************************/ typedef struct _MPI3_TARGET_CMD_BUF_POST_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U8 CmdBufferCount; /* 0x10 */ U8 Reserved11[3]; /* 0x11 */ U16 IoIndex[2]; /* 0x14 */ } MPI3_TARGET_CMD_BUF_POST_REPLY, MPI3_POINTER PTR_MPI3_TARGET_CMD_BUF_POST_REPLY, Mpi3TargetCmdBufPostReply_t, MPI3_POINTER pMpi3TargetCmdBufPostReply_t; /***************************************************************************** * Target Assist Request Message * ****************************************************************************/ typedef struct _MPI3_TARGET_ASSIST_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 DevHandle; /* 0x0A */ U32 Flags; /* 0x0C */ U16 Reserved10; /* 0x10 */ U16 QueueTag; /* 0x12 */ U16 IoIndex; /* 0x14 */ U16 InitiatorConnectionTag; /* 0x16 */ - U32 SkipCount; /* 0x18 */ + U32 IOCUseOnly18; /* 0x18 */ U32 DataLength; /* 0x1C */ U32 PortTransferLength; /* 0x20 */ U32 PrimaryReferenceTag; /* 0x24 */ U16 PrimaryApplicationTag; /* 0x28 */ U16 PrimaryApplicationTagMask; /* 0x2A */ U32 RelativeOffset; /* 0x2C */ MPI3_SGE_UNION SGL[5]; /* 0x30 */ } MPI3_TARGET_ASSIST_REQUEST, MPI3_POINTER PTR_MPI3_TARGET_ASSIST_REQUEST, Mpi3TargetAssistRequest_t, MPI3_POINTER pMpi3TargetAssistRequest_t; /**** Defines for the MsgFlags field ****/ #define MPI3_TARGET_ASSIST_MSGFLAGS_METASGL_VALID (0x80) /**** Defines for the Flags field ****/ +#define MPI3_TARGET_ASSIST_FLAGS_IOC_USE_ONLY_23_MASK (0x00800000) +#define MPI3_TARGET_ASSIST_FLAGS_IOC_USE_ONLY_22_MASK (0x00400000) #define MPI3_TARGET_ASSIST_FLAGS_REPOST_CMD_BUFFER (0x00200000) #define MPI3_TARGET_ASSIST_FLAGS_AUTO_STATUS (0x00100000) #define MPI3_TARGET_ASSIST_FLAGS_DATADIRECTION_MASK (0x000C0000) #define MPI3_TARGET_ASSIST_FLAGS_DATADIRECTION_WRITE (0x00040000) #define MPI3_TARGET_ASSIST_FLAGS_DATADIRECTION_READ (0x00080000) #define MPI3_TARGET_ASSIST_FLAGS_DMAOPERATION_MASK (0x00030000) #define MPI3_TARGET_ASSIST_FLAGS_DMAOPERATION_HOST_PI (0x00010000) /**** Defines for the SGL field ****/ #define MPI3_TARGET_ASSIST_METASGL_INDEX (4) /***************************************************************************** * Target Status Send Request Message * ****************************************************************************/ typedef struct _MPI3_TARGET_STATUS_SEND_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 DevHandle; /* 0x0A */ U16 ResponseIULength; /* 0x0C */ U16 Flags; /* 0x0E */ U16 Reserved10; /* 0x10 */ U16 QueueTag; /* 0x12 */ U16 IoIndex; /* 0x14 */ U16 InitiatorConnectionTag; /* 0x16 */ U32 IOCUseOnly18[6]; /* 0x18 */ U32 IOCUseOnly30[4]; /* 0x30 */ MPI3_SGE_UNION SGL; /* 0x40 */ } MPI3_TARGET_STATUS_SEND_REQUEST, MPI3_POINTER PTR_MPI3_TARGET_STATUS_SEND_REQUEST, Mpi3TargetStatusSendRequest_t, MPI3_POINTER pMpi3TargetStatusSendRequest_t; /**** Defines for the Flags field ****/ +#define MPI3_TSS_FLAGS_IOC_USE_ONLY_6_MASK (0x0040) #define MPI3_TSS_FLAGS_REPOST_CMD_BUFFER (0x0020) #define MPI3_TSS_FLAGS_AUTO_SEND_GOOD_STATUS (0x0010) /***************************************************************************** * Standard Target Mode Reply Message * ****************************************************************************/ typedef struct _MPI3_TARGET_STANDARD_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U32 TransferCount; /* 0x10 */ } MPI3_TARGET_STANDARD_REPLY, MPI3_POINTER PTR_MPI3_TARGET_STANDARD_REPLY, Mpi3TargetStandardReply_t, MPI3_POINTER pMpi3TargetStandardReply_t; /***************************************************************************** * Target Mode Abort Request Message * ****************************************************************************/ typedef struct _MPI3_TARGET_MODE_ABORT_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 AbortType; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U16 RequestQueueIDToAbort; /* 0x0C */ U16 HostTagToAbort; /* 0x0E */ U16 DevHandle; /* 0x10 */ U8 IOCUseOnly12; /* 0x12 */ U8 Reserved13; /* 0x13 */ } MPI3_TARGET_MODE_ABORT_REQUEST, MPI3_POINTER PTR_MPI3_TARGET_MODE_ABORT_REQUEST, Mpi3TargetModeAbortRequest_t, MPI3_POINTER pMpi3TargetModeAbortRequest_t; /**** Defines for the AbortType field ****/ #define MPI3_TARGET_MODE_ABORT_ALL_CMD_BUFFERS (0x00) #define MPI3_TARGET_MODE_ABORT_EXACT_IO_REQUEST (0x01) #define MPI3_TARGET_MODE_ABORT_ALL_COMMANDS (0x02) /***************************************************************************** * Target Mode Abort Reply Message * ****************************************************************************/ typedef struct _MPI3_TARGET_MODE_ABORT_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U32 AbortCount; /* 0x10 */ } MPI3_TARGET_MODE_ABORT_REPLY, MPI3_POINTER PTR_MPI3_TARGET_MODE_ABORT_REPLY, Mpi3TargetModeAbortReply_t, MPI3_POINTER pMpi3TargetModeAbortReply_t; #endif /* MPI30_TARG_H */ diff --git a/sys/dev/mpi3mr/mpi/mpi30_tool.h b/sys/dev/mpi3mr/mpi/mpi30_tool.h index 55fb53601863..e11ddf068555 100644 --- a/sys/dev/mpi3mr/mpi/mpi30_tool.h +++ b/sys/dev/mpi3mr/mpi/mpi30_tool.h @@ -1,476 +1,476 @@ /* - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. + * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved. * Support: * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD * */ - #ifndef MPI30_TOOL_H #define MPI30_TOOL_H 1 /***************************************************************************** * Toolbox Messages * *****************************************************************************/ /***************************************************************************** * Clean Tool Request Message * *****************************************************************************/ typedef struct _MPI3_TOOL_CLEAN_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Tool; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 Area; /* 0x0C */ } MPI3_TOOL_CLEAN_REQUEST, MPI3_POINTER PTR_MPI3_TOOL_CLEAN_REQUEST, Mpi3ToolCleanRequest_t, MPI3_POINTER pMpi3ToolCleanRequest_t; /**** Defines for the Tool field ****/ #define MPI3_TOOLBOX_TOOL_CLEAN (0x01) #define MPI3_TOOLBOX_TOOL_ISTWI_READ_WRITE (0x02) #define MPI3_TOOLBOX_TOOL_DIAGNOSTIC_CLI (0x03) #define MPI3_TOOLBOX_TOOL_LANE_MARGINING (0x04) #define MPI3_TOOLBOX_TOOL_RECOVER_DEVICE (0x05) #define MPI3_TOOLBOX_TOOL_LOOPBACK (0x06) /**** Bitfield definitions for Area field ****/ #define MPI3_TOOLBOX_CLEAN_AREA_BIOS_BOOT_SERVICES (0x00000008) #define MPI3_TOOLBOX_CLEAN_AREA_ALL_BUT_MFG (0x00000002) #define MPI3_TOOLBOX_CLEAN_AREA_NVSTORE (0x00000001) /***************************************************************************** * ISTWI Read Write Tool Request Message * *****************************************************************************/ typedef struct _MPI3_TOOL_ISTWI_READ_WRITE_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Tool; /* 0x0A */ U8 Flags; /* 0x0B */ U8 DevIndex; /* 0x0C */ U8 Action; /* 0x0D */ U16 Reserved0E; /* 0x0E */ U16 TxDataLength; /* 0x10 */ U16 RxDataLength; /* 0x12 */ U32 Reserved14[3]; /* 0x14 */ MPI3_MAN11_ISTWI_DEVICE_FORMAT IstwiDevice; /* 0x20 */ MPI3_SGE_UNION SGL; /* 0x30 */ } MPI3_TOOL_ISTWI_READ_WRITE_REQUEST, MPI3_POINTER PTR_MPI3_TOOL_ISTWI_READ_WRITE_REQUEST, Mpi3ToolIstwiReadWriteRequest_t, MPI3_POINTER pMpi3ToolIstwiReadWRiteRequest_t; /**** Bitfield definitions for Flags field ****/ #define MPI3_TOOLBOX_ISTWI_FLAGS_AUTO_RESERVE_RELEASE (0x80) #define MPI3_TOOLBOX_ISTWI_FLAGS_ADDRESS_MODE_MASK (0x04) #define MPI3_TOOLBOX_ISTWI_FLAGS_ADDRESS_MODE_DEVINDEX (0x00) #define MPI3_TOOLBOX_ISTWI_FLAGS_ADDRESS_MODE_DEVICE_FIELD (0x04) #define MPI3_TOOLBOX_ISTWI_FLAGS_PAGE_ADDRESS_MASK (0x03) /**** Definitions for the Action field ****/ #define MPI3_TOOLBOX_ISTWI_ACTION_RESERVE_BUS (0x00) #define MPI3_TOOLBOX_ISTWI_ACTION_RELEASE_BUS (0x01) #define MPI3_TOOLBOX_ISTWI_ACTION_RESET (0x02) #define MPI3_TOOLBOX_ISTWI_ACTION_READ_DATA (0x03) #define MPI3_TOOLBOX_ISTWI_ACTION_WRITE_DATA (0x04) #define MPI3_TOOLBOX_ISTWI_ACTION_SEQUENCE (0x05) /**** Defines for the IstwiDevice field - refer to struct definition in mpi30_cnfg.h ****/ /***************************************************************************** * ISTWI Read Write Tool Reply Message * *****************************************************************************/ typedef struct _MPI3_TOOL_ISTWI_READ_WRITE_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U16 IstwiStatus; /* 0x10 */ U16 Reserved12; /* 0x12 */ U16 TxDataCount; /* 0x14 */ U16 RxDataCount; /* 0x16 */ } MPI3_TOOL_ISTWI_READ_WRITE_REPLY, MPI3_POINTER PTR_MPI3_TOOL_ISTWI_READ_WRITE_REPLY, Mpi3ToolIstwiReadWriteReply_t, MPI3_POINTER pMpi3ToolIstwiReadWRiteReply_t; /***************************************************************************** * Diagnostic CLI Tool Request Message * *****************************************************************************/ typedef struct _MPI3_TOOL_DIAGNOSTIC_CLI_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Tool; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 CommandDataLength; /* 0x0C */ U32 ResponseDataLength; /* 0x10 */ U32 Reserved14[3]; /* 0x14 */ MPI3_SGE_UNION SGL; /* 0x20 */ } MPI3_TOOL_DIAGNOSTIC_CLI_REQUEST, MPI3_POINTER PTR_MPI3_TOOL_DIAGNOSTIC_CLI_REQUEST, Mpi3ToolDiagnosticCliRequest_t, MPI3_POINTER pMpi3ToolDiagnosticCliRequest_t; /***************************************************************************** * Diagnostic CLI Tool Reply Message * *****************************************************************************/ typedef struct _MPI3_TOOL_DIAGNOSTIC_CLI_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U32 ReturnedDataLength; /* 0x10 */ } MPI3_TOOL_DIAGNOSTIC_CLI_REPLY, MPI3_POINTER PTR_MPI3_TOOL_DIAGNOSTIC_CLI_REPLY, Mpi3ToolDiagnosticCliReply_t, MPI3_POINTER pMpi3ToolDiagnosticCliReply_t; /***************************************************************************** * Lane Margining Tool Request Message * *****************************************************************************/ typedef struct _MPI3_TOOL_LANE_MARGIN_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Tool; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U8 Action; /* 0x0C */ U8 SwitchPort; /* 0x0D */ U16 DevHandle; /* 0x0E */ U8 StartLane; /* 0x10 */ U8 NumLanes; /* 0x11 */ U16 Reserved12; /* 0x12 */ U32 Reserved14[3]; /* 0x14 */ MPI3_SGE_UNION SGL; /* 0x20 */ } MPI3_TOOL_LANE_MARGIN_REQUEST, MPI3_POINTER PTR_MPI3_TOOL_LANE_MARGIN_REQUEST, Mpi3ToolIstwiLaneMarginRequest_t, MPI3_POINTER pMpi3ToolLaneMarginRequest_t; /**** Definitions for the Action field ****/ #define MPI3_TOOLBOX_LM_ACTION_ENTER (0x00) #define MPI3_TOOLBOX_LM_ACTION_EXIT (0x01) #define MPI3_TOOLBOX_LM_ACTION_READ (0x02) #define MPI3_TOOLBOX_LM_ACTION_WRITE (0x03) typedef struct _MPI3_LANE_MARGIN_ELEMENT { U16 Control; /* 0x00 */ U16 Status; /* 0x02 */ } MPI3_LANE_MARGIN_ELEMENT, MPI3_POINTER PTR_MPI3_LANE_MARGIN_ELEMENT, Mpi3LaneMarginElement_t, MPI3_POINTER pMpi3LaneMarginElement_t; /***************************************************************************** * Lane Margining Tool Reply Message * *****************************************************************************/ typedef struct _MPI3_TOOL_LANE_MARGIN_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U32 ReturnedDataLength; /* 0x10 */ } MPI3_TOOL_LANE_MARGIN_REPLY, MPI3_POINTER PTR_MPI3_TOOL_LANE_MARGIN_REPLY, Mpi3ToolLaneMarginReply_t, MPI3_POINTER pMpi3ToolLaneMarginReply_t; /***************************************************************************** * Recover Device Request Message * *****************************************************************************/ typedef struct _MPI3_TOOL_RECOVER_DEVICE_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Tool; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U8 Action; /* 0x0C */ U8 Reserved0D; /* 0x0D */ U16 DevHandle; /* 0x0E */ } MPI3_TOOL_RECOVER_DEVICE_REQUEST, MPI3_POINTER PTR_MPI3_TOOL_RECOVER_DEVICE_REQUEST, Mpi3ToolRecoverDeviceRequest_t, MPI3_POINTER pMpi3ToolRecoverDeviceRequest_t; /**** Bitfield definitions for the Action field ****/ #define MPI3_TOOLBOX_RD_ACTION_START (0x01) #define MPI3_TOOLBOX_RD_ACTION_GET_STATUS (0x02) #define MPI3_TOOLBOX_RD_ACTION_ABORT (0x03) /***************************************************************************** * Recover Device Reply Message * *****************************************************************************/ typedef struct _MPI3_TOOL_RECOVER_DEVICE_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U8 Status; /* 0x10 */ U8 Reserved11; /* 0x11 */ U16 Reserved1C; /* 0x12 */ } MPI3_TOOL_RECOVER_DEVICE_REPLY, MPI3_POINTER PTR_MPI3_TOOL_RECOVER_DEVICE_REPLY, Mpi3ToolRecoverDeviceReply_t, MPI3_POINTER pMpi3ToolRecoverDeviceReply_t; /**** Bitfield definitions for the Status field ****/ #define MPI3_TOOLBOX_RD_STATUS_NOT_NEEDED (0x01) #define MPI3_TOOLBOX_RD_STATUS_NEEDED (0x02) #define MPI3_TOOLBOX_RD_STATUS_IN_PROGRESS (0x03) #define MPI3_TOOLBOX_RD_STATUS_ABORTING (0x04) /***************************************************************************** * Loopback Tool Request Message * *****************************************************************************/ typedef struct _MPI3_TOOL_LOOPBACK_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U8 Tool; /* 0x0A */ U8 Reserved0B; /* 0x0B */ U32 Reserved0C; /* 0x0C */ U64 Phys; /* 0x10 */ } MPI3_TOOL_LOOPBACK_REQUEST, MPI3_POINTER PTR_MPI3_TOOL_LOOPBACK_REQUEST, Mpi3ToolLoopbackRequest_t, MPI3_POINTER pMpi3ToolLoopbackRequest_t; /***************************************************************************** * Loopback Tool Reply Message * *****************************************************************************/ typedef struct _MPI3_TOOL_LOOPBACK_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U64 TestedPhys; /* 0x10 */ U64 FailedPhys; /* 0x18 */ } MPI3_TOOL_LOOPBACK_REPLY, MPI3_POINTER PTR_MPI3_TOOL_LOOPBACK_REPLY, Mpi3ToolLoopbackReply_t, MPI3_POINTER pMpi3ToolLoopbackReply_t; /***************************************************************************** * Diagnostic Buffer Messages * *****************************************************************************/ /***************************************************************************** * Diagnostic Buffer Post Request Message * *****************************************************************************/ typedef struct _MPI3_DIAG_BUFFER_POST_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U8 Type; /* 0x0C */ U8 Reserved0D; /* 0x0D */ U16 Reserved0E; /* 0x0E */ U64 Address; /* 0x10 */ U32 Length; /* 0x18 */ U32 Reserved1C; /* 0x1C */ } MPI3_DIAG_BUFFER_POST_REQUEST, MPI3_POINTER PTR_MPI3_DIAG_BUFFER_POST_REQUEST, Mpi3DiagBufferPostRequest_t, MPI3_POINTER pMpi3DiagBufferPostRequest_t; /**** Defines for the MsgFlags field ****/ #define MPI3_DIAG_BUFFER_POST_MSGFLAGS_SEGMENTED (0x01) /**** Defines for the Type field ****/ #define MPI3_DIAG_BUFFER_TYPE_TRACE (0x01) #define MPI3_DIAG_BUFFER_TYPE_FW (0x02) #define MPI3_DIAG_BUFFER_TYPE_DRIVER (0x10) #define MPI3_DIAG_BUFFER_TYPE_FDL (0x20) +#define MPI3_DIAG_BUFFER_TYPE_TTY (0x30) #define MPI3_DIAG_BUFFER_MIN_PRODUCT_SPECIFIC (0xF0) #define MPI3_DIAG_BUFFER_MAX_PRODUCT_SPECIFIC (0xFF) /***************************************************************************** * DRIVER DIAGNOSTIC Buffer * *****************************************************************************/ typedef struct _MPI3_DRIVER_BUFFER_HEADER { U32 Signature; /* 0x00 */ U16 HeaderSize; /* 0x04 */ U16 RTTFileHeaderOffset; /* 0x06 */ U32 Flags; /* 0x08 */ U32 CircularBufferSize; /* 0x0C */ U32 LogicalBufferEnd; /* 0x10 */ U32 LogicalBufferStart; /* 0x14 */ U32 IOCUseOnly18[2]; /* 0x18 */ U32 Reserved20[760]; /* 0x20 - 0xBFC */ U32 ReservedRTTRACE[256]; /* 0xC00 - 0xFFC */ } MPI3_DRIVER_BUFFER_HEADER, MPI3_POINTER PTR_MPI3_DRIVER_BUFFER_HEADER, Mpi3DriverBufferHeader_t, MPI3_POINTER pMpi3DriverBufferHeader_t; -/**** Defines for the Type field ****/ +/**** Defines for the Signature field ****/ #define MPI3_DRIVER_DIAG_BUFFER_HEADER_SIGNATURE_CIRCULAR (0x43495243) /**** Defines for the Flags field ****/ #define MPI3_DRIVER_DIAG_BUFFER_HEADER_FLAGS_CIRCULAR_BUF_FORMAT_MASK (0x00000003) #define MPI3_DRIVER_DIAG_BUFFER_HEADER_FLAGS_CIRCULAR_BUF_FORMAT_ASCII (0x00000000) #define MPI3_DRIVER_DIAG_BUFFER_HEADER_FLAGS_CIRCULAR_BUF_FORMAT_RTTRACE (0x00000001) /***************************************************************************** * Diagnostic Buffer Manage Request Message * *****************************************************************************/ typedef struct _MPI3_DIAG_BUFFER_MANAGE_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U8 Type; /* 0x0C */ U8 Action; /* 0x0D */ U16 Reserved0E; /* 0x0E */ } MPI3_DIAG_BUFFER_MANAGE_REQUEST, MPI3_POINTER PTR_MPI3_DIAG_BUFFER_MANAGE_REQUEST, Mpi3DiagBufferManageRequest_t, MPI3_POINTER pMpi3DiagBufferManageRequest_t; /**** Defines for the Type field - use MPI3_DIAG_BUFFER_TYPE_ values ****/ /**** Defined for the Action field ****/ #define MPI3_DIAG_BUFFER_ACTION_RELEASE (0x01) #define MPI3_DIAG_BUFFER_ACTION_PAUSE (0x02) #define MPI3_DIAG_BUFFER_ACTION_RESUME (0x03) /***************************************************************************** * Diagnostic Buffer Upload Request Message * *****************************************************************************/ typedef struct _MPI3_DIAG_BUFFER_UPLOAD_REQUEST { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 Reserved0A; /* 0x0A */ U8 Type; /* 0x0C */ U8 Flags; /* 0x0D */ U16 Reserved0E; /* 0x0E */ U64 Context; /* 0x10 */ U32 Reserved18; /* 0x18 */ U32 Reserved1C; /* 0x1C */ MPI3_SGE_UNION SGL; /* 0x20 */ } MPI3_DIAG_BUFFER_UPLOAD_REQUEST, MPI3_POINTER PTR_MPI3_DIAG_BUFFER_UPLOAD_REQUEST, Mpi3DiagBufferUploadRequest_t, MPI3_POINTER pMpi3DiagBufferUploadRequest_t; /**** Defines for the Type field - use MPI3_DIAG_BUFFER_TYPE_ values ****/ /**** Defined for the Flags field ****/ #define MPI3_DIAG_BUFFER_UPLOAD_FLAGS_FORMAT_MASK (0x01) #define MPI3_DIAG_BUFFER_UPLOAD_FLAGS_FORMAT_DECODED (0x00) #define MPI3_DIAG_BUFFER_UPLOAD_FLAGS_FORMAT_ENCODED (0x01) /***************************************************************************** * Diagnostic Buffer Upload Reply Message * *****************************************************************************/ typedef struct _MPI3_DIAG_BUFFER_UPLOAD_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ U64 Context; /* 0x10 */ U32 ReturnedDataLength; /* 0x18 */ U32 Reserved1C; /* 0x1C */ } MPI3_DIAG_BUFFER_UPLOAD_REPLY, MPI3_POINTER PTR_MPI3_DIAG_BUFFER_UPLOAD_REPLY, Mpi3DiagBufferUploadReply_t, MPI3_POINTER pMpi3DiagBufferUploadReply_t; #endif /* MPI30_TOOL_H */ diff --git a/sys/dev/mpi3mr/mpi/mpi30_transport.h b/sys/dev/mpi3mr/mpi/mpi30_transport.h index 436496411309..860c27a2dd42 100644 --- a/sys/dev/mpi3mr/mpi/mpi30_transport.h +++ b/sys/dev/mpi3mr/mpi/mpi30_transport.h @@ -1,748 +1,743 @@ /* - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. + * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved. * Support: * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD * - */ - -/* - * Version History + * + * Version History * --------------- * * Date Version Description * -------- ----------- ------------------------------------------------------ * 11-30-18 03.00.00.08 Corresponds to Fusion-MPT MPI 3.0 Specification Rev H. * 02-08-19 03.00.00.09 Corresponds to Fusion-MPT MPI 3.0 Specification Rev I. * 05-03-19 03.00.00.10 Corresponds to Fusion-MPT MPI 3.0 Specification Rev J. * 08-30-19 03.00.00.12 Corresponds to Fusion-MPT MPI 3.0 Specification Rev L. * 11-01-19 03.00.00.13 Corresponds to Fusion-MPT MPI 3.0 Specification Rev M. * 12-16-19 03.00.00.14 Corresponds to Fusion-MPT MPI 3.0 Specification Rev N. * 02-28-20 03.00.00.15 Corresponds to Fusion-MPT MPI 3.0 Specification Rev O. * 05-01-20 03.00.00.16 Corresponds to Fusion-MPT MPI 3.0 Specification Rev P. * 06-26-20 03.00.00.17 Corresponds to Fusion-MPT MPI 3.0 Specification Rev Q. * 08-28-20 03.00.00.18 Corresponds to Fusion-MPT MPI 3.0 Specification Rev R. * 10-30-20 03.00.00.19 Corresponds to Fusion-MPT MPI 3.0 Specification Rev S. * 12-18-20 03.00.00.20 Corresponds to Fusion-MPT MPI 3.0 Specification Rev T. * 02-09-21 03.00.20.01 Corresponds to Fusion-MPT MPI 3.0 Specification Rev T - Interim Release 1. * 02-26-21 03.00.21.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev U. * 04-16-21 03.00.21.01 Corresponds to Fusion-MPT MPI 3.0 Specification Rev U - Interim Release 1. * 04-28-21 03.00.21.02 Corresponds to Fusion-MPT MPI 3.0 Specification Rev U - Interim Release 2. * 05-28-21 03.00.22.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev V. * 07-23-21 03.00.22.01 Corresponds to Fusion-MPT MPI 3.0 Specification Rev V - Interim Release 1. * 09-03-21 03.00.23.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 23. * 10-23-21 03.00.23.01 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 23 - Interim Release 1. * 12-03-21 03.00.24.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 24. * 02-25-22 03.00.25.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 25. * 06-03-22 03.00.26.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 26. * 08-09-22 03.00.26.01 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 26 - Interim Release 1. * 09-02-22 03.00.27.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 27. * 10-20-22 03.00.27.01 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 27 - Interim Release 1. * 12-02-22 03.00.28.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 28. - * 02-24-22 03.00.29.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 29. + * 02-24-23 03.00.29.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 29. + * 05-19-23 03.00.30.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 30. + * 08-18-23 03.00.30.01 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 30 - Interim Release 1. + * 11-17-23 03.00.31.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 31 + * 02-16-24 03.00.32.00 Corresponds to Fusion-MPT MPI 3.0 Specification Rev 32 */ #ifndef MPI30_TRANSPORT_H #define MPI30_TRANSPORT_H 1 /***************************************************************************** * Common version structure/union used in * * messages and configuration pages * ****************************************************************************/ typedef struct _MPI3_VERSION_STRUCT { U8 Dev; /* 0x00 */ U8 Unit; /* 0x01 */ U8 Minor; /* 0x02 */ U8 Major; /* 0x03 */ } MPI3_VERSION_STRUCT, MPI3_POINTER PTR_MPI3_VERSION_STRUCT, Mpi3VersionStruct_t, MPI3_POINTER pMpi3VersionStruct_t; typedef union _MPI3_VERSION_UNION { MPI3_VERSION_STRUCT Struct; U32 Word; } MPI3_VERSION_UNION, MPI3_POINTER PTR_MPI3_VERSION_UNION, Mpi3VersionUnion_t, MPI3_POINTER pMpi3VersionUnion_t; /****** Version constants for this revision ****/ #define MPI3_VERSION_MAJOR (3) #define MPI3_VERSION_MINOR (0) -#define MPI3_VERSION_UNIT (29) +#define MPI3_VERSION_UNIT (32) #define MPI3_VERSION_DEV (0) /****** DevHandle definitions *****/ #define MPI3_DEVHANDLE_INVALID (0xFFFF) /***************************************************************************** * System Interface Register Definitions * ****************************************************************************/ typedef struct _MPI3_SYSIF_OPER_QUEUE_INDEXES { U16 ProducerIndex; /* 0x00 */ U16 Reserved02; /* 0x02 */ U16 ConsumerIndex; /* 0x04 */ U16 Reserved06; /* 0x06 */ } MPI3_SYSIF_OPER_QUEUE_INDEXES, MPI3_POINTER PTR_MPI3_SYSIF_OPER_QUEUE_INDEXES; typedef volatile struct _MPI3_SYSIF_REGISTERS { U64 IOCInformation; /* 0x00 */ MPI3_VERSION_UNION Version; /* 0x08 */ U32 Reserved0C[2]; /* 0x0C */ U32 IOCConfiguration; /* 0x14 */ U32 Reserved18; /* 0x18 */ U32 IOCStatus; /* 0x1C */ U32 Reserved20; /* 0x20 */ U32 AdminQueueNumEntries; /* 0x24 */ U64 AdminRequestQueueAddress; /* 0x28 */ U64 AdminReplyQueueAddress; /* 0x30 */ U32 Reserved38[2]; /* 0x38 */ U32 CoalesceControl; /* 0x40 */ U32 Reserved44[1007]; /* 0x44 */ U16 AdminRequestQueuePI; /* 0x1000 */ U16 Reserved1002; /* 0x1002 */ U16 AdminReplyQueueCI; /* 0x1004 */ U16 Reserved1006; /* 0x1006 */ MPI3_SYSIF_OPER_QUEUE_INDEXES OperQueueIndexes[383]; /* 0x1008 */ U32 Reserved1C00; /* 0x1C00 */ U32 WriteSequence; /* 0x1C04 */ U32 HostDiagnostic; /* 0x1C08 */ U32 Reserved1C0C; /* 0x1C0C */ U32 Fault; /* 0x1C10 */ U32 FaultInfo[3]; /* 0x1C14 */ U32 Reserved1C20[4]; /* 0x1C20 */ U64 HCBAddress; /* 0x1C30 */ U32 HCBSize; /* 0x1C38 */ U32 Reserved1C3C; /* 0x1C3C */ U32 ReplyFreeHostIndex; /* 0x1C40 */ U32 SenseBufferFreeHostIndex; /* 0x1C44 */ U32 Reserved1C48[2]; /* 0x1C48 */ U64 DiagRWData; /* 0x1C50 */ U64 DiagRWAddress; /* 0x1C58 */ U16 DiagRWControl; /* 0x1C60 */ U16 DiagRWStatus; /* 0x1C62 */ U32 Reserved1C64[35]; /* 0x1C64 */ U32 Scratchpad[4]; /* 0x1CF0 */ U32 Reserved1D00[192]; /* 0x1D00 */ U32 DeviceAssignedRegisters[2048]; /* 0x2000 */ } MPI3_SYSIF_REGS, MPI3_POINTER PTR_MPI3_SYSIF_REGS, Mpi3SysIfRegs_t, MPI3_POINTER pMpi3SysIfRegs_t; /**** Defines for the IOCInformation register ****/ #define MPI3_SYSIF_IOC_INFO_LOW_OFFSET (0x00000000) #define MPI3_SYSIF_IOC_INFO_HIGH_OFFSET (0x00000004) #define MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_MASK (0xFF000000) #define MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_SHIFT (24) #define MPI3_SYSIF_IOC_INFO_LOW_HCB_DISABLED (0x00000001) /**** Defines for the IOCConfiguration register ****/ #define MPI3_SYSIF_IOC_CONFIG_OFFSET (0x00000014) #define MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ (0x00F00000) #define MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ_SHIFT (20) #define MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ (0x000F0000) #define MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ_SHIFT (16) #define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_MASK (0x0000C000) #define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NO (0x00000000) #define MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL (0x00004000) #define MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ (0x00002000) #define MPI3_SYSIF_IOC_CONFIG_DIAG_SAVE (0x00000010) #define MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC (0x00000001) /**** Defines for the IOCStatus register ****/ #define MPI3_SYSIF_IOC_STATUS_OFFSET (0x0000001C) #define MPI3_SYSIF_IOC_STATUS_RESET_HISTORY (0x00000010) #define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK (0x0000000C) #define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_SHIFT (0x00000002) #define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_NONE (0x00000000) #define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS (0x00000004) #define MPI3_SYSIF_IOC_STATUS_SHUTDOWN_COMPLETE (0x00000008) #define MPI3_SYSIF_IOC_STATUS_FAULT (0x00000002) #define MPI3_SYSIF_IOC_STATUS_READY (0x00000001) /**** Defines for the AdminQueueNumEntries register ****/ #define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_OFFSET (0x00000024) #define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REQ_MASK (0x0FFF) #define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REPLY_OFFSET (0x00000026) #define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REPLY_MASK (0x0FFF0000) #define MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_REPLY_SHIFT (16) /**** Defines for the AdminRequestQueueAddress register ****/ #define MPI3_SYSIF_ADMIN_REQ_Q_ADDR_LOW_OFFSET (0x00000028) #define MPI3_SYSIF_ADMIN_REQ_Q_ADDR_HIGH_OFFSET (0x0000002C) /**** Defines for the AdminReplyQueueAddress register ****/ #define MPI3_SYSIF_ADMIN_REPLY_Q_ADDR_LOW_OFFSET (0x00000030) #define MPI3_SYSIF_ADMIN_REPLY_Q_ADDR_HIGH_OFFSET (0x00000034) /**** Defines for the CoalesceControl register ****/ #define MPI3_SYSIF_COALESCE_CONTROL_OFFSET (0x00000040) #define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_MASK (0xC0000000) #define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_NO_CHANGE (0x00000000) #define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_DISABLE (0x40000000) #define MPI3_SYSIF_COALESCE_CONTROL_ENABLE_ENABLE (0xC0000000) #define MPI3_SYSIF_COALESCE_CONTROL_VALID (0x20000000) #define MPI3_SYSIF_COALESCE_CONTROL_MSIX_IDX_MASK (0x01FF0000) #define MPI3_SYSIF_COALESCE_CONTROL_MSIX_IDX_SHIFT (16) #define MPI3_SYSIF_COALESCE_CONTROL_TIMEOUT_MASK (0x0000FF00) #define MPI3_SYSIF_COALESCE_CONTROL_TIMEOUT_SHIFT (8) #define MPI3_SYSIF_COALESCE_CONTROL_DEPTH_MASK (0x000000FF) #define MPI3_SYSIF_COALESCE_CONTROL_DEPTH_SHIFT (0) /**** Defines for the AdminRequestQueuePI register ****/ #define MPI3_SYSIF_ADMIN_REQ_Q_PI_OFFSET (0x00001000) /**** Defines for the AdminReplyQueueCI register ****/ #define MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET (0x00001004) /**** Defines for the OperationalRequestQueuePI register */ #define MPI3_SYSIF_OPER_REQ_Q_PI_OFFSET (0x00001008) #define MPI3_SYSIF_OPER_REQ_Q_N_PI_OFFSET(N) (MPI3_SYSIF_OPER_REQ_Q_PI_OFFSET + (((N)-1)*8)) /* N = 1, 2, 3, ..., 255 */ /**** Defines for the OperationalReplyQueueCI register */ #define MPI3_SYSIF_OPER_REPLY_Q_CI_OFFSET (0x0000100C) #define MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(N) (MPI3_SYSIF_OPER_REPLY_Q_CI_OFFSET + (((N)-1)*8)) /* N = 1, 2, 3, ..., 255 */ /**** Defines for the WriteSequence register *****/ #define MPI3_SYSIF_WRITE_SEQUENCE_OFFSET (0x00001C04) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_MASK (0x0000000F) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_FLUSH (0x0) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_1ST (0xF) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND (0x4) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_3RD (0xB) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_4TH (0x2) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_5TH (0x7) #define MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_6TH (0xD) /**** Defines for the HostDiagnostic register *****/ #define MPI3_SYSIF_HOST_DIAG_OFFSET (0x00001C08) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_MASK (0x00000700) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_NO_RESET (0x00000000) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET (0x00000100) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_HOST_CONTROL_BOOT_RESET (0x00000200) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_COMPLETE_RESET (0x00000300) #define MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT (0x00000700) #define MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS (0x00000080) #define MPI3_SYSIF_HOST_DIAG_SECURE_BOOT (0x00000040) #define MPI3_SYSIF_HOST_DIAG_CLEAR_INVALID_FW_IMAGE (0x00000020) #define MPI3_SYSIF_HOST_DIAG_INVALID_FW_IMAGE (0x00000010) #define MPI3_SYSIF_HOST_DIAG_HCBENABLE (0x00000008) #define MPI3_SYSIF_HOST_DIAG_HCBMODE (0x00000004) #define MPI3_SYSIF_HOST_DIAG_DIAG_RW_ENABLE (0x00000002) #define MPI3_SYSIF_HOST_DIAG_DIAG_WRITE_ENABLE (0x00000001) /**** Defines for the Fault register ****/ #define MPI3_SYSIF_FAULT_OFFSET (0x00001C10) #define MPI3_SYSIF_FAULT_CODE_MASK (0x0000FFFF) #define MPI3_SYSIF_FAULT_CODE_DIAG_FAULT_RESET (0x0000F000) #define MPI3_SYSIF_FAULT_CODE_CI_ACTIVATION_RESET (0x0000F001) #define MPI3_SYSIF_FAULT_CODE_SOFT_RESET_IN_PROGRESS (0x0000F002) #define MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED (0x0000F003) #define MPI3_SYSIF_FAULT_CODE_SOFT_RESET_NEEDED (0x0000F004) #define MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED (0x0000F005) #define MPI3_SYSIF_FAULT_CODE_TEMP_THRESHOLD_EXCEEDED (0x0000F006) /**** Defines for FaultCodeAdditionalInfo registers ****/ #define MPI3_SYSIF_FAULT_INFO0_OFFSET (0x00001C14) #define MPI3_SYSIF_FAULT_INFO1_OFFSET (0x00001C18) #define MPI3_SYSIF_FAULT_INFO2_OFFSET (0x00001C1C) /**** Defines for HCBAddress register ****/ #define MPI3_SYSIF_HCB_ADDRESS_LOW_OFFSET (0x00001C30) #define MPI3_SYSIF_HCB_ADDRESS_HIGH_OFFSET (0x00001C34) /**** Defines for HCBSize register ****/ #define MPI3_SYSIF_HCB_SIZE_OFFSET (0x00001C38) #define MPI3_SYSIF_HCB_SIZE_SIZE_MASK (0xFFFFF000) #define MPI3_SYSIF_HCB_SIZE_SIZE_SHIFT (12) #define MPI3_SYSIF_HCB_SIZE_HCDW_ENABLE (0x00000001) /**** Defines for ReplyFreeHostIndex register ****/ #define MPI3_SYSIF_REPLY_FREE_HOST_INDEX_OFFSET (0x00001C40) /**** Defines for SenseBufferFreeHostIndex register ****/ #define MPI3_SYSIF_SENSE_BUF_FREE_HOST_INDEX_OFFSET (0x00001C44) /**** Defines for DiagRWData register ****/ #define MPI3_SYSIF_DIAG_RW_DATA_LOW_OFFSET (0x00001C50) #define MPI3_SYSIF_DIAG_RW_DATA_HIGH_OFFSET (0x00001C54) /**** Defines for DiagRWAddress ****/ #define MPI3_SYSIF_DIAG_RW_ADDRESS_LOW_OFFSET (0x00001C58) #define MPI3_SYSIF_DIAG_RW_ADDRESS_HIGH_OFFSET (0x00001C5C) /**** Defines for DiagRWControl register ****/ #define MPI3_SYSIF_DIAG_RW_CONTROL_OFFSET (0x00001C60) #define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_MASK (0x00000030) #define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_1BYTE (0x00000000) #define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_2BYTES (0x00000010) #define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_4BYTES (0x00000020) #define MPI3_SYSIF_DIAG_RW_CONTROL_LEN_8BYTES (0x00000030) #define MPI3_SYSIF_DIAG_RW_CONTROL_RESET (0x00000004) #define MPI3_SYSIF_DIAG_RW_CONTROL_DIR_MASK (0x00000002) #define MPI3_SYSIF_DIAG_RW_CONTROL_DIR_READ (0x00000000) #define MPI3_SYSIF_DIAG_RW_CONTROL_DIR_WRITE (0x00000002) #define MPI3_SYSIF_DIAG_RW_CONTROL_START (0x00000001) /**** Defines for DiagRWStatus register ****/ #define MPI3_SYSIF_DIAG_RW_STATUS_OFFSET (0x00001C62) #define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_MASK (0x0000000E) #define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_SUCCESS (0x00000000) #define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_INV_ADDR (0x00000002) #define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_ACC_ERR (0x00000004) #define MPI3_SYSIF_DIAG_RW_STATUS_STATUS_PAR_ERR (0x00000006) #define MPI3_SYSIF_DIAG_RW_STATUS_BUSY (0x00000001) /**** Defines for Scratchpad registers ****/ #define MPI3_SYSIF_SCRATCHPAD0_OFFSET (0x00001CF0) #define MPI3_SYSIF_SCRATCHPAD1_OFFSET (0x00001CF4) #define MPI3_SYSIF_SCRATCHPAD2_OFFSET (0x00001CF8) #define MPI3_SYSIF_SCRATCHPAD3_OFFSET (0x00001CFC) /**** Defines for Device Assigned registers ****/ #define MPI3_SYSIF_DEVICE_ASSIGNED_REGS_OFFSET (0x00002000) /**** Default Defines for Diag Save Timeout ****/ #define MPI3_SYSIF_DIAG_SAVE_TIMEOUT (60) /* seconds */ /***************************************************************************** * Reply Descriptors * ****************************************************************************/ /***************************************************************************** * Default Reply Descriptor * ****************************************************************************/ typedef struct _MPI3_DEFAULT_REPLY_DESCRIPTOR { U32 DescriptorTypeDependent1[2]; /* 0x00 */ U16 RequestQueueCI; /* 0x08 */ U16 RequestQueueID; /* 0x0A */ U16 DescriptorTypeDependent2; /* 0x0C */ U16 ReplyFlags; /* 0x0E */ } MPI3_DEFAULT_REPLY_DESCRIPTOR, MPI3_POINTER PTR_MPI3_DEFAULT_REPLY_DESCRIPTOR, Mpi3DefaultReplyDescriptor_t, MPI3_POINTER pMpi3DefaultReplyDescriptor_t; /**** Defines for the ReplyFlags field ****/ #define MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK (0x0001) #define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK (0xF000) #define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY (0x0000) #define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS (0x1000) #define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_TARGET_COMMAND_BUFFER (0x2000) #define MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS (0x3000) /**** Defines for the RequestQueueID field ****/ #define MPI3_REPLY_DESCRIPT_REQUEST_QUEUE_ID_INVALID (0xFFFF) /***************************************************************************** * Address Reply Descriptor * ****************************************************************************/ typedef struct _MPI3_ADDRESS_REPLY_DESCRIPTOR { U64 ReplyFrameAddress; /* 0x00 */ U16 RequestQueueCI; /* 0x08 */ U16 RequestQueueID; /* 0x0A */ U16 Reserved0C; /* 0x0C */ U16 ReplyFlags; /* 0x0E */ } MPI3_ADDRESS_REPLY_DESCRIPTOR, MPI3_POINTER PTR_MPI3_ADDRESS_REPLY_DESCRIPTOR, Mpi3AddressReplyDescriptor_t, MPI3_POINTER pMpi3AddressReplyDescriptor_t; /***************************************************************************** * Success Reply Descriptor * ****************************************************************************/ typedef struct _MPI3_SUCCESS_REPLY_DESCRIPTOR { U32 Reserved00[2]; /* 0x00 */ U16 RequestQueueCI; /* 0x08 */ U16 RequestQueueID; /* 0x0A */ U16 HostTag; /* 0x0C */ U16 ReplyFlags; /* 0x0E */ } MPI3_SUCCESS_REPLY_DESCRIPTOR, MPI3_POINTER PTR_MPI3_SUCCESS_REPLY_DESCRIPTOR, Mpi3SuccessReplyDescriptor_t, MPI3_POINTER pMpi3SuccessReplyDescriptor_t; /***************************************************************************** * Target Command Buffer Reply Descriptor * ****************************************************************************/ typedef struct _MPI3_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR { U32 Reserved00; /* 0x00 */ U16 InitiatorDevHandle; /* 0x04 */ U8 PhyNum; /* 0x06 */ U8 Reserved07; /* 0x07 */ U16 RequestQueueCI; /* 0x08 */ U16 RequestQueueID; /* 0x0A */ U16 IOIndex; /* 0x0C */ U16 ReplyFlags; /* 0x0E */ } MPI3_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, MPI3_POINTER PTR_MPI3_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, Mpi3TargetCommandBufferReplyDescriptor_t, MPI3_POINTER pMpi3TargetCommandBufferReplyDescriptor_t; /**** See Default Reply Descriptor Defines above for definitions in the ReplyFlags field ****/ /***************************************************************************** * Status Reply Descriptor * ****************************************************************************/ typedef struct _MPI3_STATUS_REPLY_DESCRIPTOR { U16 IOCStatus; /* 0x00 */ U16 Reserved02; /* 0x02 */ U32 IOCLogInfo; /* 0x04 */ U16 RequestQueueCI; /* 0x08 */ U16 RequestQueueID; /* 0x0A */ U16 HostTag; /* 0x0C */ U16 ReplyFlags; /* 0x0E */ } MPI3_STATUS_REPLY_DESCRIPTOR, MPI3_POINTER PTR_MPI3_STATUS_REPLY_DESCRIPTOR, Mpi3StatusReplyDescriptor_t, MPI3_POINTER pMpi3StatusReplyDescriptor_t; -/**** Defines for the IOCStatus field ****/ -#define MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL (0x8000) -#define MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK (0x7FFF) +/**** Use MPI3_IOCSTATUS_ defines for the IOCStatus field ****/ -/**** Defines for the IOCLogInfo field ****/ -#define MPI3_REPLY_DESCRIPT_STATUS_IOCLOGINFO_TYPE_MASK (0xF0000000) -#define MPI3_REPLY_DESCRIPT_STATUS_IOCLOGINFO_TYPE_NO_INFO (0x00000000) -#define MPI3_REPLY_DESCRIPT_STATUS_IOCLOGINFO_TYPE_SAS (0x30000000) -#define MPI3_REPLY_DESCRIPT_STATUS_IOCLOGINFO_DATA_MASK (0x0FFFFFFF) +/**** Use MPI3_IOCLOGINFO_ defines for the IOCLogInfo field ****/ /***************************************************************************** * Union of Reply Descriptors * ****************************************************************************/ typedef union _MPI3_REPLY_DESCRIPTORS_UNION { MPI3_DEFAULT_REPLY_DESCRIPTOR Default; MPI3_ADDRESS_REPLY_DESCRIPTOR AddressReply; MPI3_SUCCESS_REPLY_DESCRIPTOR Success; MPI3_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer; MPI3_STATUS_REPLY_DESCRIPTOR Status; U32 Words[4]; } MPI3_REPLY_DESCRIPTORS_UNION, MPI3_POINTER PTR_MPI3_REPLY_DESCRIPTORS_UNION, Mpi3ReplyDescriptorsUnion_t, MPI3_POINTER pMpi3ReplyDescriptorsUnion_t; /***************************************************************************** * Scatter Gather Elements * ****************************************************************************/ /***************************************************************************** * Common structure for Simple, Chain, and Last Chain * * scatter gather elements * ****************************************************************************/ typedef struct _MPI3_SGE_COMMON { U64 Address; /* 0x00 */ U32 Length; /* 0x08 */ U8 Reserved0C[3]; /* 0x0C */ U8 Flags; /* 0x0F */ } MPI3_SGE_SIMPLE, MPI3_POINTER PTR_MPI3_SGE_SIMPLE, Mpi3SGESimple_t, MPI3_POINTER pMpi3SGESimple_t, MPI3_SGE_CHAIN, MPI3_POINTER PTR_MPI3_SGE_CHAIN, Mpi3SGEChain_t, MPI3_POINTER pMpi3SGEChain_t, MPI3_SGE_LAST_CHAIN, MPI3_POINTER PTR_MPI3_SGE_LAST_CHAIN, Mpi3SGELastChain_t, MPI3_POINTER pMpi3SGELastChain_t; /***************************************************************************** * Bit Bucket scatter gather element * ****************************************************************************/ typedef struct _MPI3_SGE_BIT_BUCKET { U64 Reserved00; /* 0x00 */ U32 Length; /* 0x08 */ U8 Reserved0C[3]; /* 0x0C */ U8 Flags; /* 0x0F */ } MPI3_SGE_BIT_BUCKET, MPI3_POINTER PTR_MPI3_SGE_BIT_BUCKET, Mpi3SGEBitBucket_t, MPI3_POINTER pMpi3SGEBitBucket_t; /***************************************************************************** * Extended EEDP scatter gather element * ****************************************************************************/ typedef struct _MPI3_SGE_EXTENDED_EEDP { U8 UserDataSize; /* 0x00 */ U8 Reserved01; /* 0x01 */ U16 EEDPFlags; /* 0x02 */ U32 SecondaryReferenceTag; /* 0x04 */ U16 SecondaryApplicationTag; /* 0x08 */ U16 ApplicationTagTranslationMask; /* 0x0A */ U16 Reserved0C; /* 0x0C */ U8 ExtendedOperation; /* 0x0E */ U8 Flags; /* 0x0F */ } MPI3_SGE_EXTENDED_EEDP, MPI3_POINTER PTR_MPI3_SGE_EXTENDED_EEDP, Mpi3SGEExtendedEEDP_t, MPI3_POINTER pMpi3SGEExtendedEEDP_t; /***************************************************************************** * Union of scatter gather elements * ****************************************************************************/ typedef union _MPI3_SGE_UNION { MPI3_SGE_SIMPLE Simple; MPI3_SGE_CHAIN Chain; MPI3_SGE_LAST_CHAIN LastChain; MPI3_SGE_BIT_BUCKET BitBucket; MPI3_SGE_EXTENDED_EEDP Eedp; U32 Words[4]; } MPI3_SGE_UNION, MPI3_POINTER PTR_MPI3_SGE_UNION, Mpi3SGEUnion_t, MPI3_POINTER pMpi3SGEUnion_t; /**** Definitions for the Flags field ****/ #define MPI3_SGE_FLAGS_ELEMENT_TYPE_MASK (0xF0) #define MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE (0x00) #define MPI3_SGE_FLAGS_ELEMENT_TYPE_BIT_BUCKET (0x10) #define MPI3_SGE_FLAGS_ELEMENT_TYPE_CHAIN (0x20) #define MPI3_SGE_FLAGS_ELEMENT_TYPE_LAST_CHAIN (0x30) #define MPI3_SGE_FLAGS_ELEMENT_TYPE_EXTENDED (0xF0) #define MPI3_SGE_FLAGS_END_OF_LIST (0x08) #define MPI3_SGE_FLAGS_END_OF_BUFFER (0x04) #define MPI3_SGE_FLAGS_DLAS_MASK (0x03) #define MPI3_SGE_FLAGS_DLAS_SYSTEM (0x00) #define MPI3_SGE_FLAGS_DLAS_IOC_UDP (0x01) #define MPI3_SGE_FLAGS_DLAS_IOC_CTL (0x02) /**** Definitions for the ExtendedOperation field of Extended element ****/ #define MPI3_SGE_EXT_OPER_EEDP (0x00) /**** Definitions for the EEDPFlags field of Extended EEDP element ****/ #define MPI3_EEDPFLAGS_INCR_PRI_REF_TAG (0x8000) #define MPI3_EEDPFLAGS_INCR_SEC_REF_TAG (0x4000) #define MPI3_EEDPFLAGS_INCR_PRI_APP_TAG (0x2000) #define MPI3_EEDPFLAGS_INCR_SEC_APP_TAG (0x1000) #define MPI3_EEDPFLAGS_ESC_PASSTHROUGH (0x0800) #define MPI3_EEDPFLAGS_CHK_REF_TAG (0x0400) #define MPI3_EEDPFLAGS_CHK_APP_TAG (0x0200) #define MPI3_EEDPFLAGS_CHK_GUARD (0x0100) #define MPI3_EEDPFLAGS_ESC_MODE_MASK (0x00C0) #define MPI3_EEDPFLAGS_ESC_MODE_DO_NOT_DISABLE (0x0040) #define MPI3_EEDPFLAGS_ESC_MODE_APPTAG_DISABLE (0x0080) #define MPI3_EEDPFLAGS_ESC_MODE_APPTAG_REFTAG_DISABLE (0x00C0) #define MPI3_EEDPFLAGS_HOST_GUARD_MASK (0x0030) #define MPI3_EEDPFLAGS_HOST_GUARD_T10_CRC (0x0000) #define MPI3_EEDPFLAGS_HOST_GUARD_IP_CHKSUM (0x0010) #define MPI3_EEDPFLAGS_HOST_GUARD_OEM_SPECIFIC (0x0020) #define MPI3_EEDPFLAGS_PT_REF_TAG (0x0008) #define MPI3_EEDPFLAGS_EEDP_OP_MASK (0x0007) #define MPI3_EEDPFLAGS_EEDP_OP_CHECK (0x0001) #define MPI3_EEDPFLAGS_EEDP_OP_STRIP (0x0002) #define MPI3_EEDPFLAGS_EEDP_OP_CHECK_REMOVE (0x0003) #define MPI3_EEDPFLAGS_EEDP_OP_INSERT (0x0004) #define MPI3_EEDPFLAGS_EEDP_OP_REPLACE (0x0006) #define MPI3_EEDPFLAGS_EEDP_OP_CHECK_REGEN (0x0007) /**** Definitions for the UserDataSize field of Extended EEDP element ****/ #define MPI3_EEDP_UDS_512 (0x01) #define MPI3_EEDP_UDS_520 (0x02) #define MPI3_EEDP_UDS_4080 (0x03) #define MPI3_EEDP_UDS_4088 (0x04) #define MPI3_EEDP_UDS_4096 (0x05) #define MPI3_EEDP_UDS_4104 (0x06) #define MPI3_EEDP_UDS_4160 (0x07) /***************************************************************************** * Standard Message Structures * ****************************************************************************/ /***************************************************************************** * Request Message Header for all request messages * ****************************************************************************/ typedef struct _MPI3_REQUEST_HEADER { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 ChangeCount; /* 0x08 */ U16 FunctionDependent; /* 0x0A */ } MPI3_REQUEST_HEADER, MPI3_POINTER PTR_MPI3_REQUEST_HEADER, Mpi3RequestHeader_t, MPI3_POINTER pMpi3RequestHeader_t; /***************************************************************************** * Default Reply * ****************************************************************************/ typedef struct _MPI3_DEFAULT_REPLY { U16 HostTag; /* 0x00 */ U8 IOCUseOnly02; /* 0x02 */ U8 Function; /* 0x03 */ U16 IOCUseOnly04; /* 0x04 */ U8 IOCUseOnly06; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U16 IOCUseOnly08; /* 0x08 */ U16 IOCStatus; /* 0x0A */ U32 IOCLogInfo; /* 0x0C */ } MPI3_DEFAULT_REPLY, MPI3_POINTER PTR_MPI3_DEFAULT_REPLY, Mpi3DefaultReply_t, MPI3_POINTER pMpi3DefaultReply_t; /**** Defines for the HostTag field ****/ #define MPI3_HOST_TAG_INVALID (0xFFFF) /**** Defines for message Function ****/ /* I/O Controller functions */ #define MPI3_FUNCTION_IOC_FACTS (0x01) /* IOC Facts */ #define MPI3_FUNCTION_IOC_INIT (0x02) /* IOC Init */ #define MPI3_FUNCTION_PORT_ENABLE (0x03) /* Port Enable */ #define MPI3_FUNCTION_EVENT_NOTIFICATION (0x04) /* Event Notification */ #define MPI3_FUNCTION_EVENT_ACK (0x05) /* Event Acknowledge */ #define MPI3_FUNCTION_CI_DOWNLOAD (0x06) /* Component Image Download */ #define MPI3_FUNCTION_CI_UPLOAD (0x07) /* Component Image Upload */ #define MPI3_FUNCTION_IO_UNIT_CONTROL (0x08) /* IO Unit Control */ #define MPI3_FUNCTION_PERSISTENT_EVENT_LOG (0x09) /* Persistent Event Log */ #define MPI3_FUNCTION_MGMT_PASSTHROUGH (0x0A) /* Management Passthrough */ #define MPI3_FUNCTION_CONFIG (0x10) /* Configuration */ /* SCSI Initiator I/O functions */ #define MPI3_FUNCTION_SCSI_IO (0x20) /* SCSI IO */ #define MPI3_FUNCTION_SCSI_TASK_MGMT (0x21) /* SCSI Task Management */ #define MPI3_FUNCTION_SMP_PASSTHROUGH (0x22) /* SMP Passthrough */ #define MPI3_FUNCTION_NVME_ENCAPSULATED (0x24) /* NVMe Encapsulated */ /* SCSI Target I/O functions */ #define MPI3_FUNCTION_TARGET_ASSIST (0x30) /* Target Assist */ #define MPI3_FUNCTION_TARGET_STATUS_SEND (0x31) /* Target Status Send */ #define MPI3_FUNCTION_TARGET_MODE_ABORT (0x32) /* Target Mode Abort */ #define MPI3_FUNCTION_TARGET_CMD_BUF_POST_BASE (0x33) /* Target Command Buffer Post Base */ #define MPI3_FUNCTION_TARGET_CMD_BUF_POST_LIST (0x34) /* Target Command Buffer Post List */ /* Queue Management functions */ #define MPI3_FUNCTION_CREATE_REQUEST_QUEUE (0x70) /* Create an operational request queue */ #define MPI3_FUNCTION_DELETE_REQUEST_QUEUE (0x71) /* Delete an operational request queue */ #define MPI3_FUNCTION_CREATE_REPLY_QUEUE (0x72) /* Create an operational reply queue */ #define MPI3_FUNCTION_DELETE_REPLY_QUEUE (0x73) /* Delete an operational reply queue */ /* Diagnostic Tools */ #define MPI3_FUNCTION_TOOLBOX (0x80) /* Toolbox */ #define MPI3_FUNCTION_DIAG_BUFFER_POST (0x81) /* Post a Diagnostic Buffer to the I/O Unit */ #define MPI3_FUNCTION_DIAG_BUFFER_MANAGE (0x82) /* Manage a Diagnostic Buffer */ #define MPI3_FUNCTION_DIAG_BUFFER_UPLOAD (0x83) /* Upload a Diagnostic Buffer */ /* Miscellaneous functions */ #define MPI3_FUNCTION_MIN_IOC_USE_ONLY (0xC0) /* Beginning of IOC Use Only range of function codes */ #define MPI3_FUNCTION_MAX_IOC_USE_ONLY (0xEF) /* End of IOC Use Only range of function codes */ #define MPI3_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0) /* Beginning of the product-specific range of function codes */ #define MPI3_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF) /* End of the product-specific range of function codes */ /**** Defines for IOCStatus ****/ -#define MPI3_IOCSTATUS_LOG_INFO_AVAIL_MASK (0x8000) #define MPI3_IOCSTATUS_LOG_INFO_AVAILABLE (0x8000) #define MPI3_IOCSTATUS_STATUS_MASK (0x7FFF) /* Common IOCStatus values for all replies */ #define MPI3_IOCSTATUS_SUCCESS (0x0000) #define MPI3_IOCSTATUS_INVALID_FUNCTION (0x0001) #define MPI3_IOCSTATUS_BUSY (0x0002) #define MPI3_IOCSTATUS_INVALID_SGL (0x0003) #define MPI3_IOCSTATUS_INTERNAL_ERROR (0x0004) #define MPI3_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006) #define MPI3_IOCSTATUS_INVALID_FIELD (0x0007) #define MPI3_IOCSTATUS_INVALID_STATE (0x0008) #define MPI3_IOCSTATUS_INSUFFICIENT_POWER (0x000A) #define MPI3_IOCSTATUS_INVALID_CHANGE_COUNT (0x000B) #define MPI3_IOCSTATUS_ALLOWED_CMD_BLOCK (0x000C) #define MPI3_IOCSTATUS_SUPERVISOR_ONLY (0x000D) #define MPI3_IOCSTATUS_FAILURE (0x001F) /* Config IOCStatus values */ #define MPI3_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) #define MPI3_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) #define MPI3_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) #define MPI3_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) #define MPI3_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) #define MPI3_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) /* SCSI IO IOCStatus values */ #define MPI3_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040) #define MPI3_IOCSTATUS_SCSI_TM_NOT_SUPPORTED (0x0041) #define MPI3_IOCSTATUS_SCSI_INVALID_DEVHANDLE (0x0042) #define MPI3_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043) #define MPI3_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044) #define MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045) #define MPI3_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046) #define MPI3_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) #define MPI3_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) #define MPI3_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) #define MPI3_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) #define MPI3_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) #define MPI3_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) /* SCSI Initiator and SCSI Target end-to-end data protection values */ #define MPI3_IOCSTATUS_EEDP_GUARD_ERROR (0x004D) #define MPI3_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E) #define MPI3_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F) /* SCSI Target IOCStatus values */ #define MPI3_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062) #define MPI3_IOCSTATUS_TARGET_ABORTED (0x0063) #define MPI3_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064) #define MPI3_IOCSTATUS_TARGET_NO_CONNECTION (0x0065) #define MPI3_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A) #define MPI3_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) #define MPI3_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) #define MPI3_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) #define MPI3_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070) #define MPI3_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071) /* Serial Attached SCSI IOCStatus values */ #define MPI3_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) #define MPI3_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091) /* Diagnostic Buffer Post/Release IOCStatus values */ #define MPI3_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) /* Component Image Upload/Download */ #define MPI3_IOCSTATUS_CI_UNSUPPORTED (0x00B0) #define MPI3_IOCSTATUS_CI_UPDATE_SEQUENCE (0x00B1) #define MPI3_IOCSTATUS_CI_VALIDATION_FAILED (0x00B2) #define MPI3_IOCSTATUS_CI_KEY_UPDATE_PENDING (0x00B3) #define MPI3_IOCSTATUS_CI_KEY_UPDATE_NOT_POSSIBLE (0x00B4) /* Security values */ #define MPI3_IOCSTATUS_SECURITY_KEY_REQUIRED (0x00C0) #define MPI3_IOCSTATUS_SECURITY_VIOLATION (0x00C1) /* Request and Reply Queues related IOCStatus values */ #define MPI3_IOCSTATUS_INVALID_QUEUE_ID (0x0F00) #define MPI3_IOCSTATUS_INVALID_QUEUE_SIZE (0x0F01) #define MPI3_IOCSTATUS_INVALID_MSIX_VECTOR (0x0F02) #define MPI3_IOCSTATUS_INVALID_REPLY_QUEUE_ID (0x0F03) #define MPI3_IOCSTATUS_INVALID_QUEUE_DELETION (0x0F04) /**** Defines for IOCLogInfo ****/ #define MPI3_IOCLOGINFO_TYPE_MASK (0xF0000000) #define MPI3_IOCLOGINFO_TYPE_SHIFT (28) #define MPI3_IOCLOGINFO_TYPE_NONE (0x0) #define MPI3_IOCLOGINFO_TYPE_SAS (0x3) #define MPI3_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF) #endif /* MPI30_TRANSPORT_H */ diff --git a/sys/dev/mpi3mr/mpi/mpi30_type.h b/sys/dev/mpi3mr/mpi/mpi30_type.h index 267ede701762..815becadcf25 100644 --- a/sys/dev/mpi3mr/mpi/mpi30_type.h +++ b/sys/dev/mpi3mr/mpi/mpi30_type.h @@ -1,99 +1,98 @@ /* - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. + * Copyright (c) 2016-2024, Broadcom Inc. All rights reserved. * Support: * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD * */ - #ifndef MPI30_TYPE_H #define MPI30_TYPE_H 1 /***************************************************************************** * Define MPI3_POINTER if it has not already been defined. By default * * MPI3_POINTER is defined to be a near pointer. MPI3_POINTER can be defined * * as a far pointer by defining MPI3_POINTER as "far *" before this header * * file is included. * ****************************************************************************/ #ifndef MPI3_POINTER #define MPI3_POINTER * #endif /* MPI3_POINTER */ /* The basic types may have already been included by mpi_type.h or mpi2_type.h */ #if !defined(MPI_TYPE_H) && !defined(MPI2_TYPE_H) /***************************************************************************** * Basic Types * ****************************************************************************/ typedef int8_t S8; typedef uint8_t U8; typedef int16_t S16; typedef uint16_t U16; typedef int32_t S32; typedef uint32_t U32; typedef int64_t S64; typedef uint64_t U64; /***************************************************************************** * Structure Types * ****************************************************************************/ typedef struct _S64struct { U32 Low; S32 High; } S64struct; typedef struct _U64struct { U32 Low; U32 High; } U64struct; /***************************************************************************** * Pointer Types * ****************************************************************************/ typedef S8 *PS8; typedef U8 *PU8; typedef S16 *PS16; typedef U16 *PU16; typedef S32 *PS32; typedef U32 *PU32; typedef S64 *PS64; typedef U64 *PU64; typedef S64struct *PS64struct; typedef U64struct *PU64struct; #endif /* MPI_TYPE_H && MPI2_TYPE_H */ #endif /* MPI30_TYPE_H */ diff --git a/sys/dev/mpi3mr/mpi3mr.c b/sys/dev/mpi3mr/mpi3mr.c index c592d5734d38..99a331c9baf0 100644 --- a/sys/dev/mpi3mr/mpi3mr.c +++ b/sys/dev/mpi3mr/mpi3mr.c @@ -1,6156 +1,6152 @@ /* * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2016-2023, Broadcom Inc. All rights reserved. * Support: * * Authors: Sumit Saxena * Chandrakanth Patil * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mpi3mr.h" #include "mpi3mr_cam.h" #include "mpi3mr_app.h" static void mpi3mr_repost_reply_buf(struct mpi3mr_softc *sc, U64 reply_dma); static int mpi3mr_complete_admin_cmd(struct mpi3mr_softc *sc); static void mpi3mr_port_enable_complete(struct mpi3mr_softc *sc, struct mpi3mr_drvr_cmd *drvrcmd); static void mpi3mr_flush_io(struct mpi3mr_softc *sc); static int mpi3mr_issue_reset(struct mpi3mr_softc *sc, U16 reset_type, U16 reset_reason); static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_softc *sc, U16 handle, struct mpi3mr_drvr_cmd *cmdparam, U8 iou_rc); static void mpi3mr_dev_rmhs_complete_iou(struct mpi3mr_softc *sc, struct mpi3mr_drvr_cmd *drv_cmd); static void mpi3mr_dev_rmhs_complete_tm(struct mpi3mr_softc *sc, struct mpi3mr_drvr_cmd *drv_cmd); static void mpi3mr_send_evt_ack(struct mpi3mr_softc *sc, U8 event, struct mpi3mr_drvr_cmd *cmdparam, U32 event_ctx); static void mpi3mr_print_fault_info(struct mpi3mr_softc *sc); static inline void mpi3mr_set_diagsave(struct mpi3mr_softc *sc); static const char *mpi3mr_reset_rc_name(enum mpi3mr_reset_reason reason_code); void mpi3mr_hexdump(void *buf, int sz, int format) { int i; U32 *buf_loc = (U32 *)buf; for (i = 0; i < (sz / sizeof(U32)); i++) { if ((i % format) == 0) { if (i != 0) printf("\n"); printf("%08x: ", (i * 4)); } printf("%08x ", buf_loc[i]); } printf("\n"); } void init_completion(struct completion *completion) { completion->done = 0; } void complete(struct completion *completion) { completion->done = 1; wakeup(complete); } void wait_for_completion_timeout(struct completion *completion, U32 timeout) { U32 count = timeout * 1000; while ((completion->done == 0) && count) { DELAY(1000); count--; } if (completion->done == 0) { printf("%s: Command is timedout\n", __func__); completion->done = 1; } } void wait_for_completion_timeout_tm(struct completion *completion, U32 timeout, struct mpi3mr_softc *sc) { U32 count = timeout * 1000; while ((completion->done == 0) && count) { msleep(&sc->tm_chan, &sc->mpi3mr_mtx, PRIBIO, "TM command", 1 * hz); count--; } if (completion->done == 0) { printf("%s: Command is timedout\n", __func__); completion->done = 1; } } void poll_for_command_completion(struct mpi3mr_softc *sc, struct mpi3mr_drvr_cmd *cmd, U16 wait) { int wait_time = wait * 1000; while (wait_time) { mpi3mr_complete_admin_cmd(sc); if (cmd->state & MPI3MR_CMD_COMPLETE) break; DELAY(1000); wait_time--; } } /** * mpi3mr_trigger_snapdump - triggers firmware snapdump * @sc: Adapter instance reference * @reason_code: reason code for the fault. * * This routine will trigger the snapdump and wait for it to * complete or timeout before it returns. * This will be called during initilaization time faults/resets/timeouts * before soft reset invocation. * * Return: None. */ static void mpi3mr_trigger_snapdump(struct mpi3mr_softc *sc, U16 reason_code) { U32 host_diagnostic, timeout = MPI3_SYSIF_DIAG_SAVE_TIMEOUT * 10; mpi3mr_dprint(sc, MPI3MR_INFO, "snapdump triggered: reason code: %s\n", mpi3mr_reset_rc_name(reason_code)); mpi3mr_set_diagsave(sc); mpi3mr_issue_reset(sc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reason_code); do { host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET); if (!(host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS)) break; DELAY(100 * 1000); } while (--timeout); return; } /** * mpi3mr_check_rh_fault_ioc - check reset history and fault * controller * @sc: Adapter instance reference * @reason_code, reason code for the fault. * * This routine will fault the controller with * the given reason code if it is not already in the fault or * not asynchronosuly reset. This will be used to handle * initilaization time faults/resets/timeout as in those cases * immediate soft reset invocation is not required. * * Return: None. */ static void mpi3mr_check_rh_fault_ioc(struct mpi3mr_softc *sc, U16 reason_code) { U32 ioc_status; if (sc->unrecoverable) { mpi3mr_dprint(sc, MPI3MR_ERROR, "controller is unrecoverable\n"); return; } ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); if ((ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) || (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) { mpi3mr_print_fault_info(sc); return; } mpi3mr_trigger_snapdump(sc, reason_code); return; } static void * mpi3mr_get_reply_virt_addr(struct mpi3mr_softc *sc, bus_addr_t phys_addr) { if (!phys_addr) return NULL; if ((phys_addr < sc->reply_buf_dma_min_address) || (phys_addr > sc->reply_buf_dma_max_address)) return NULL; return sc->reply_buf + (phys_addr - sc->reply_buf_phys); } static void * mpi3mr_get_sensebuf_virt_addr(struct mpi3mr_softc *sc, bus_addr_t phys_addr) { if (!phys_addr) return NULL; return sc->sense_buf + (phys_addr - sc->sense_buf_phys); } static void mpi3mr_repost_reply_buf(struct mpi3mr_softc *sc, U64 reply_dma) { U32 old_idx = 0; mtx_lock_spin(&sc->reply_free_q_lock); old_idx = sc->reply_free_q_host_index; sc->reply_free_q_host_index = ((sc->reply_free_q_host_index == (sc->reply_free_q_sz - 1)) ? 0 : (sc->reply_free_q_host_index + 1)); sc->reply_free_q[old_idx] = reply_dma; mpi3mr_regwrite(sc, MPI3_SYSIF_REPLY_FREE_HOST_INDEX_OFFSET, sc->reply_free_q_host_index); mtx_unlock_spin(&sc->reply_free_q_lock); } static void mpi3mr_repost_sense_buf(struct mpi3mr_softc *sc, U64 sense_buf_phys) { U32 old_idx = 0; mtx_lock_spin(&sc->sense_buf_q_lock); old_idx = sc->sense_buf_q_host_index; sc->sense_buf_q_host_index = ((sc->sense_buf_q_host_index == (sc->sense_buf_q_sz - 1)) ? 0 : (sc->sense_buf_q_host_index + 1)); sc->sense_buf_q[old_idx] = sense_buf_phys; mpi3mr_regwrite(sc, MPI3_SYSIF_SENSE_BUF_FREE_HOST_INDEX_OFFSET, sc->sense_buf_q_host_index); mtx_unlock_spin(&sc->sense_buf_q_lock); } void mpi3mr_set_io_divert_for_all_vd_in_tg(struct mpi3mr_softc *sc, struct mpi3mr_throttle_group_info *tg, U8 divert_value) { struct mpi3mr_target *target; mtx_lock_spin(&sc->target_lock); TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) { if (target->throttle_group == tg) target->io_divert = divert_value; } mtx_unlock_spin(&sc->target_lock); } /** * mpi3mr_submit_admin_cmd - Submit request to admin queue * @mrioc: Adapter reference * @admin_req: MPI3 request * @admin_req_sz: Request size * * Post the MPI3 request into admin request queue and * inform the controller, if the queue is full return * appropriate error. * * Return: 0 on success, non-zero on failure. */ int mpi3mr_submit_admin_cmd(struct mpi3mr_softc *sc, void *admin_req, U16 admin_req_sz) { U16 areq_pi = 0, areq_ci = 0, max_entries = 0; int retval = 0; U8 *areq_entry; mtx_lock_spin(&sc->admin_req_lock); areq_pi = sc->admin_req_pi; areq_ci = sc->admin_req_ci; max_entries = sc->num_admin_reqs; if (sc->unrecoverable) return -EFAULT; if ((areq_ci == (areq_pi + 1)) || ((!areq_ci) && (areq_pi == (max_entries - 1)))) { printf(IOCNAME "AdminReqQ full condition detected\n", sc->name); retval = -EAGAIN; goto out; } areq_entry = (U8 *)sc->admin_req + (areq_pi * MPI3MR_AREQ_FRAME_SZ); memset(areq_entry, 0, MPI3MR_AREQ_FRAME_SZ); memcpy(areq_entry, (U8 *)admin_req, admin_req_sz); if (++areq_pi == max_entries) areq_pi = 0; sc->admin_req_pi = areq_pi; mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REQ_Q_PI_OFFSET, sc->admin_req_pi); out: mtx_unlock_spin(&sc->admin_req_lock); return retval; } /** * mpi3mr_check_req_qfull - Check request queue is full or not * @op_req_q: Operational reply queue info * * Return: true when queue full, false otherwise. */ static inline bool mpi3mr_check_req_qfull(struct mpi3mr_op_req_queue *op_req_q) { U16 pi, ci, max_entries; bool is_qfull = false; pi = op_req_q->pi; ci = op_req_q->ci; max_entries = op_req_q->num_reqs; if ((ci == (pi + 1)) || ((!ci) && (pi == (max_entries - 1)))) is_qfull = true; return is_qfull; } /** * mpi3mr_submit_io - Post IO command to firmware * @sc: Adapter instance reference * @op_req_q: Operational Request queue reference * @req: MPT request data * * This function submits IO command to firmware. * * Return: Nothing */ int mpi3mr_submit_io(struct mpi3mr_softc *sc, struct mpi3mr_op_req_queue *op_req_q, U8 *req) { U16 pi, max_entries; int retval = 0; U8 *req_entry; U16 req_sz = sc->facts.op_req_sz; struct mpi3mr_irq_context *irq_ctx; mtx_lock_spin(&op_req_q->q_lock); pi = op_req_q->pi; max_entries = op_req_q->num_reqs; if (mpi3mr_check_req_qfull(op_req_q)) { irq_ctx = &sc->irq_ctx[op_req_q->reply_qid - 1]; mpi3mr_complete_io_cmd(sc, irq_ctx); if (mpi3mr_check_req_qfull(op_req_q)) { printf(IOCNAME "OpReqQ full condition detected\n", sc->name); retval = -EBUSY; goto out; } } req_entry = (U8 *)op_req_q->q_base + (pi * req_sz); memset(req_entry, 0, req_sz); memcpy(req_entry, req, MPI3MR_AREQ_FRAME_SZ); if (++pi == max_entries) pi = 0; op_req_q->pi = pi; mpi3mr_atomic_inc(&sc->op_reply_q[op_req_q->reply_qid - 1].pend_ios); mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REQ_Q_N_PI_OFFSET(op_req_q->qid), op_req_q->pi); if (sc->mpi3mr_debug & MPI3MR_TRACE) { device_printf(sc->mpi3mr_dev, "IO submission: QID:%d PI:0x%x\n", op_req_q->qid, op_req_q->pi); mpi3mr_hexdump(req_entry, MPI3MR_AREQ_FRAME_SZ, 8); } out: mtx_unlock_spin(&op_req_q->q_lock); return retval; } inline void mpi3mr_add_sg_single(void *paddr, U8 flags, U32 length, bus_addr_t dma_addr) { Mpi3SGESimple_t *sgel = paddr; sgel->Flags = flags; sgel->Length = (length); sgel->Address = (U64)dma_addr; } void mpi3mr_build_zero_len_sge(void *paddr) { U8 sgl_flags = (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | MPI3_SGE_FLAGS_END_OF_LIST); mpi3mr_add_sg_single(paddr, sgl_flags, 0, -1); } void mpi3mr_enable_interrupts(struct mpi3mr_softc *sc) { sc->intr_enabled = 1; } void mpi3mr_disable_interrupts(struct mpi3mr_softc *sc) { sc->intr_enabled = 0; } void mpi3mr_memaddr_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error) { bus_addr_t *addr; addr = arg; *addr = segs[0].ds_addr; } static int mpi3mr_delete_op_reply_queue(struct mpi3mr_softc *sc, U16 qid) { Mpi3DeleteReplyQueueRequest_t delq_req; struct mpi3mr_op_reply_queue *op_reply_q; int retval = 0; op_reply_q = &sc->op_reply_q[qid - 1]; if (!op_reply_q->qid) { retval = -1; printf(IOCNAME "Issue DelRepQ: called with invalid Reply QID\n", sc->name); goto out; } memset(&delq_req, 0, sizeof(delq_req)); mtx_lock(&sc->init_cmds.completion.lock); if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { retval = -1; printf(IOCNAME "Issue DelRepQ: Init command is in use\n", sc->name); mtx_unlock(&sc->init_cmds.completion.lock); goto out; } if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { retval = -1; printf(IOCNAME "Issue DelRepQ: Init command is in use\n", sc->name); goto out; } sc->init_cmds.state = MPI3MR_CMD_PENDING; sc->init_cmds.is_waiting = 1; sc->init_cmds.callback = NULL; delq_req.HostTag = MPI3MR_HOSTTAG_INITCMDS; delq_req.Function = MPI3_FUNCTION_DELETE_REPLY_QUEUE; delq_req.QueueID = qid; init_completion(&sc->init_cmds.completion); retval = mpi3mr_submit_admin_cmd(sc, &delq_req, sizeof(delq_req)); if (retval) { printf(IOCNAME "Issue DelRepQ: Admin Post failed\n", sc->name); goto out_unlock; } wait_for_completion_timeout(&sc->init_cmds.completion, (MPI3MR_INTADMCMD_TIMEOUT)); if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { printf(IOCNAME "Issue DelRepQ: command timed out\n", sc->name); mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_DELREPQ_TIMEOUT); sc->unrecoverable = 1; retval = -1; goto out_unlock; } if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) != MPI3_IOCSTATUS_SUCCESS ) { printf(IOCNAME "Issue DelRepQ: Failed IOCStatus(0x%04x) " " Loginfo(0x%08x) \n" , sc->name, (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), sc->init_cmds.ioc_loginfo); retval = -1; goto out_unlock; } sc->irq_ctx[qid - 1].op_reply_q = NULL; if (sc->op_reply_q[qid - 1].q_base_phys != 0) bus_dmamap_unload(sc->op_reply_q[qid - 1].q_base_tag, sc->op_reply_q[qid - 1].q_base_dmamap); if (sc->op_reply_q[qid - 1].q_base != NULL) bus_dmamem_free(sc->op_reply_q[qid - 1].q_base_tag, sc->op_reply_q[qid - 1].q_base, sc->op_reply_q[qid - 1].q_base_dmamap); if (sc->op_reply_q[qid - 1].q_base_tag != NULL) bus_dma_tag_destroy(sc->op_reply_q[qid - 1].q_base_tag); sc->op_reply_q[qid - 1].q_base = NULL; sc->op_reply_q[qid - 1].qid = 0; out_unlock: sc->init_cmds.state = MPI3MR_CMD_NOTUSED; mtx_unlock(&sc->init_cmds.completion.lock); out: return retval; } /** * mpi3mr_create_op_reply_queue - create operational reply queue * @sc: Adapter instance reference * @qid: operational reply queue id * * Create operatinal reply queue by issuing MPI request * through admin queue. * * Return: 0 on success, non-zero on failure. */ static int mpi3mr_create_op_reply_queue(struct mpi3mr_softc *sc, U16 qid) { Mpi3CreateReplyQueueRequest_t create_req; struct mpi3mr_op_reply_queue *op_reply_q; int retval = 0; char q_lock_name[32]; op_reply_q = &sc->op_reply_q[qid - 1]; if (op_reply_q->qid) { retval = -1; printf(IOCNAME "CreateRepQ: called for duplicate qid %d\n", sc->name, op_reply_q->qid); return retval; } op_reply_q->ci = 0; if (pci_get_revid(sc->mpi3mr_dev) == SAS4116_CHIP_REV_A0) op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD_A0; else op_reply_q->num_replies = MPI3MR_OP_REP_Q_QD; op_reply_q->qsz = op_reply_q->num_replies * sc->op_reply_sz; op_reply_q->ephase = 1; if (!op_reply_q->q_base) { snprintf(q_lock_name, 32, "Reply Queue Lock[%d]", qid); mtx_init(&op_reply_q->q_lock, q_lock_name, NULL, MTX_SPIN); if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ op_reply_q->qsz, /* maxsize */ 1, /* nsegments */ op_reply_q->qsz, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &op_reply_q->q_base_tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Operational reply DMA tag\n"); return (ENOMEM); } if (bus_dmamem_alloc(op_reply_q->q_base_tag, (void **)&op_reply_q->q_base, BUS_DMA_NOWAIT, &op_reply_q->q_base_dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); return (ENOMEM); } bzero(op_reply_q->q_base, op_reply_q->qsz); bus_dmamap_load(op_reply_q->q_base_tag, op_reply_q->q_base_dmamap, op_reply_q->q_base, op_reply_q->qsz, mpi3mr_memaddr_cb, &op_reply_q->q_base_phys, BUS_DMA_NOWAIT); mpi3mr_dprint(sc, MPI3MR_XINFO, "Operational Reply queue ID: %d phys addr= %#016jx virt_addr: %pa size= %d\n", qid, (uintmax_t)op_reply_q->q_base_phys, op_reply_q->q_base, op_reply_q->qsz); if (!op_reply_q->q_base) { retval = -1; printf(IOCNAME "CreateRepQ: memory alloc failed for qid %d\n", sc->name, qid); goto out; } } memset(&create_req, 0, sizeof(create_req)); mtx_lock(&sc->init_cmds.completion.lock); if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { retval = -1; printf(IOCNAME "CreateRepQ: Init command is in use\n", sc->name); mtx_unlock(&sc->init_cmds.completion.lock); goto out; } sc->init_cmds.state = MPI3MR_CMD_PENDING; sc->init_cmds.is_waiting = 1; sc->init_cmds.callback = NULL; create_req.HostTag = MPI3MR_HOSTTAG_INITCMDS; create_req.Function = MPI3_FUNCTION_CREATE_REPLY_QUEUE; create_req.QueueID = qid; create_req.Flags = MPI3_CREATE_REPLY_QUEUE_FLAGS_INT_ENABLE_ENABLE; create_req.MSIxIndex = sc->irq_ctx[qid - 1].msix_index; create_req.BaseAddress = (U64)op_reply_q->q_base_phys; create_req.Size = op_reply_q->num_replies; init_completion(&sc->init_cmds.completion); retval = mpi3mr_submit_admin_cmd(sc, &create_req, sizeof(create_req)); if (retval) { printf(IOCNAME "CreateRepQ: Admin Post failed\n", sc->name); goto out_unlock; } wait_for_completion_timeout(&sc->init_cmds.completion, MPI3MR_INTADMCMD_TIMEOUT); if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { printf(IOCNAME "CreateRepQ: command timed out\n", sc->name); mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_CREATEREPQ_TIMEOUT); sc->unrecoverable = 1; retval = -1; goto out_unlock; } if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) != MPI3_IOCSTATUS_SUCCESS ) { printf(IOCNAME "CreateRepQ: Failed IOCStatus(0x%04x) " " Loginfo(0x%08x) \n" , sc->name, (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), sc->init_cmds.ioc_loginfo); retval = -1; goto out_unlock; } op_reply_q->qid = qid; sc->irq_ctx[qid - 1].op_reply_q = op_reply_q; out_unlock: sc->init_cmds.state = MPI3MR_CMD_NOTUSED; mtx_unlock(&sc->init_cmds.completion.lock); out: if (retval) { if (op_reply_q->q_base_phys != 0) bus_dmamap_unload(op_reply_q->q_base_tag, op_reply_q->q_base_dmamap); if (op_reply_q->q_base != NULL) bus_dmamem_free(op_reply_q->q_base_tag, op_reply_q->q_base, op_reply_q->q_base_dmamap); if (op_reply_q->q_base_tag != NULL) bus_dma_tag_destroy(op_reply_q->q_base_tag); op_reply_q->q_base = NULL; op_reply_q->qid = 0; } return retval; } /** * mpi3mr_create_op_req_queue - create operational request queue * @sc: Adapter instance reference * @req_qid: operational request queue id * @reply_qid: Reply queue ID * * Create operatinal request queue by issuing MPI request * through admin queue. * * Return: 0 on success, non-zero on failure. */ static int mpi3mr_create_op_req_queue(struct mpi3mr_softc *sc, U16 req_qid, U8 reply_qid) { Mpi3CreateRequestQueueRequest_t create_req; struct mpi3mr_op_req_queue *op_req_q; int retval = 0; char q_lock_name[32]; op_req_q = &sc->op_req_q[req_qid - 1]; if (op_req_q->qid) { retval = -1; printf(IOCNAME "CreateReqQ: called for duplicate qid %d\n", sc->name, op_req_q->qid); return retval; } op_req_q->ci = 0; op_req_q->pi = 0; op_req_q->num_reqs = MPI3MR_OP_REQ_Q_QD; op_req_q->qsz = op_req_q->num_reqs * sc->facts.op_req_sz; op_req_q->reply_qid = reply_qid; if (!op_req_q->q_base) { snprintf(q_lock_name, 32, "Request Queue Lock[%d]", req_qid); mtx_init(&op_req_q->q_lock, q_lock_name, NULL, MTX_SPIN); if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ op_req_q->qsz, /* maxsize */ 1, /* nsegments */ op_req_q->qsz, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &op_req_q->q_base_tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); return (ENOMEM); } if (bus_dmamem_alloc(op_req_q->q_base_tag, (void **)&op_req_q->q_base, BUS_DMA_NOWAIT, &op_req_q->q_base_dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); return (ENOMEM); } bzero(op_req_q->q_base, op_req_q->qsz); bus_dmamap_load(op_req_q->q_base_tag, op_req_q->q_base_dmamap, op_req_q->q_base, op_req_q->qsz, mpi3mr_memaddr_cb, &op_req_q->q_base_phys, BUS_DMA_NOWAIT); mpi3mr_dprint(sc, MPI3MR_XINFO, "Operational Request QID: %d phys addr= %#016jx virt addr= %pa size= %d associated Reply QID: %d\n", req_qid, (uintmax_t)op_req_q->q_base_phys, op_req_q->q_base, op_req_q->qsz, reply_qid); if (!op_req_q->q_base) { retval = -1; printf(IOCNAME "CreateReqQ: memory alloc failed for qid %d\n", sc->name, req_qid); goto out; } } memset(&create_req, 0, sizeof(create_req)); mtx_lock(&sc->init_cmds.completion.lock); if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { retval = -1; printf(IOCNAME "CreateReqQ: Init command is in use\n", sc->name); mtx_unlock(&sc->init_cmds.completion.lock); goto out; } sc->init_cmds.state = MPI3MR_CMD_PENDING; sc->init_cmds.is_waiting = 1; sc->init_cmds.callback = NULL; create_req.HostTag = MPI3MR_HOSTTAG_INITCMDS; create_req.Function = MPI3_FUNCTION_CREATE_REQUEST_QUEUE; create_req.QueueID = req_qid; create_req.Flags = 0; create_req.ReplyQueueID = reply_qid; create_req.BaseAddress = (U64)op_req_q->q_base_phys; create_req.Size = op_req_q->num_reqs; init_completion(&sc->init_cmds.completion); retval = mpi3mr_submit_admin_cmd(sc, &create_req, sizeof(create_req)); if (retval) { printf(IOCNAME "CreateReqQ: Admin Post failed\n", sc->name); goto out_unlock; } wait_for_completion_timeout(&sc->init_cmds.completion, (MPI3MR_INTADMCMD_TIMEOUT)); if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { printf(IOCNAME "CreateReqQ: command timed out\n", sc->name); mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_CREATEREQQ_TIMEOUT); sc->unrecoverable = 1; retval = -1; goto out_unlock; } if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) != MPI3_IOCSTATUS_SUCCESS ) { printf(IOCNAME "CreateReqQ: Failed IOCStatus(0x%04x) " " Loginfo(0x%08x) \n" , sc->name, (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), sc->init_cmds.ioc_loginfo); retval = -1; goto out_unlock; } op_req_q->qid = req_qid; out_unlock: sc->init_cmds.state = MPI3MR_CMD_NOTUSED; mtx_unlock(&sc->init_cmds.completion.lock); out: if (retval) { if (op_req_q->q_base_phys != 0) bus_dmamap_unload(op_req_q->q_base_tag, op_req_q->q_base_dmamap); if (op_req_q->q_base != NULL) bus_dmamem_free(op_req_q->q_base_tag, op_req_q->q_base, op_req_q->q_base_dmamap); if (op_req_q->q_base_tag != NULL) bus_dma_tag_destroy(op_req_q->q_base_tag); op_req_q->q_base = NULL; op_req_q->qid = 0; } return retval; } /** * mpi3mr_create_op_queues - create operational queues * @sc: Adapter instance reference * * Create operatinal queues(request queues and reply queues). * Return: 0 on success, non-zero on failure. */ static int mpi3mr_create_op_queues(struct mpi3mr_softc *sc) { int retval = 0; U16 num_queues = 0, i = 0, qid; num_queues = min(sc->facts.max_op_reply_q, sc->facts.max_op_req_q); num_queues = min(num_queues, sc->msix_count); /* * During reset set the num_queues to the number of queues * that was set before the reset. */ if (sc->num_queues) num_queues = sc->num_queues; mpi3mr_dprint(sc, MPI3MR_XINFO, "Trying to create %d Operational Q pairs\n", num_queues); if (!sc->op_req_q) { sc->op_req_q = malloc(sizeof(struct mpi3mr_op_req_queue) * num_queues, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->op_req_q) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to alloc memory for Request queue info\n"); retval = -1; goto out_failed; } } if (!sc->op_reply_q) { sc->op_reply_q = malloc(sizeof(struct mpi3mr_op_reply_queue) * num_queues, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->op_reply_q) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to alloc memory for Reply queue info\n"); retval = -1; goto out_failed; } } sc->num_hosttag_op_req_q = (sc->max_host_ios + 1) / num_queues; /*Operational Request and reply queue ID starts with 1*/ for (i = 0; i < num_queues; i++) { qid = i + 1; if (mpi3mr_create_op_reply_queue(sc, qid)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to create Reply queue %d\n", qid); break; } if (mpi3mr_create_op_req_queue(sc, qid, sc->op_reply_q[qid - 1].qid)) { mpi3mr_delete_op_reply_queue(sc, qid); mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to create Request queue %d\n", qid); break; } } /* Not even one queue is created successfully*/ if (i == 0) { retval = -1; goto out_failed; } if (!sc->num_queues) { sc->num_queues = i; } else { if (num_queues != i) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Number of queues (%d) post reset are not same as" "queues allocated (%d) during driver init\n", i, num_queues); goto out_failed; } } mpi3mr_dprint(sc, MPI3MR_INFO, "Successfully created %d Operational Queue pairs\n", sc->num_queues); mpi3mr_dprint(sc, MPI3MR_INFO, "Request Queue QD: %d Reply queue QD: %d\n", sc->op_req_q[0].num_reqs, sc->op_reply_q[0].num_replies); return retval; out_failed: if (sc->op_req_q) { free(sc->op_req_q, M_MPI3MR); sc->op_req_q = NULL; } if (sc->op_reply_q) { free(sc->op_reply_q, M_MPI3MR); sc->op_reply_q = NULL; } return retval; } /** * mpi3mr_setup_admin_qpair - Setup admin queue pairs * @sc: Adapter instance reference * * Allocation and setup admin queues(request queues and reply queues). * Return: 0 on success, non-zero on failure. */ static int mpi3mr_setup_admin_qpair(struct mpi3mr_softc *sc) { int retval = 0; U32 num_adm_entries = 0; sc->admin_req_q_sz = MPI3MR_AREQQ_SIZE; sc->num_admin_reqs = sc->admin_req_q_sz / MPI3MR_AREQ_FRAME_SZ; sc->admin_req_ci = sc->admin_req_pi = 0; sc->admin_reply_q_sz = MPI3MR_AREPQ_SIZE; sc->num_admin_replies = sc->admin_reply_q_sz/ MPI3MR_AREP_FRAME_SZ; sc->admin_reply_ci = 0; sc->admin_reply_ephase = 1; if (!sc->admin_req) { /* * We need to create the tag for the admin queue to get the * iofacts to see how many bits the controller decodes. Solve * this chicken and egg problem by only doing lower 4GB DMA. */ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sc->admin_req_q_sz, /* maxsize */ 1, /* nsegments */ sc->admin_req_q_sz, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->admin_req_tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); return (ENOMEM); } if (bus_dmamem_alloc(sc->admin_req_tag, (void **)&sc->admin_req, BUS_DMA_NOWAIT, &sc->admin_req_dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); return (ENOMEM); } bzero(sc->admin_req, sc->admin_req_q_sz); bus_dmamap_load(sc->admin_req_tag, sc->admin_req_dmamap, sc->admin_req, sc->admin_req_q_sz, mpi3mr_memaddr_cb, &sc->admin_req_phys, BUS_DMA_NOWAIT); mpi3mr_dprint(sc, MPI3MR_XINFO, "Admin Req queue phys addr= %#016jx size= %d\n", (uintmax_t)sc->admin_req_phys, sc->admin_req_q_sz); if (!sc->admin_req) { retval = -1; printf(IOCNAME "Memory alloc for AdminReqQ: failed\n", sc->name); goto out_failed; } } if (!sc->admin_reply) { mtx_init(&sc->admin_reply_lock, "Admin Reply Queue Lock", NULL, MTX_SPIN); if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sc->admin_reply_q_sz, /* maxsize */ 1, /* nsegments */ sc->admin_reply_q_sz, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->admin_reply_tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate reply DMA tag\n"); return (ENOMEM); } if (bus_dmamem_alloc(sc->admin_reply_tag, (void **)&sc->admin_reply, BUS_DMA_NOWAIT, &sc->admin_reply_dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); return (ENOMEM); } bzero(sc->admin_reply, sc->admin_reply_q_sz); bus_dmamap_load(sc->admin_reply_tag, sc->admin_reply_dmamap, sc->admin_reply, sc->admin_reply_q_sz, mpi3mr_memaddr_cb, &sc->admin_reply_phys, BUS_DMA_NOWAIT); mpi3mr_dprint(sc, MPI3MR_XINFO, "Admin Reply queue phys addr= %#016jx size= %d\n", (uintmax_t)sc->admin_reply_phys, sc->admin_req_q_sz); if (!sc->admin_reply) { retval = -1; printf(IOCNAME "Memory alloc for AdminRepQ: failed\n", sc->name); goto out_failed; } } num_adm_entries = (sc->num_admin_replies << 16) | (sc->num_admin_reqs); mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_Q_NUM_ENTRIES_OFFSET, num_adm_entries); mpi3mr_regwrite64(sc, MPI3_SYSIF_ADMIN_REQ_Q_ADDR_LOW_OFFSET, sc->admin_req_phys); mpi3mr_regwrite64(sc, MPI3_SYSIF_ADMIN_REPLY_Q_ADDR_LOW_OFFSET, sc->admin_reply_phys); mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REQ_Q_PI_OFFSET, sc->admin_req_pi); mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, sc->admin_reply_ci); return retval; out_failed: /* Free Admin reply*/ if (sc->admin_reply_phys) bus_dmamap_unload(sc->admin_reply_tag, sc->admin_reply_dmamap); if (sc->admin_reply != NULL) bus_dmamem_free(sc->admin_reply_tag, sc->admin_reply, sc->admin_reply_dmamap); if (sc->admin_reply_tag != NULL) bus_dma_tag_destroy(sc->admin_reply_tag); /* Free Admin request*/ if (sc->admin_req_phys) bus_dmamap_unload(sc->admin_req_tag, sc->admin_req_dmamap); if (sc->admin_req != NULL) bus_dmamem_free(sc->admin_req_tag, sc->admin_req, sc->admin_req_dmamap); if (sc->admin_req_tag != NULL) bus_dma_tag_destroy(sc->admin_req_tag); return retval; } /** * mpi3mr_print_fault_info - Display fault information * @sc: Adapter instance reference * * Display the controller fault information if there is a * controller fault. * * Return: Nothing. */ static void mpi3mr_print_fault_info(struct mpi3mr_softc *sc) { U32 ioc_status, code, code1, code2, code3; ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) { code = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_OFFSET) & MPI3_SYSIF_FAULT_CODE_MASK; code1 = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_INFO0_OFFSET); code2 = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_INFO1_OFFSET); code3 = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_INFO2_OFFSET); printf(IOCNAME "fault codes 0x%04x:0x%04x:0x%04x:0x%04x\n", sc->name, code, code1, code2, code3); } } enum mpi3mr_iocstate mpi3mr_get_iocstate(struct mpi3mr_softc *sc) { U32 ioc_status, ioc_control; U8 ready, enabled; ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); ioc_control = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); if(sc->unrecoverable) return MRIOC_STATE_UNRECOVERABLE; if (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) return MRIOC_STATE_FAULT; ready = (ioc_status & MPI3_SYSIF_IOC_STATUS_READY); enabled = (ioc_control & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC); if (ready && enabled) return MRIOC_STATE_READY; if ((!ready) && (!enabled)) return MRIOC_STATE_RESET; if ((!ready) && (enabled)) return MRIOC_STATE_BECOMING_READY; return MRIOC_STATE_RESET_REQUESTED; } static inline void mpi3mr_clear_resethistory(struct mpi3mr_softc *sc) { U32 ioc_status; ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_STATUS_OFFSET, ioc_status); } /** * mpi3mr_mur_ioc - Message unit Reset handler * @sc: Adapter instance reference * @reset_reason: Reset reason code * * Issue Message unit Reset to the controller and wait for it to * be complete. * * Return: 0 on success, -1 on failure. */ static int mpi3mr_mur_ioc(struct mpi3mr_softc *sc, U16 reset_reason) { U32 ioc_config, timeout, ioc_status, scratch_pad0; int retval = -1; mpi3mr_dprint(sc, MPI3MR_INFO, "Issuing Message Unit Reset(MUR)\n"); if (sc->unrecoverable) { mpi3mr_dprint(sc, MPI3MR_ERROR, "IOC is unrecoverable MUR not issued\n"); return retval; } mpi3mr_clear_resethistory(sc); scratch_pad0 = ((MPI3MR_RESET_REASON_OSTYPE_FREEBSD << MPI3MR_RESET_REASON_OSTYPE_SHIFT) | (sc->facts.ioc_num << MPI3MR_RESET_REASON_IOCNUM_SHIFT) | reset_reason); mpi3mr_regwrite(sc, MPI3_SYSIF_SCRATCHPAD0_OFFSET, scratch_pad0); ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); ioc_config &= ~MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC; mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); timeout = MPI3MR_MUR_TIMEOUT * 10; do { ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); if ((ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY)) { mpi3mr_clear_resethistory(sc); ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); if (!((ioc_status & MPI3_SYSIF_IOC_STATUS_READY) || (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) || (ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC))) { retval = 0; break; } } DELAY(100 * 1000); } while (--timeout); ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); mpi3mr_dprint(sc, MPI3MR_INFO, "IOC Status/Config after %s MUR is (0x%x)/(0x%x)\n", !retval ? "successful":"failed", ioc_status, ioc_config); return retval; } /** * mpi3mr_bring_ioc_ready - Bring controller to ready state * @sc: Adapter instance reference * * Set Enable IOC bit in IOC configuration register and wait for * the controller to become ready. * * Return: 0 on success, appropriate error on failure. */ static int mpi3mr_bring_ioc_ready(struct mpi3mr_softc *sc) { U32 ioc_config, timeout; enum mpi3mr_iocstate current_state; ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); ioc_config |= MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC; mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); timeout = sc->ready_timeout * 10; do { current_state = mpi3mr_get_iocstate(sc); if (current_state == MRIOC_STATE_READY) return 0; DELAY(100 * 1000); } while (--timeout); return -1; } static const struct { enum mpi3mr_iocstate value; char *name; } mrioc_states[] = { { MRIOC_STATE_READY, "ready" }, { MRIOC_STATE_FAULT, "fault" }, { MRIOC_STATE_RESET, "reset" }, { MRIOC_STATE_BECOMING_READY, "becoming ready" }, { MRIOC_STATE_RESET_REQUESTED, "reset requested" }, { MRIOC_STATE_COUNT, "Count" }, }; static const char *mpi3mr_iocstate_name(enum mpi3mr_iocstate mrioc_state) { int i; char *name = NULL; for (i = 0; i < MRIOC_STATE_COUNT; i++) { if (mrioc_states[i].value == mrioc_state){ name = mrioc_states[i].name; break; } } return name; } /* Reset reason to name mapper structure*/ static const struct { enum mpi3mr_reset_reason value; char *name; } mpi3mr_reset_reason_codes[] = { { MPI3MR_RESET_FROM_BRINGUP, "timeout in bringup" }, { MPI3MR_RESET_FROM_FAULT_WATCH, "fault" }, { MPI3MR_RESET_FROM_IOCTL, "application" }, { MPI3MR_RESET_FROM_EH_HOS, "error handling" }, { MPI3MR_RESET_FROM_TM_TIMEOUT, "TM timeout" }, { MPI3MR_RESET_FROM_IOCTL_TIMEOUT, "IOCTL timeout" }, { MPI3MR_RESET_FROM_SCSIIO_TIMEOUT, "SCSIIO timeout" }, { MPI3MR_RESET_FROM_MUR_FAILURE, "MUR failure" }, { MPI3MR_RESET_FROM_CTLR_CLEANUP, "timeout in controller cleanup" }, { MPI3MR_RESET_FROM_CIACTIV_FAULT, "component image activation fault" }, { MPI3MR_RESET_FROM_PE_TIMEOUT, "port enable timeout" }, { MPI3MR_RESET_FROM_TSU_TIMEOUT, "time stamp update timeout" }, { MPI3MR_RESET_FROM_DELREQQ_TIMEOUT, "delete request queue timeout" }, { MPI3MR_RESET_FROM_DELREPQ_TIMEOUT, "delete reply queue timeout" }, { MPI3MR_RESET_FROM_CREATEREPQ_TIMEOUT, "create request queue timeout" }, { MPI3MR_RESET_FROM_CREATEREQQ_TIMEOUT, "create reply queue timeout" }, { MPI3MR_RESET_FROM_IOCFACTS_TIMEOUT, "IOC facts timeout" }, { MPI3MR_RESET_FROM_IOCINIT_TIMEOUT, "IOC init timeout" }, { MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT, "event notify timeout" }, { MPI3MR_RESET_FROM_EVTACK_TIMEOUT, "event acknowledgment timeout" }, { MPI3MR_RESET_FROM_CIACTVRST_TIMER, "component image activation timeout" }, { MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT, "get package version timeout" }, { MPI3MR_RESET_FROM_PELABORT_TIMEOUT, "persistent event log abort timeout" }, { MPI3MR_RESET_FROM_SYSFS, "sysfs invocation" }, { MPI3MR_RESET_FROM_SYSFS_TIMEOUT, "sysfs TM timeout" }, { MPI3MR_RESET_FROM_DIAG_BUFFER_POST_TIMEOUT, "diagnostic buffer post timeout" }, { MPI3MR_RESET_FROM_FIRMWARE, "firmware asynchronus reset" }, { MPI3MR_RESET_REASON_COUNT, "Reset reason count" }, }; /** * mpi3mr_reset_rc_name - get reset reason code name * @reason_code: reset reason code value * * Map reset reason to an NULL terminated ASCII string * * Return: Name corresponding to reset reason value or NULL. */ static const char *mpi3mr_reset_rc_name(enum mpi3mr_reset_reason reason_code) { int i; char *name = NULL; for (i = 0; i < MPI3MR_RESET_REASON_COUNT; i++) { if (mpi3mr_reset_reason_codes[i].value == reason_code) { name = mpi3mr_reset_reason_codes[i].name; break; } } return name; } #define MAX_RESET_TYPE 3 /* Reset type to name mapper structure*/ static const struct { U16 reset_type; char *name; } mpi3mr_reset_types[] = { { MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, "soft" }, { MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, "diag fault" }, { MAX_RESET_TYPE, "count"} }; /** * mpi3mr_reset_type_name - get reset type name * @reset_type: reset type value * * Map reset type to an NULL terminated ASCII string * * Return: Name corresponding to reset type value or NULL. */ static const char *mpi3mr_reset_type_name(U16 reset_type) { int i; char *name = NULL; for (i = 0; i < MAX_RESET_TYPE; i++) { if (mpi3mr_reset_types[i].reset_type == reset_type) { name = mpi3mr_reset_types[i].name; break; } } return name; } /** * mpi3mr_soft_reset_success - Check softreset is success or not * @ioc_status: IOC status register value * @ioc_config: IOC config register value * * Check whether the soft reset is successful or not based on * IOC status and IOC config register values. * * Return: True when the soft reset is success, false otherwise. */ static inline bool mpi3mr_soft_reset_success(U32 ioc_status, U32 ioc_config) { if (!((ioc_status & MPI3_SYSIF_IOC_STATUS_READY) || (ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT) || (ioc_config & MPI3_SYSIF_IOC_CONFIG_ENABLE_IOC))) return true; return false; } /** * mpi3mr_diagfault_success - Check diag fault is success or not * @sc: Adapter reference * @ioc_status: IOC status register value * * Check whether the controller hit diag reset fault code. * * Return: True when there is diag fault, false otherwise. */ static inline bool mpi3mr_diagfault_success(struct mpi3mr_softc *sc, U32 ioc_status) { if (!(ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) return false; mpi3mr_print_fault_info(sc); return true; } /** * mpi3mr_issue_iocfacts - Send IOC Facts * @sc: Adapter instance reference * @facts_data: Cached IOC facts data * * Issue IOC Facts MPI request through admin queue and wait for * the completion of it or time out. * * Return: 0 on success, non-zero on failures. */ static int mpi3mr_issue_iocfacts(struct mpi3mr_softc *sc, Mpi3IOCFactsData_t *facts_data) { Mpi3IOCFactsRequest_t iocfacts_req; bus_dma_tag_t data_tag = NULL; bus_dmamap_t data_map = NULL; bus_addr_t data_phys = 0; void *data = NULL; U32 data_len = sizeof(*facts_data); int retval = 0; U8 sgl_flags = (MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM | MPI3_SGE_FLAGS_END_OF_LIST); /* * We can't use sc->dma_loaddr here. We set those only after we get the * iocfacts. So allocate in the lower 4GB. The amount of data is tiny * and we don't do this that often, so any bouncing we might have to do * isn't a cause for concern. */ if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ data_len, /* maxsize */ 1, /* nsegments */ data_len, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &data_tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); return (ENOMEM); } if (bus_dmamem_alloc(data_tag, (void **)&data, BUS_DMA_NOWAIT, &data_map)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d Data DMA mem alloc failed\n", __func__, __LINE__); return (ENOMEM); } bzero(data, data_len); bus_dmamap_load(data_tag, data_map, data, data_len, mpi3mr_memaddr_cb, &data_phys, BUS_DMA_NOWAIT); mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d IOCfacts data phys addr= %#016jx size= %d\n", __func__, __LINE__, (uintmax_t)data_phys, data_len); if (!data) { retval = -1; printf(IOCNAME "Memory alloc for IOCFactsData: failed\n", sc->name); goto out; } mtx_lock(&sc->init_cmds.completion.lock); memset(&iocfacts_req, 0, sizeof(iocfacts_req)); if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { retval = -1; printf(IOCNAME "Issue IOCFacts: Init command is in use\n", sc->name); mtx_unlock(&sc->init_cmds.completion.lock); goto out; } sc->init_cmds.state = MPI3MR_CMD_PENDING; sc->init_cmds.is_waiting = 1; sc->init_cmds.callback = NULL; iocfacts_req.HostTag = (MPI3MR_HOSTTAG_INITCMDS); iocfacts_req.Function = MPI3_FUNCTION_IOC_FACTS; mpi3mr_add_sg_single(&iocfacts_req.SGL, sgl_flags, data_len, data_phys); init_completion(&sc->init_cmds.completion); retval = mpi3mr_submit_admin_cmd(sc, &iocfacts_req, sizeof(iocfacts_req)); if (retval) { printf(IOCNAME "Issue IOCFacts: Admin Post failed\n", sc->name); goto out_unlock; } wait_for_completion_timeout(&sc->init_cmds.completion, (MPI3MR_INTADMCMD_TIMEOUT)); if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { printf(IOCNAME "Issue IOCFacts: command timed out\n", sc->name); mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_IOCFACTS_TIMEOUT); sc->unrecoverable = 1; retval = -1; goto out_unlock; } if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) != MPI3_IOCSTATUS_SUCCESS ) { printf(IOCNAME "Issue IOCFacts: Failed IOCStatus(0x%04x) " " Loginfo(0x%08x) \n" , sc->name, (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), sc->init_cmds.ioc_loginfo); retval = -1; goto out_unlock; } memcpy(facts_data, (U8 *)data, data_len); out_unlock: sc->init_cmds.state = MPI3MR_CMD_NOTUSED; mtx_unlock(&sc->init_cmds.completion.lock); out: if (data_phys != 0) bus_dmamap_unload(data_tag, data_map); if (data != NULL) bus_dmamem_free(data_tag, data, data_map); if (data_tag != NULL) bus_dma_tag_destroy(data_tag); return retval; } /** * mpi3mr_process_factsdata - Process IOC facts data * @sc: Adapter instance reference * @facts_data: Cached IOC facts data * * Convert IOC facts data into cpu endianness and cache it in * the driver . * * Return: Nothing. */ static int mpi3mr_process_factsdata(struct mpi3mr_softc *sc, Mpi3IOCFactsData_t *facts_data) { int retval = 0; U32 ioc_config, req_sz, facts_flags; struct mpi3mr_compimg_ver *fwver; if (le16toh(facts_data->IOCFactsDataLength) != (sizeof(*facts_data) / 4)) { mpi3mr_dprint(sc, MPI3MR_INFO, "IOCFacts data length mismatch " " driver_sz(%ld) firmware_sz(%d) \n", sizeof(*facts_data), facts_data->IOCFactsDataLength); } ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); req_sz = 1 << ((ioc_config & MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ) >> MPI3_SYSIF_IOC_CONFIG_OPER_REQ_ENT_SZ_SHIFT); if (facts_data->IOCRequestFrameSize != (req_sz/4)) { mpi3mr_dprint(sc, MPI3MR_INFO, "IOCFacts data reqFrameSize mismatch " " hw_size(%d) firmware_sz(%d) \n" , req_sz/4, facts_data->IOCRequestFrameSize); } memset(&sc->facts, 0, sizeof(sc->facts)); facts_flags = le32toh(facts_data->Flags); sc->facts.op_req_sz = req_sz; sc->op_reply_sz = 1 << ((ioc_config & MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ) >> MPI3_SYSIF_IOC_CONFIG_OPER_RPY_ENT_SZ_SHIFT); sc->facts.ioc_num = facts_data->IOCNumber; sc->facts.who_init = facts_data->WhoInit; sc->facts.max_msix_vectors = facts_data->MaxMSIxVectors; sc->facts.personality = (facts_flags & MPI3_IOCFACTS_FLAGS_PERSONALITY_MASK); sc->facts.dma_mask = (facts_flags & MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_MASK) >> MPI3_IOCFACTS_FLAGS_DMA_ADDRESS_WIDTH_SHIFT; sc->facts.protocol_flags = facts_data->ProtocolFlags; sc->facts.mpi_version = (facts_data->MPIVersion.Word); sc->facts.max_reqs = (facts_data->MaxOutstandingRequests); sc->facts.product_id = (facts_data->ProductID); sc->facts.reply_sz = (facts_data->ReplyFrameSize) * 4; sc->facts.exceptions = (facts_data->IOCExceptions); sc->facts.max_perids = (facts_data->MaxPersistentID); sc->facts.max_vds = (facts_data->MaxVDs); sc->facts.max_hpds = (facts_data->MaxHostPDs); sc->facts.max_advhpds = (facts_data->MaxAdvHostPDs); sc->facts.max_raidpds = (facts_data->MaxRAIDPDs); sc->facts.max_nvme = (facts_data->MaxNVMe); sc->facts.max_pcieswitches = (facts_data->MaxPCIeSwitches); sc->facts.max_sasexpanders = (facts_data->MaxSASExpanders); sc->facts.max_sasinitiators = (facts_data->MaxSASInitiators); sc->facts.max_enclosures = (facts_data->MaxEnclosures); sc->facts.min_devhandle = (facts_data->MinDevHandle); sc->facts.max_devhandle = (facts_data->MaxDevHandle); sc->facts.max_op_req_q = (facts_data->MaxOperationalRequestQueues); sc->facts.max_op_reply_q = (facts_data->MaxOperationalReplyQueues); sc->facts.ioc_capabilities = (facts_data->IOCCapabilities); sc->facts.fw_ver.build_num = (facts_data->FWVersion.BuildNum); sc->facts.fw_ver.cust_id = (facts_data->FWVersion.CustomerID); sc->facts.fw_ver.ph_minor = facts_data->FWVersion.PhaseMinor; sc->facts.fw_ver.ph_major = facts_data->FWVersion.PhaseMajor; sc->facts.fw_ver.gen_minor = facts_data->FWVersion.GenMinor; sc->facts.fw_ver.gen_major = facts_data->FWVersion.GenMajor; sc->max_msix_vectors = min(sc->max_msix_vectors, sc->facts.max_msix_vectors); sc->facts.sge_mod_mask = facts_data->SGEModifierMask; sc->facts.sge_mod_value = facts_data->SGEModifierValue; sc->facts.sge_mod_shift = facts_data->SGEModifierShift; sc->facts.shutdown_timeout = (facts_data->ShutdownTimeout); sc->facts.max_dev_per_tg = facts_data->MaxDevicesPerThrottleGroup; sc->facts.io_throttle_data_length = facts_data->IOThrottleDataLength; sc->facts.max_io_throttle_group = facts_data->MaxIOThrottleGroup; sc->facts.io_throttle_low = facts_data->IOThrottleLow; sc->facts.io_throttle_high = facts_data->IOThrottleHigh; /*Store in 512b block count*/ if (sc->facts.io_throttle_data_length) sc->io_throttle_data_length = (sc->facts.io_throttle_data_length * 2 * 4); else /* set the length to 1MB + 1K to disable throttle*/ sc->io_throttle_data_length = MPI3MR_MAX_SECTORS + 2; sc->io_throttle_high = (sc->facts.io_throttle_high * 2 * 1024); sc->io_throttle_low = (sc->facts.io_throttle_low * 2 * 1024); fwver = &sc->facts.fw_ver; snprintf(sc->fw_version, sizeof(sc->fw_version), "%d.%d.%d.%d.%05d-%05d", fwver->gen_major, fwver->gen_minor, fwver->ph_major, fwver->ph_minor, fwver->cust_id, fwver->build_num); mpi3mr_dprint(sc, MPI3MR_INFO, "ioc_num(%d), maxopQ(%d), maxopRepQ(%d), maxdh(%d)," "maxreqs(%d), mindh(%d) maxPDs(%d) maxvectors(%d) maxperids(%d)\n", sc->facts.ioc_num, sc->facts.max_op_req_q, sc->facts.max_op_reply_q, sc->facts.max_devhandle, sc->facts.max_reqs, sc->facts.min_devhandle, sc->facts.max_pds, sc->facts.max_msix_vectors, sc->facts.max_perids); mpi3mr_dprint(sc, MPI3MR_INFO, "SGEModMask 0x%x SGEModVal 0x%x SGEModShift 0x%x\n", sc->facts.sge_mod_mask, sc->facts.sge_mod_value, sc->facts.sge_mod_shift); mpi3mr_dprint(sc, MPI3MR_INFO, "max_dev_per_throttle_group(%d), max_throttle_groups(%d), io_throttle_data_len(%dKiB), io_throttle_high(%dMiB), io_throttle_low(%dMiB)\n", sc->facts.max_dev_per_tg, sc->facts.max_io_throttle_group, sc->facts.io_throttle_data_length * 4, sc->facts.io_throttle_high, sc->facts.io_throttle_low); sc->max_host_ios = sc->facts.max_reqs - (MPI3MR_INTERNALCMDS_RESVD + 1); /* * Set the DMA mask for the card. dma_mask is the number of bits that * can have bits set in them. Translate this into bus_dma loaddr args. * Add sanity for more bits than address space or other overflow * situations. */ if (sc->facts.dma_mask == 0 || (sc->facts.dma_mask >= sizeof(bus_addr_t) * 8)) sc->dma_loaddr = BUS_SPACE_MAXADDR; else sc->dma_loaddr = ~((1ull << sc->facts.dma_mask) - 1); mpi3mr_dprint(sc, MPI3MR_INFO, "dma_mask bits: %d loaddr 0x%jx\n", sc->facts.dma_mask, sc->dma_loaddr); return retval; } static inline void mpi3mr_setup_reply_free_queues(struct mpi3mr_softc *sc) { int i; bus_addr_t phys_addr; /* initialize Reply buffer Queue */ for (i = 0, phys_addr = sc->reply_buf_phys; i < sc->num_reply_bufs; i++, phys_addr += sc->reply_sz) sc->reply_free_q[i] = phys_addr; sc->reply_free_q[i] = (0); /* initialize Sense Buffer Queue */ for (i = 0, phys_addr = sc->sense_buf_phys; i < sc->num_sense_bufs; i++, phys_addr += MPI3MR_SENSEBUF_SZ) sc->sense_buf_q[i] = phys_addr; sc->sense_buf_q[i] = (0); } static int mpi3mr_reply_dma_alloc(struct mpi3mr_softc *sc) { U32 sz; sc->num_reply_bufs = sc->facts.max_reqs + MPI3MR_NUM_EVTREPLIES; sc->reply_free_q_sz = sc->num_reply_bufs + 1; sc->num_sense_bufs = sc->facts.max_reqs / MPI3MR_SENSEBUF_FACTOR; sc->sense_buf_q_sz = sc->num_sense_bufs + 1; sz = sc->num_reply_bufs * sc->reply_sz; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 16, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sz, /* maxsize */ 1, /* nsegments */ sz, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->reply_buf_tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); return (ENOMEM); } if (bus_dmamem_alloc(sc->reply_buf_tag, (void **)&sc->reply_buf, BUS_DMA_NOWAIT, &sc->reply_buf_dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n", __func__, __LINE__); return (ENOMEM); } bzero(sc->reply_buf, sz); bus_dmamap_load(sc->reply_buf_tag, sc->reply_buf_dmamap, sc->reply_buf, sz, mpi3mr_memaddr_cb, &sc->reply_buf_phys, BUS_DMA_NOWAIT); sc->reply_buf_dma_min_address = sc->reply_buf_phys; sc->reply_buf_dma_max_address = sc->reply_buf_phys + sz; mpi3mr_dprint(sc, MPI3MR_XINFO, "reply buf (0x%p): depth(%d), frame_size(%d), " "pool_size(%d kB), reply_buf_dma(0x%llx)\n", sc->reply_buf, sc->num_reply_bufs, sc->reply_sz, (sz / 1024), (unsigned long long)sc->reply_buf_phys); /* reply free queue, 8 byte align */ sz = sc->reply_free_q_sz * 8; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 8, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sz, /* maxsize */ 1, /* nsegments */ sz, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->reply_free_q_tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate reply free queue DMA tag\n"); return (ENOMEM); } if (bus_dmamem_alloc(sc->reply_free_q_tag, (void **)&sc->reply_free_q, BUS_DMA_NOWAIT, &sc->reply_free_q_dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n", __func__, __LINE__); return (ENOMEM); } bzero(sc->reply_free_q, sz); bus_dmamap_load(sc->reply_free_q_tag, sc->reply_free_q_dmamap, sc->reply_free_q, sz, mpi3mr_memaddr_cb, &sc->reply_free_q_phys, BUS_DMA_NOWAIT); mpi3mr_dprint(sc, MPI3MR_XINFO, "reply_free_q (0x%p): depth(%d), frame_size(%d), " "pool_size(%d kB), reply_free_q_dma(0x%llx)\n", sc->reply_free_q, sc->reply_free_q_sz, 8, (sz / 1024), (unsigned long long)sc->reply_free_q_phys); /* sense buffer pool, 4 byte align */ sz = sc->num_sense_bufs * MPI3MR_SENSEBUF_SZ; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sz, /* maxsize */ 1, /* nsegments */ sz, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->sense_buf_tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Sense buffer DMA tag\n"); return (ENOMEM); } if (bus_dmamem_alloc(sc->sense_buf_tag, (void **)&sc->sense_buf, BUS_DMA_NOWAIT, &sc->sense_buf_dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n", __func__, __LINE__); return (ENOMEM); } bzero(sc->sense_buf, sz); bus_dmamap_load(sc->sense_buf_tag, sc->sense_buf_dmamap, sc->sense_buf, sz, mpi3mr_memaddr_cb, &sc->sense_buf_phys, BUS_DMA_NOWAIT); mpi3mr_dprint(sc, MPI3MR_XINFO, "sense_buf (0x%p): depth(%d), frame_size(%d), " "pool_size(%d kB), sense_dma(0x%llx)\n", sc->sense_buf, sc->num_sense_bufs, MPI3MR_SENSEBUF_SZ, (sz / 1024), (unsigned long long)sc->sense_buf_phys); /* sense buffer queue, 8 byte align */ sz = sc->sense_buf_q_sz * 8; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 8, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sz, /* maxsize */ 1, /* nsegments */ sz, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->sense_buf_q_tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Sense buffer Queue DMA tag\n"); return (ENOMEM); } if (bus_dmamem_alloc(sc->sense_buf_q_tag, (void **)&sc->sense_buf_q, BUS_DMA_NOWAIT, &sc->sense_buf_q_dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n", __func__, __LINE__); return (ENOMEM); } bzero(sc->sense_buf_q, sz); bus_dmamap_load(sc->sense_buf_q_tag, sc->sense_buf_q_dmamap, sc->sense_buf_q, sz, mpi3mr_memaddr_cb, &sc->sense_buf_q_phys, BUS_DMA_NOWAIT); mpi3mr_dprint(sc, MPI3MR_XINFO, "sense_buf_q (0x%p): depth(%d), frame_size(%d), " "pool_size(%d kB), sense_dma(0x%llx)\n", sc->sense_buf_q, sc->sense_buf_q_sz, 8, (sz / 1024), (unsigned long long)sc->sense_buf_q_phys); return 0; } static int mpi3mr_reply_alloc(struct mpi3mr_softc *sc) { int retval = 0; U32 i; if (sc->init_cmds.reply) goto post_reply_sbuf; sc->init_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->init_cmds.reply) { printf(IOCNAME "Cannot allocate memory for init_cmds.reply\n", sc->name); goto out_failed; } sc->ioctl_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->ioctl_cmds.reply) { printf(IOCNAME "Cannot allocate memory for ioctl_cmds.reply\n", sc->name); goto out_failed; } sc->host_tm_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->host_tm_cmds.reply) { printf(IOCNAME "Cannot allocate memory for host_tm.reply\n", sc->name); goto out_failed; } for (i=0; idev_rmhs_cmds[i].reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->dev_rmhs_cmds[i].reply) { printf(IOCNAME "Cannot allocate memory for" " dev_rmhs_cmd[%d].reply\n", sc->name, i); goto out_failed; } } for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) { sc->evtack_cmds[i].reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->evtack_cmds[i].reply) goto out_failed; } sc->dev_handle_bitmap_sz = MPI3MR_DIV_ROUND_UP(sc->facts.max_devhandle, 8); sc->removepend_bitmap = malloc(sc->dev_handle_bitmap_sz, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->removepend_bitmap) { printf(IOCNAME "Cannot alloc memory for remove pend bitmap\n", sc->name); goto out_failed; } sc->devrem_bitmap_sz = MPI3MR_DIV_ROUND_UP(MPI3MR_NUM_DEVRMCMD, 8); sc->devrem_bitmap = malloc(sc->devrem_bitmap_sz, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->devrem_bitmap) { printf(IOCNAME "Cannot alloc memory for dev remove bitmap\n", sc->name); goto out_failed; } sc->evtack_cmds_bitmap_sz = MPI3MR_DIV_ROUND_UP(MPI3MR_NUM_EVTACKCMD, 8); sc->evtack_cmds_bitmap = malloc(sc->evtack_cmds_bitmap_sz, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->evtack_cmds_bitmap) goto out_failed; if (mpi3mr_reply_dma_alloc(sc)) { printf(IOCNAME "func:%s line:%d DMA memory allocation failed\n", sc->name, __func__, __LINE__); goto out_failed; } post_reply_sbuf: mpi3mr_setup_reply_free_queues(sc); return retval; out_failed: mpi3mr_cleanup_interrupts(sc); mpi3mr_free_mem(sc); retval = -1; return retval; } static void mpi3mr_print_fw_pkg_ver(struct mpi3mr_softc *sc) { int retval = 0; void *fw_pkg_ver = NULL; bus_dma_tag_t fw_pkg_ver_tag; bus_dmamap_t fw_pkg_ver_map; bus_addr_t fw_pkg_ver_dma; Mpi3CIUploadRequest_t ci_upload; Mpi3ComponentImageHeader_t *ci_header; U32 fw_pkg_ver_len = sizeof(*ci_header); U8 sgl_flags = MPI3MR_SGEFLAGS_SYSTEM_SIMPLE_END_OF_LIST; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ fw_pkg_ver_len, /* maxsize */ 1, /* nsegments */ fw_pkg_ver_len, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &fw_pkg_ver_tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate fw package version request DMA tag\n"); return; } if (bus_dmamem_alloc(fw_pkg_ver_tag, (void **)&fw_pkg_ver, BUS_DMA_NOWAIT, &fw_pkg_ver_map)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d fw package version DMA mem alloc failed\n", __func__, __LINE__); return; } bzero(fw_pkg_ver, fw_pkg_ver_len); bus_dmamap_load(fw_pkg_ver_tag, fw_pkg_ver_map, fw_pkg_ver, fw_pkg_ver_len, mpi3mr_memaddr_cb, &fw_pkg_ver_dma, BUS_DMA_NOWAIT); mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d fw package version phys addr= %#016jx size= %d\n", __func__, __LINE__, (uintmax_t)fw_pkg_ver_dma, fw_pkg_ver_len); if (!fw_pkg_ver) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Memory alloc for fw package version failed\n"); goto out; } memset(&ci_upload, 0, sizeof(ci_upload)); mtx_lock(&sc->init_cmds.completion.lock); if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { mpi3mr_dprint(sc, MPI3MR_INFO,"Issue CI Header Upload: command is in use\n"); mtx_unlock(&sc->init_cmds.completion.lock); goto out; } sc->init_cmds.state = MPI3MR_CMD_PENDING; sc->init_cmds.is_waiting = 1; sc->init_cmds.callback = NULL; ci_upload.HostTag = htole16(MPI3MR_HOSTTAG_INITCMDS); ci_upload.Function = MPI3_FUNCTION_CI_UPLOAD; ci_upload.MsgFlags = MPI3_CI_UPLOAD_MSGFLAGS_LOCATION_PRIMARY; ci_upload.ImageOffset = MPI3_IMAGE_HEADER_SIGNATURE0_OFFSET; ci_upload.SegmentSize = MPI3_IMAGE_HEADER_SIZE; mpi3mr_add_sg_single(&ci_upload.SGL, sgl_flags, fw_pkg_ver_len, fw_pkg_ver_dma); init_completion(&sc->init_cmds.completion); if ((retval = mpi3mr_submit_admin_cmd(sc, &ci_upload, sizeof(ci_upload)))) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue CI Header Upload: Admin Post failed\n"); goto out_unlock; } wait_for_completion_timeout(&sc->init_cmds.completion, (MPI3MR_INTADMCMD_TIMEOUT)); if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue CI Header Upload: command timed out\n"); sc->init_cmds.is_waiting = 0; if (!(sc->init_cmds.state & MPI3MR_CMD_RESET)) mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_GETPKGVER_TIMEOUT); goto out_unlock; } if ((GET_IOC_STATUS(sc->init_cmds.ioc_status)) != MPI3_IOCSTATUS_SUCCESS) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Issue CI Header Upload: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", GET_IOC_STATUS(sc->init_cmds.ioc_status), sc->init_cmds.ioc_loginfo); goto out_unlock; } ci_header = (Mpi3ComponentImageHeader_t *) fw_pkg_ver; mpi3mr_dprint(sc, MPI3MR_XINFO, "Issue CI Header Upload:EnvVariableOffset(0x%x) \ HeaderSize(0x%x) Signature1(0x%x)\n", ci_header->EnvironmentVariableOffset, ci_header->HeaderSize, ci_header->Signature1); mpi3mr_dprint(sc, MPI3MR_INFO, "FW Package Version: %02d.%02d.%02d.%02d\n", ci_header->ComponentImageVersion.GenMajor, ci_header->ComponentImageVersion.GenMinor, ci_header->ComponentImageVersion.PhaseMajor, ci_header->ComponentImageVersion.PhaseMinor); out_unlock: sc->init_cmds.state = MPI3MR_CMD_NOTUSED; mtx_unlock(&sc->init_cmds.completion.lock); out: if (fw_pkg_ver_dma != 0) bus_dmamap_unload(fw_pkg_ver_tag, fw_pkg_ver_map); if (fw_pkg_ver) bus_dmamem_free(fw_pkg_ver_tag, fw_pkg_ver, fw_pkg_ver_map); if (fw_pkg_ver_tag) bus_dma_tag_destroy(fw_pkg_ver_tag); } /** * mpi3mr_issue_iocinit - Send IOC Init * @sc: Adapter instance reference * * Issue IOC Init MPI request through admin queue and wait for * the completion of it or time out. * * Return: 0 on success, non-zero on failures. */ static int mpi3mr_issue_iocinit(struct mpi3mr_softc *sc) { Mpi3IOCInitRequest_t iocinit_req; Mpi3DriverInfoLayout_t *drvr_info = NULL; bus_dma_tag_t drvr_info_tag; bus_dmamap_t drvr_info_map; bus_addr_t drvr_info_phys; U32 drvr_info_len = sizeof(*drvr_info); int retval = 0; struct timeval now; uint64_t time_in_msec; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ drvr_info_len, /* maxsize */ 1, /* nsegments */ drvr_info_len, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &drvr_info_tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); return (ENOMEM); } if (bus_dmamem_alloc(drvr_info_tag, (void **)&drvr_info, BUS_DMA_NOWAIT, &drvr_info_map)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d Data DMA mem alloc failed\n", __func__, __LINE__); return (ENOMEM); } bzero(drvr_info, drvr_info_len); bus_dmamap_load(drvr_info_tag, drvr_info_map, drvr_info, drvr_info_len, mpi3mr_memaddr_cb, &drvr_info_phys, BUS_DMA_NOWAIT); mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d IOCfacts drvr_info phys addr= %#016jx size= %d\n", __func__, __LINE__, (uintmax_t)drvr_info_phys, drvr_info_len); if (!drvr_info) { retval = -1; printf(IOCNAME "Memory alloc for Driver Info failed\n", sc->name); goto out; } drvr_info->InformationLength = (drvr_info_len); strcpy(drvr_info->DriverSignature, "Broadcom"); strcpy(drvr_info->OsName, "FreeBSD"); strcpy(drvr_info->OsVersion, fmt_os_ver); strcpy(drvr_info->DriverName, MPI3MR_DRIVER_NAME); strcpy(drvr_info->DriverVersion, MPI3MR_DRIVER_VERSION); strcpy(drvr_info->DriverReleaseDate, MPI3MR_DRIVER_RELDATE); drvr_info->DriverCapabilities = 0; memcpy((U8 *)&sc->driver_info, (U8 *)drvr_info, sizeof(sc->driver_info)); memset(&iocinit_req, 0, sizeof(iocinit_req)); mtx_lock(&sc->init_cmds.completion.lock); if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { retval = -1; printf(IOCNAME "Issue IOCInit: Init command is in use\n", sc->name); mtx_unlock(&sc->init_cmds.completion.lock); goto out; } sc->init_cmds.state = MPI3MR_CMD_PENDING; sc->init_cmds.is_waiting = 1; sc->init_cmds.callback = NULL; iocinit_req.HostTag = MPI3MR_HOSTTAG_INITCMDS; iocinit_req.Function = MPI3_FUNCTION_IOC_INIT; iocinit_req.MPIVersion.Struct.Dev = MPI3_VERSION_DEV; iocinit_req.MPIVersion.Struct.Unit = MPI3_VERSION_UNIT; iocinit_req.MPIVersion.Struct.Major = MPI3_VERSION_MAJOR; iocinit_req.MPIVersion.Struct.Minor = MPI3_VERSION_MINOR; iocinit_req.WhoInit = MPI3_WHOINIT_HOST_DRIVER; iocinit_req.ReplyFreeQueueDepth = sc->reply_free_q_sz; iocinit_req.ReplyFreeQueueAddress = sc->reply_free_q_phys; iocinit_req.SenseBufferLength = MPI3MR_SENSEBUF_SZ; iocinit_req.SenseBufferFreeQueueDepth = sc->sense_buf_q_sz; iocinit_req.SenseBufferFreeQueueAddress = sc->sense_buf_q_phys; iocinit_req.DriverInformationAddress = drvr_info_phys; getmicrotime(&now); time_in_msec = (now.tv_sec * 1000 + now.tv_usec/1000); iocinit_req.TimeStamp = htole64(time_in_msec); init_completion(&sc->init_cmds.completion); retval = mpi3mr_submit_admin_cmd(sc, &iocinit_req, sizeof(iocinit_req)); if (retval) { printf(IOCNAME "Issue IOCInit: Admin Post failed\n", sc->name); goto out_unlock; } wait_for_completion_timeout(&sc->init_cmds.completion, (MPI3MR_INTADMCMD_TIMEOUT)); if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { printf(IOCNAME "Issue IOCInit: command timed out\n", sc->name); mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_IOCINIT_TIMEOUT); sc->unrecoverable = 1; retval = -1; goto out_unlock; } if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) != MPI3_IOCSTATUS_SUCCESS ) { printf(IOCNAME "Issue IOCInit: Failed IOCStatus(0x%04x) " " Loginfo(0x%08x) \n" , sc->name, (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), sc->init_cmds.ioc_loginfo); retval = -1; goto out_unlock; } out_unlock: sc->init_cmds.state = MPI3MR_CMD_NOTUSED; mtx_unlock(&sc->init_cmds.completion.lock); out: if (drvr_info_phys != 0) bus_dmamap_unload(drvr_info_tag, drvr_info_map); if (drvr_info != NULL) bus_dmamem_free(drvr_info_tag, drvr_info, drvr_info_map); if (drvr_info_tag != NULL) bus_dma_tag_destroy(drvr_info_tag); return retval; } static void mpi3mr_display_ioc_info(struct mpi3mr_softc *sc) { int i = 0; char personality[16]; switch (sc->facts.personality) { case MPI3_IOCFACTS_FLAGS_PERSONALITY_EHBA: strcpy(personality, "Enhanced HBA"); break; case MPI3_IOCFACTS_FLAGS_PERSONALITY_RAID_DDR: strcpy(personality, "RAID"); break; default: strcpy(personality, "Unknown"); break; } mpi3mr_dprint(sc, MPI3MR_INFO, "Current Personality: %s\n", personality); mpi3mr_dprint(sc, MPI3MR_INFO, "%s\n", sc->fw_version); mpi3mr_dprint(sc, MPI3MR_INFO, "Protocol=("); if (sc->facts.protocol_flags & MPI3_IOCFACTS_PROTOCOL_SCSI_INITIATOR) { printf("Initiator"); i++; } if (sc->facts.protocol_flags & MPI3_IOCFACTS_PROTOCOL_SCSI_TARGET) { printf("%sTarget", i ? "," : ""); i++; } if (sc->facts.protocol_flags & MPI3_IOCFACTS_PROTOCOL_NVME) { printf("%sNVMe attachment", i ? "," : ""); i++; } i = 0; printf("), "); printf("Capabilities=("); if (sc->facts.ioc_capabilities & - MPI3_IOCFACTS_CAPABILITY_RAID_CAPABLE) { + MPI3_IOCFACTS_CAPABILITY_RAID_SUPPORTED) { printf("RAID"); i++; } printf(")\n"); } /** * mpi3mr_unmask_events - Unmask events in event mask bitmap * @sc: Adapter instance reference * @event: MPI event ID * * Un mask the specific event by resetting the event_mask * bitmap. * * Return: None. */ static void mpi3mr_unmask_events(struct mpi3mr_softc *sc, U16 event) { U32 desired_event; if (event >= 128) return; desired_event = (1 << (event % 32)); if (event < 32) sc->event_masks[0] &= ~desired_event; else if (event < 64) sc->event_masks[1] &= ~desired_event; else if (event < 96) sc->event_masks[2] &= ~desired_event; else if (event < 128) sc->event_masks[3] &= ~desired_event; } static void mpi3mr_set_events_mask(struct mpi3mr_softc *sc) { int i; for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) sc->event_masks[i] = -1; mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_ADDED); mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_INFO_CHANGED); mpi3mr_unmask_events(sc, MPI3_EVENT_DEVICE_STATUS_CHANGE); mpi3mr_unmask_events(sc, MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE); mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST); mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_DISCOVERY); mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR); mpi3mr_unmask_events(sc, MPI3_EVENT_SAS_BROADCAST_PRIMITIVE); mpi3mr_unmask_events(sc, MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST); mpi3mr_unmask_events(sc, MPI3_EVENT_PCIE_ENUMERATION); mpi3mr_unmask_events(sc, MPI3_EVENT_PREPARE_FOR_RESET); mpi3mr_unmask_events(sc, MPI3_EVENT_CABLE_MGMT); mpi3mr_unmask_events(sc, MPI3_EVENT_ENERGY_PACK_CHANGE); } /** * mpi3mr_issue_event_notification - Send event notification * @sc: Adapter instance reference * * Issue event notification MPI request through admin queue and * wait for the completion of it or time out. * * Return: 0 on success, non-zero on failures. */ int mpi3mr_issue_event_notification(struct mpi3mr_softc *sc) { Mpi3EventNotificationRequest_t evtnotify_req; int retval = 0; U8 i; memset(&evtnotify_req, 0, sizeof(evtnotify_req)); mtx_lock(&sc->init_cmds.completion.lock); if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { retval = -1; printf(IOCNAME "Issue EvtNotify: Init command is in use\n", sc->name); mtx_unlock(&sc->init_cmds.completion.lock); goto out; } sc->init_cmds.state = MPI3MR_CMD_PENDING; sc->init_cmds.is_waiting = 1; sc->init_cmds.callback = NULL; evtnotify_req.HostTag = (MPI3MR_HOSTTAG_INITCMDS); evtnotify_req.Function = MPI3_FUNCTION_EVENT_NOTIFICATION; for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) evtnotify_req.EventMasks[i] = (sc->event_masks[i]); init_completion(&sc->init_cmds.completion); retval = mpi3mr_submit_admin_cmd(sc, &evtnotify_req, sizeof(evtnotify_req)); if (retval) { printf(IOCNAME "Issue EvtNotify: Admin Post failed\n", sc->name); goto out_unlock; } poll_for_command_completion(sc, &sc->init_cmds, (MPI3MR_INTADMCMD_TIMEOUT)); if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { printf(IOCNAME "Issue EvtNotify: command timed out\n", sc->name); mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_EVTNOTIFY_TIMEOUT); retval = -1; goto out_unlock; } if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) != MPI3_IOCSTATUS_SUCCESS ) { printf(IOCNAME "Issue EvtNotify: Failed IOCStatus(0x%04x) " " Loginfo(0x%08x) \n" , sc->name, (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), sc->init_cmds.ioc_loginfo); retval = -1; goto out_unlock; } out_unlock: sc->init_cmds.state = MPI3MR_CMD_NOTUSED; mtx_unlock(&sc->init_cmds.completion.lock); out: return retval; } int mpi3mr_register_events(struct mpi3mr_softc *sc) { int error; mpi3mr_set_events_mask(sc); error = mpi3mr_issue_event_notification(sc); if (error) { printf(IOCNAME "Failed to issue event notification %d\n", sc->name, error); } return error; } /** * mpi3mr_process_event_ack - Process event acknowledgment * @sc: Adapter instance reference * @event: MPI3 event ID * @event_ctx: Event context * * Send event acknowledgement through admin queue and wait for * it to complete. * * Return: 0 on success, non-zero on failures. */ int mpi3mr_process_event_ack(struct mpi3mr_softc *sc, U8 event, U32 event_ctx) { Mpi3EventAckRequest_t evtack_req; int retval = 0; memset(&evtack_req, 0, sizeof(evtack_req)); mtx_lock(&sc->init_cmds.completion.lock); if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { retval = -1; printf(IOCNAME "Issue EvtAck: Init command is in use\n", sc->name); mtx_unlock(&sc->init_cmds.completion.lock); goto out; } sc->init_cmds.state = MPI3MR_CMD_PENDING; sc->init_cmds.is_waiting = 1; sc->init_cmds.callback = NULL; evtack_req.HostTag = htole16(MPI3MR_HOSTTAG_INITCMDS); evtack_req.Function = MPI3_FUNCTION_EVENT_ACK; evtack_req.Event = event; evtack_req.EventContext = htole32(event_ctx); init_completion(&sc->init_cmds.completion); retval = mpi3mr_submit_admin_cmd(sc, &evtack_req, sizeof(evtack_req)); if (retval) { printf(IOCNAME "Issue EvtAck: Admin Post failed\n", sc->name); goto out_unlock; } wait_for_completion_timeout(&sc->init_cmds.completion, (MPI3MR_INTADMCMD_TIMEOUT)); if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { printf(IOCNAME "Issue EvtAck: command timed out\n", sc->name); retval = -1; goto out_unlock; } if ((sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK) != MPI3_IOCSTATUS_SUCCESS ) { printf(IOCNAME "Issue EvtAck: Failed IOCStatus(0x%04x) " " Loginfo(0x%08x) \n" , sc->name, (sc->init_cmds.ioc_status & MPI3_IOCSTATUS_STATUS_MASK), sc->init_cmds.ioc_loginfo); retval = -1; goto out_unlock; } out_unlock: sc->init_cmds.state = MPI3MR_CMD_NOTUSED; mtx_unlock(&sc->init_cmds.completion.lock); out: return retval; } static int mpi3mr_alloc_chain_bufs(struct mpi3mr_softc *sc) { int retval = 0; U32 sz, i; U16 num_chains; num_chains = sc->max_host_ios; sc->chain_buf_count = num_chains; sz = sizeof(struct mpi3mr_chain) * num_chains; sc->chain_sgl_list = malloc(sz, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->chain_sgl_list) { printf(IOCNAME "Cannot allocate memory for chain SGL list\n", sc->name); retval = -1; goto out_failed; } sz = MPI3MR_CHAINSGE_SIZE; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4096, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sz, /* maxsize */ 1, /* nsegments */ sz, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->chain_sgl_list_tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate Chain buffer DMA tag\n"); return (ENOMEM); } for (i = 0; i < num_chains; i++) { if (bus_dmamem_alloc(sc->chain_sgl_list_tag, (void **)&sc->chain_sgl_list[i].buf, BUS_DMA_NOWAIT, &sc->chain_sgl_list[i].buf_dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Func: %s line: %d DMA mem alloc failed\n", __func__, __LINE__); return (ENOMEM); } bzero(sc->chain_sgl_list[i].buf, sz); bus_dmamap_load(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap, sc->chain_sgl_list[i].buf, sz, mpi3mr_memaddr_cb, &sc->chain_sgl_list[i].buf_phys, BUS_DMA_NOWAIT); mpi3mr_dprint(sc, MPI3MR_XINFO, "Func: %s line: %d phys addr= %#016jx size= %d\n", __func__, __LINE__, (uintmax_t)sc->chain_sgl_list[i].buf_phys, sz); } sc->chain_bitmap_sz = MPI3MR_DIV_ROUND_UP(num_chains, 8); sc->chain_bitmap = malloc(sc->chain_bitmap_sz, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->chain_bitmap) { mpi3mr_dprint(sc, MPI3MR_INFO, "Cannot alloc memory for chain bitmap\n"); retval = -1; goto out_failed; } return retval; out_failed: for (i = 0; i < num_chains; i++) { if (sc->chain_sgl_list[i].buf_phys != 0) bus_dmamap_unload(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap); if (sc->chain_sgl_list[i].buf != NULL) bus_dmamem_free(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf, sc->chain_sgl_list[i].buf_dmamap); } if (sc->chain_sgl_list_tag != NULL) bus_dma_tag_destroy(sc->chain_sgl_list_tag); return retval; } static int mpi3mr_pel_alloc(struct mpi3mr_softc *sc) { int retval = 0; if (!sc->pel_cmds.reply) { sc->pel_cmds.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->pel_cmds.reply) { printf(IOCNAME "Cannot allocate memory for pel_cmds.reply\n", sc->name); goto out_failed; } } if (!sc->pel_abort_cmd.reply) { sc->pel_abort_cmd.reply = malloc(sc->reply_sz, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->pel_abort_cmd.reply) { printf(IOCNAME "Cannot allocate memory for pel_abort_cmd.reply\n", sc->name); goto out_failed; } } if (!sc->pel_seq_number) { sc->pel_seq_number_sz = sizeof(Mpi3PELSeq_t); if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* alignment, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ sc->pel_seq_number_sz, /* maxsize */ 1, /* nsegments */ sc->pel_seq_number_sz, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->pel_seq_num_dmatag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot create PEL seq number dma memory tag\n"); retval = -ENOMEM; goto out_failed; } if (bus_dmamem_alloc(sc->pel_seq_num_dmatag, (void **)&sc->pel_seq_number, BUS_DMA_NOWAIT, &sc->pel_seq_num_dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate PEL seq number kernel buffer dma memory\n"); retval = -ENOMEM; goto out_failed; } bzero(sc->pel_seq_number, sc->pel_seq_number_sz); bus_dmamap_load(sc->pel_seq_num_dmatag, sc->pel_seq_num_dmamap, sc->pel_seq_number, sc->pel_seq_number_sz, mpi3mr_memaddr_cb, &sc->pel_seq_number_dma, BUS_DMA_NOWAIT); if (!sc->pel_seq_number) { printf(IOCNAME "%s:%d Cannot load PEL seq number dma memory for size: %d\n", sc->name, __func__, __LINE__, sc->pel_seq_number_sz); retval = -ENOMEM; goto out_failed; } } out_failed: return retval; } /** * mpi3mr_validate_fw_update - validate IOCFacts post adapter reset * @sc: Adapter instance reference * * Return zero if the new IOCFacts is compatible with previous values * else return appropriate error */ static int mpi3mr_validate_fw_update(struct mpi3mr_softc *sc) { U16 dev_handle_bitmap_sz; U8 *removepend_bitmap; if (sc->facts.reply_sz > sc->reply_sz) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot increase reply size from %d to %d\n", sc->reply_sz, sc->reply_sz); return -EPERM; } if (sc->num_io_throttle_group != sc->facts.max_io_throttle_group) { mpi3mr_dprint(sc, MPI3MR_ERROR, "max io throttle group doesn't match old(%d), new(%d)\n", sc->num_io_throttle_group, sc->facts.max_io_throttle_group); return -EPERM; } if (sc->facts.max_op_reply_q < sc->num_queues) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot reduce number of operational reply queues from %d to %d\n", sc->num_queues, sc->facts.max_op_reply_q); return -EPERM; } if (sc->facts.max_op_req_q < sc->num_queues) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot reduce number of operational request queues from %d to %d\n", sc->num_queues, sc->facts.max_op_req_q); return -EPERM; } dev_handle_bitmap_sz = MPI3MR_DIV_ROUND_UP(sc->facts.max_devhandle, 8); if (dev_handle_bitmap_sz > sc->dev_handle_bitmap_sz) { removepend_bitmap = realloc(sc->removepend_bitmap, dev_handle_bitmap_sz, M_MPI3MR, M_NOWAIT); if (!removepend_bitmap) { mpi3mr_dprint(sc, MPI3MR_ERROR, "failed to increase removepend_bitmap sz from: %d to %d\n", sc->dev_handle_bitmap_sz, dev_handle_bitmap_sz); return -ENOMEM; } memset(removepend_bitmap + sc->dev_handle_bitmap_sz, 0, dev_handle_bitmap_sz - sc->dev_handle_bitmap_sz); sc->removepend_bitmap = removepend_bitmap; mpi3mr_dprint(sc, MPI3MR_INFO, "increased dev_handle_bitmap_sz from %d to %d\n", sc->dev_handle_bitmap_sz, dev_handle_bitmap_sz); sc->dev_handle_bitmap_sz = dev_handle_bitmap_sz; } return 0; } /* * mpi3mr_initialize_ioc - Controller initialization * @dev: pointer to device struct * * This function allocates the controller wide resources and brings * the controller to operational state * * Return: 0 on success and proper error codes on failure */ int mpi3mr_initialize_ioc(struct mpi3mr_softc *sc, U8 init_type) { int retval = 0; enum mpi3mr_iocstate ioc_state; U64 ioc_info; U32 ioc_status, ioc_control, i, timeout; Mpi3IOCFactsData_t facts_data; char str[32]; U32 size; sc->cpu_count = mp_ncpus; ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); ioc_control = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); ioc_info = mpi3mr_regread64(sc, MPI3_SYSIF_IOC_INFO_LOW_OFFSET); mpi3mr_dprint(sc, MPI3MR_INFO, "SOD ioc_status: 0x%x ioc_control: 0x%x " "ioc_info: 0x%lx\n", ioc_status, ioc_control, ioc_info); /*The timeout value is in 2sec unit, changing it to seconds*/ sc->ready_timeout = ((ioc_info & MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_MASK) >> MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_SHIFT) * 2; ioc_state = mpi3mr_get_iocstate(sc); mpi3mr_dprint(sc, MPI3MR_INFO, "IOC state: %s IOC ready timeout: %d\n", mpi3mr_iocstate_name(ioc_state), sc->ready_timeout); if (ioc_state == MRIOC_STATE_BECOMING_READY || ioc_state == MRIOC_STATE_RESET_REQUESTED) { timeout = sc->ready_timeout * 10; do { DELAY(1000 * 100); } while (--timeout); ioc_state = mpi3mr_get_iocstate(sc); mpi3mr_dprint(sc, MPI3MR_INFO, "IOC in %s state after waiting for reset time\n", mpi3mr_iocstate_name(ioc_state)); } if (ioc_state == MRIOC_STATE_READY) { retval = mpi3mr_mur_ioc(sc, MPI3MR_RESET_FROM_BRINGUP); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to MU reset IOC, error 0x%x\n", retval); } ioc_state = mpi3mr_get_iocstate(sc); } if (ioc_state != MRIOC_STATE_RESET) { mpi3mr_print_fault_info(sc); mpi3mr_dprint(sc, MPI3MR_ERROR, "issuing soft reset to bring to reset state\n"); retval = mpi3mr_issue_reset(sc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, MPI3MR_RESET_FROM_BRINGUP); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :Failed to soft reset IOC, error 0x%d\n", __func__, retval); goto out_failed; } } ioc_state = mpi3mr_get_iocstate(sc); if (ioc_state != MRIOC_STATE_RESET) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot bring IOC to reset state\n"); goto out_failed; } retval = mpi3mr_setup_admin_qpair(sc); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to setup Admin queues, error 0x%x\n", retval); goto out_failed; } retval = mpi3mr_bring_ioc_ready(sc); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to bring IOC ready, error 0x%x\n", retval); goto out_failed; } if (init_type == MPI3MR_INIT_TYPE_INIT) { retval = mpi3mr_alloc_interrupts(sc, 1); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate interrupts, error 0x%x\n", retval); goto out_failed; } retval = mpi3mr_setup_irqs(sc); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to setup ISR, error 0x%x\n", retval); goto out_failed; } } mpi3mr_enable_interrupts(sc); if (init_type == MPI3MR_INIT_TYPE_INIT) { mtx_init(&sc->mpi3mr_mtx, "SIM lock", NULL, MTX_DEF); mtx_init(&sc->io_lock, "IO lock", NULL, MTX_DEF); mtx_init(&sc->admin_req_lock, "Admin Request Queue lock", NULL, MTX_SPIN); mtx_init(&sc->reply_free_q_lock, "Reply free Queue lock", NULL, MTX_SPIN); mtx_init(&sc->sense_buf_q_lock, "Sense buffer Queue lock", NULL, MTX_SPIN); mtx_init(&sc->chain_buf_lock, "Chain buffer lock", NULL, MTX_SPIN); mtx_init(&sc->cmd_pool_lock, "Command pool lock", NULL, MTX_DEF); mtx_init(&sc->fwevt_lock, "Firmware Event lock", NULL, MTX_DEF); mtx_init(&sc->target_lock, "Target lock", NULL, MTX_SPIN); mtx_init(&sc->reset_mutex, "Reset lock", NULL, MTX_DEF); mtx_init(&sc->init_cmds.completion.lock, "Init commands lock", NULL, MTX_DEF); sc->init_cmds.reply = NULL; sc->init_cmds.state = MPI3MR_CMD_NOTUSED; sc->init_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE; sc->init_cmds.host_tag = MPI3MR_HOSTTAG_INITCMDS; mtx_init(&sc->ioctl_cmds.completion.lock, "IOCTL commands lock", NULL, MTX_DEF); sc->ioctl_cmds.reply = NULL; sc->ioctl_cmds.state = MPI3MR_CMD_NOTUSED; sc->ioctl_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE; sc->ioctl_cmds.host_tag = MPI3MR_HOSTTAG_IOCTLCMDS; mtx_init(&sc->pel_abort_cmd.completion.lock, "PEL Abort command lock", NULL, MTX_DEF); sc->pel_abort_cmd.reply = NULL; sc->pel_abort_cmd.state = MPI3MR_CMD_NOTUSED; sc->pel_abort_cmd.dev_handle = MPI3MR_INVALID_DEV_HANDLE; sc->pel_abort_cmd.host_tag = MPI3MR_HOSTTAG_PELABORT; mtx_init(&sc->host_tm_cmds.completion.lock, "TM commands lock", NULL, MTX_DEF); sc->host_tm_cmds.reply = NULL; sc->host_tm_cmds.state = MPI3MR_CMD_NOTUSED; sc->host_tm_cmds.dev_handle = MPI3MR_INVALID_DEV_HANDLE; sc->host_tm_cmds.host_tag = MPI3MR_HOSTTAG_TMS; TAILQ_INIT(&sc->cmd_list_head); TAILQ_INIT(&sc->event_list); TAILQ_INIT(&sc->delayed_rmhs_list); TAILQ_INIT(&sc->delayed_evtack_cmds_list); for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { snprintf(str, 32, "Dev REMHS commands lock[%d]", i); mtx_init(&sc->dev_rmhs_cmds[i].completion.lock, str, NULL, MTX_DEF); sc->dev_rmhs_cmds[i].reply = NULL; sc->dev_rmhs_cmds[i].state = MPI3MR_CMD_NOTUSED; sc->dev_rmhs_cmds[i].dev_handle = MPI3MR_INVALID_DEV_HANDLE; sc->dev_rmhs_cmds[i].host_tag = MPI3MR_HOSTTAG_DEVRMCMD_MIN + i; } } retval = mpi3mr_issue_iocfacts(sc, &facts_data); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to Issue IOC Facts, retval: 0x%x\n", retval); goto out_failed; } retval = mpi3mr_process_factsdata(sc, &facts_data); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "IOC Facts data processing failedi, retval: 0x%x\n", retval); goto out_failed; } sc->num_io_throttle_group = sc->facts.max_io_throttle_group; mpi3mr_atomic_set(&sc->pend_large_data_sz, 0); if (init_type == MPI3MR_INIT_TYPE_RESET) { retval = mpi3mr_validate_fw_update(sc); if (retval) goto out_failed; } else { sc->reply_sz = sc->facts.reply_sz; } mpi3mr_display_ioc_info(sc); retval = mpi3mr_reply_alloc(sc); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocated reply and sense buffers, retval: 0x%x\n", retval); goto out_failed; } if (init_type == MPI3MR_INIT_TYPE_INIT) { retval = mpi3mr_alloc_chain_bufs(sc); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocated chain buffers, retval: 0x%x\n", retval); goto out_failed; } } retval = mpi3mr_issue_iocinit(sc); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to Issue IOC Init, retval: 0x%x\n", retval); goto out_failed; } mpi3mr_print_fw_pkg_ver(sc); sc->reply_free_q_host_index = sc->num_reply_bufs; mpi3mr_regwrite(sc, MPI3_SYSIF_REPLY_FREE_HOST_INDEX_OFFSET, sc->reply_free_q_host_index); sc->sense_buf_q_host_index = sc->num_sense_bufs; mpi3mr_regwrite(sc, MPI3_SYSIF_SENSE_BUF_FREE_HOST_INDEX_OFFSET, sc->sense_buf_q_host_index); if (init_type == MPI3MR_INIT_TYPE_INIT) { retval = mpi3mr_alloc_interrupts(sc, 0); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate interrupts, retval: 0x%x\n", retval); goto out_failed; } retval = mpi3mr_setup_irqs(sc); if (retval) { printf(IOCNAME "Failed to setup ISR, error: 0x%x\n", sc->name, retval); goto out_failed; } mpi3mr_enable_interrupts(sc); } else mpi3mr_enable_interrupts(sc); retval = mpi3mr_create_op_queues(sc); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to create operational queues, error: %d\n", retval); goto out_failed; } if (!sc->throttle_groups && sc->num_io_throttle_group) { mpi3mr_dprint(sc, MPI3MR_ERROR, "allocating memory for throttle groups\n"); size = sizeof(struct mpi3mr_throttle_group_info); sc->throttle_groups = (struct mpi3mr_throttle_group_info *) malloc(sc->num_io_throttle_group * size, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->throttle_groups) goto out_failed; } if (init_type == MPI3MR_INIT_TYPE_RESET) { mpi3mr_dprint(sc, MPI3MR_INFO, "Re-register events\n"); retval = mpi3mr_register_events(sc); if (retval) { mpi3mr_dprint(sc, MPI3MR_INFO, "Failed to re-register events, retval: 0x%x\n", retval); goto out_failed; } mpi3mr_dprint(sc, MPI3MR_INFO, "Issuing Port Enable\n"); retval = mpi3mr_issue_port_enable(sc, 0); if (retval) { mpi3mr_dprint(sc, MPI3MR_INFO, "Failed to issue port enable, retval: 0x%x\n", retval); goto out_failed; } } retval = mpi3mr_pel_alloc(sc); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate memory for PEL, retval: 0x%x\n", retval); goto out_failed; } return retval; out_failed: retval = -1; return retval; } static void mpi3mr_port_enable_complete(struct mpi3mr_softc *sc, struct mpi3mr_drvr_cmd *drvrcmd) { drvrcmd->state = MPI3MR_CMD_NOTUSED; drvrcmd->callback = NULL; printf(IOCNAME "Completing Port Enable Request\n", sc->name); sc->mpi3mr_flags |= MPI3MR_FLAGS_PORT_ENABLE_DONE; mpi3mr_startup_decrement(sc->cam_sc); } int mpi3mr_issue_port_enable(struct mpi3mr_softc *sc, U8 async) { Mpi3PortEnableRequest_t pe_req; int retval = 0; memset(&pe_req, 0, sizeof(pe_req)); mtx_lock(&sc->init_cmds.completion.lock); if (sc->init_cmds.state & MPI3MR_CMD_PENDING) { retval = -1; printf(IOCNAME "Issue PortEnable: Init command is in use\n", sc->name); mtx_unlock(&sc->init_cmds.completion.lock); goto out; } sc->init_cmds.state = MPI3MR_CMD_PENDING; if (async) { sc->init_cmds.is_waiting = 0; sc->init_cmds.callback = mpi3mr_port_enable_complete; } else { sc->init_cmds.is_waiting = 1; sc->init_cmds.callback = NULL; init_completion(&sc->init_cmds.completion); } pe_req.HostTag = MPI3MR_HOSTTAG_INITCMDS; pe_req.Function = MPI3_FUNCTION_PORT_ENABLE; printf(IOCNAME "Sending Port Enable Request\n", sc->name); retval = mpi3mr_submit_admin_cmd(sc, &pe_req, sizeof(pe_req)); if (retval) { printf(IOCNAME "Issue PortEnable: Admin Post failed\n", sc->name); goto out_unlock; } if (!async) { wait_for_completion_timeout(&sc->init_cmds.completion, MPI3MR_PORTENABLE_TIMEOUT); if (!(sc->init_cmds.state & MPI3MR_CMD_COMPLETE)) { printf(IOCNAME "Issue PortEnable: command timed out\n", sc->name); retval = -1; mpi3mr_check_rh_fault_ioc(sc, MPI3MR_RESET_FROM_PE_TIMEOUT); goto out_unlock; } mpi3mr_port_enable_complete(sc, &sc->init_cmds); } out_unlock: mtx_unlock(&sc->init_cmds.completion.lock); out: return retval; } void mpi3mr_watchdog_thread(void *arg) { struct mpi3mr_softc *sc; enum mpi3mr_iocstate ioc_state; U32 fault, host_diagnostic, ioc_status; sc = (struct mpi3mr_softc *)arg; mpi3mr_dprint(sc, MPI3MR_XINFO, "%s\n", __func__); sc->watchdog_thread_active = 1; mtx_lock(&sc->reset_mutex); for (;;) { if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN || (sc->unrecoverable == 1)) { mpi3mr_dprint(sc, MPI3MR_INFO, "Exit due to %s from %s\n", sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN ? "Shutdown" : "Hardware critical error", __func__); break; } mtx_unlock(&sc->reset_mutex); if ((sc->prepare_for_reset) && ((sc->prepare_for_reset_timeout_counter++) >= MPI3MR_PREPARE_FOR_RESET_TIMEOUT)) { mpi3mr_soft_reset_handler(sc, MPI3MR_RESET_FROM_CIACTVRST_TIMER, 1); goto sleep; } ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) { mpi3mr_soft_reset_handler(sc, MPI3MR_RESET_FROM_FIRMWARE, 0); goto sleep; } ioc_state = mpi3mr_get_iocstate(sc); if (ioc_state == MRIOC_STATE_FAULT) { fault = mpi3mr_regread(sc, MPI3_SYSIF_FAULT_OFFSET) & MPI3_SYSIF_FAULT_CODE_MASK; host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET); if (host_diagnostic & MPI3_SYSIF_HOST_DIAG_SAVE_IN_PROGRESS) { if (!sc->diagsave_timeout) { mpi3mr_print_fault_info(sc); mpi3mr_dprint(sc, MPI3MR_INFO, "diag save in progress\n"); } if ((sc->diagsave_timeout++) <= MPI3_SYSIF_DIAG_SAVE_TIMEOUT) goto sleep; } mpi3mr_print_fault_info(sc); sc->diagsave_timeout = 0; if ((fault == MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED) || (fault == MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED)) { mpi3mr_dprint(sc, MPI3MR_INFO, "Controller requires system power cycle or complete reset is needed," "fault code: 0x%x. marking controller as unrecoverable\n", fault); sc->unrecoverable = 1; break; } if ((fault == MPI3_SYSIF_FAULT_CODE_DIAG_FAULT_RESET) || (fault == MPI3_SYSIF_FAULT_CODE_SOFT_RESET_IN_PROGRESS) || (sc->reset_in_progress)) break; if (fault == MPI3_SYSIF_FAULT_CODE_CI_ACTIVATION_RESET) mpi3mr_soft_reset_handler(sc, MPI3MR_RESET_FROM_CIACTIV_FAULT, 0); else mpi3mr_soft_reset_handler(sc, MPI3MR_RESET_FROM_FAULT_WATCH, 0); } if (sc->reset.type == MPI3MR_TRIGGER_SOFT_RESET) { mpi3mr_print_fault_info(sc); mpi3mr_soft_reset_handler(sc, sc->reset.reason, 1); } sleep: mtx_lock(&sc->reset_mutex); /* * Sleep for 1 second if we're not exiting, then loop to top * to poll exit status and hardware health. */ if ((sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) == 0 && !sc->unrecoverable) { msleep(&sc->watchdog_chan, &sc->reset_mutex, PRIBIO, "mpi3mr_watchdog", 1 * hz); } } mtx_unlock(&sc->reset_mutex); sc->watchdog_thread_active = 0; mpi3mr_kproc_exit(0); } static void mpi3mr_display_event_data(struct mpi3mr_softc *sc, Mpi3EventNotificationReply_t *event_rep) { char *desc = NULL; U16 event; event = event_rep->Event; switch (event) { case MPI3_EVENT_LOG_DATA: desc = "Log Data"; break; case MPI3_EVENT_CHANGE: desc = "Event Change"; break; case MPI3_EVENT_GPIO_INTERRUPT: desc = "GPIO Interrupt"; break; case MPI3_EVENT_CABLE_MGMT: desc = "Cable Management"; break; case MPI3_EVENT_ENERGY_PACK_CHANGE: desc = "Energy Pack Change"; break; case MPI3_EVENT_DEVICE_ADDED: { Mpi3DevicePage0_t *event_data = (Mpi3DevicePage0_t *)event_rep->EventData; mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Added: Dev=0x%04x Form=0x%x Perst id: 0x%x\n", event_data->DevHandle, event_data->DeviceForm, event_data->PersistentID); return; } case MPI3_EVENT_DEVICE_INFO_CHANGED: { Mpi3DevicePage0_t *event_data = (Mpi3DevicePage0_t *)event_rep->EventData; mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Info Changed: Dev=0x%04x Form=0x%x\n", event_data->DevHandle, event_data->DeviceForm); return; } case MPI3_EVENT_DEVICE_STATUS_CHANGE: { Mpi3EventDataDeviceStatusChange_t *event_data = (Mpi3EventDataDeviceStatusChange_t *)event_rep->EventData; mpi3mr_dprint(sc, MPI3MR_EVENT, "Device Status Change: Dev=0x%04x RC=0x%x\n", event_data->DevHandle, event_data->ReasonCode); return; } case MPI3_EVENT_SAS_DISCOVERY: { Mpi3EventDataSasDiscovery_t *event_data = (Mpi3EventDataSasDiscovery_t *)event_rep->EventData; mpi3mr_dprint(sc, MPI3MR_EVENT, "SAS Discovery: (%s)", (event_data->ReasonCode == MPI3_EVENT_SAS_DISC_RC_STARTED) ? "start" : "stop"); if (event_data->DiscoveryStatus && (sc->mpi3mr_debug & MPI3MR_EVENT)) { printf("discovery_status(0x%08x)", event_data->DiscoveryStatus); } if (sc->mpi3mr_debug & MPI3MR_EVENT) printf("\n"); return; } case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE: desc = "SAS Broadcast Primitive"; break; case MPI3_EVENT_SAS_NOTIFY_PRIMITIVE: desc = "SAS Notify Primitive"; break; case MPI3_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: desc = "SAS Init Device Status Change"; break; case MPI3_EVENT_SAS_INIT_TABLE_OVERFLOW: desc = "SAS Init Table Overflow"; break; case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST: desc = "SAS Topology Change List"; break; case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: desc = "Enclosure Device Status Change"; break; case MPI3_EVENT_HARD_RESET_RECEIVED: desc = "Hard Reset Received"; break; case MPI3_EVENT_SAS_PHY_COUNTER: desc = "SAS PHY Counter"; break; case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR: desc = "SAS Device Discovery Error"; break; case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: desc = "PCIE Topology Change List"; break; case MPI3_EVENT_PCIE_ENUMERATION: { Mpi3EventDataPcieEnumeration_t *event_data = (Mpi3EventDataPcieEnumeration_t *)event_rep->EventData; mpi3mr_dprint(sc, MPI3MR_EVENT, "PCIE Enumeration: (%s)", (event_data->ReasonCode == MPI3_EVENT_PCIE_ENUM_RC_STARTED) ? "start" : "stop"); if (event_data->EnumerationStatus) mpi3mr_dprint(sc, MPI3MR_EVENT, "enumeration_status(0x%08x)", event_data->EnumerationStatus); if (sc->mpi3mr_debug & MPI3MR_EVENT) printf("\n"); return; } case MPI3_EVENT_PREPARE_FOR_RESET: desc = "Prepare For Reset"; break; } if (!desc) return; mpi3mr_dprint(sc, MPI3MR_EVENT, "%s\n", desc); } struct mpi3mr_target * mpi3mr_find_target_by_per_id(struct mpi3mr_cam_softc *cam_sc, uint16_t per_id) { struct mpi3mr_target *target = NULL; mtx_lock_spin(&cam_sc->sc->target_lock); TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) { if (target->per_id == per_id) break; } mtx_unlock_spin(&cam_sc->sc->target_lock); return target; } struct mpi3mr_target * mpi3mr_find_target_by_dev_handle(struct mpi3mr_cam_softc *cam_sc, uint16_t handle) { struct mpi3mr_target *target = NULL; mtx_lock_spin(&cam_sc->sc->target_lock); TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) { if (target->dev_handle == handle) break; } mtx_unlock_spin(&cam_sc->sc->target_lock); return target; } void mpi3mr_update_device(struct mpi3mr_softc *sc, struct mpi3mr_target *tgtdev, Mpi3DevicePage0_t *dev_pg0, bool is_added) { U16 flags = 0; tgtdev->per_id = (dev_pg0->PersistentID); tgtdev->dev_handle = (dev_pg0->DevHandle); tgtdev->dev_type = dev_pg0->DeviceForm; tgtdev->encl_handle = (dev_pg0->EnclosureHandle); tgtdev->parent_handle = (dev_pg0->ParentDevHandle); tgtdev->slot = (dev_pg0->Slot); tgtdev->qdepth = (dev_pg0->QueueDepth); tgtdev->wwid = (dev_pg0->WWID); flags = (dev_pg0->Flags); tgtdev->is_hidden = (flags & MPI3_DEVICE0_FLAGS_HIDDEN); if (is_added == true) tgtdev->io_throttle_enabled = (flags & MPI3_DEVICE0_FLAGS_IO_THROTTLING_REQUIRED) ? 1 : 0; switch (dev_pg0->AccessStatus) { case MPI3_DEVICE0_ASTATUS_NO_ERRORS: case MPI3_DEVICE0_ASTATUS_PREPARE: case MPI3_DEVICE0_ASTATUS_NEEDS_INITIALIZATION: case MPI3_DEVICE0_ASTATUS_DEVICE_MISSING_DELAY: break; default: tgtdev->is_hidden = 1; break; } switch (tgtdev->dev_type) { case MPI3_DEVICE_DEVFORM_SAS_SATA: { Mpi3Device0SasSataFormat_t *sasinf = &dev_pg0->DeviceSpecific.SasSataFormat; U16 dev_info = (sasinf->DeviceInfo); tgtdev->dev_spec.sassata_inf.dev_info = dev_info; tgtdev->dev_spec.sassata_inf.sas_address = (sasinf->SASAddress); if ((dev_info & MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_MASK) != MPI3_SAS_DEVICE_INFO_DEVICE_TYPE_END_DEVICE) tgtdev->is_hidden = 1; else if (!(dev_info & (MPI3_SAS_DEVICE_INFO_STP_SATA_TARGET | MPI3_SAS_DEVICE_INFO_SSP_TARGET))) tgtdev->is_hidden = 1; break; } case MPI3_DEVICE_DEVFORM_PCIE: { Mpi3Device0PcieFormat_t *pcieinf = &dev_pg0->DeviceSpecific.PcieFormat; U16 dev_info = (pcieinf->DeviceInfo); tgtdev->q_depth = dev_pg0->QueueDepth; tgtdev->dev_spec.pcie_inf.dev_info = dev_info; tgtdev->dev_spec.pcie_inf.capb = (pcieinf->Capabilities); tgtdev->dev_spec.pcie_inf.mdts = MPI3MR_DEFAULT_MDTS; if (dev_pg0->AccessStatus == MPI3_DEVICE0_ASTATUS_NO_ERRORS) { tgtdev->dev_spec.pcie_inf.mdts = (pcieinf->MaximumDataTransferSize); tgtdev->dev_spec.pcie_inf.pgsz = pcieinf->PageSize; tgtdev->dev_spec.pcie_inf.reset_to = pcieinf->ControllerResetTO; tgtdev->dev_spec.pcie_inf.abort_to = pcieinf->NVMeAbortTO; } if (tgtdev->dev_spec.pcie_inf.mdts > (1024 * 1024)) tgtdev->dev_spec.pcie_inf.mdts = (1024 * 1024); if (((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) != MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE) && ((dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) != MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_SCSI_DEVICE)) tgtdev->is_hidden = 1; break; } case MPI3_DEVICE_DEVFORM_VD: { Mpi3Device0VdFormat_t *vdinf = &dev_pg0->DeviceSpecific.VdFormat; struct mpi3mr_throttle_group_info *tg = NULL; tgtdev->dev_spec.vol_inf.state = vdinf->VdState; if (vdinf->VdState == MPI3_DEVICE0_VD_STATE_OFFLINE) tgtdev->is_hidden = 1; tgtdev->dev_spec.vol_inf.tg_id = vdinf->IOThrottleGroup; tgtdev->dev_spec.vol_inf.tg_high = vdinf->IOThrottleGroupHigh * 2048; tgtdev->dev_spec.vol_inf.tg_low = vdinf->IOThrottleGroupLow * 2048; if (vdinf->IOThrottleGroup < sc->num_io_throttle_group) { tg = sc->throttle_groups + vdinf->IOThrottleGroup; tg->id = vdinf->IOThrottleGroup; tg->high = tgtdev->dev_spec.vol_inf.tg_high; tg->low = tgtdev->dev_spec.vol_inf.tg_low; if (is_added == true) tg->fw_qd = tgtdev->q_depth; tg->modified_qd = tgtdev->q_depth; } tgtdev->dev_spec.vol_inf.tg = tg; tgtdev->throttle_group = tg; break; } default: goto out; } out: return; } int mpi3mr_create_device(struct mpi3mr_softc *sc, Mpi3DevicePage0_t *dev_pg0) { int retval = 0; struct mpi3mr_target *target = NULL; U16 per_id = 0; per_id = dev_pg0->PersistentID; mtx_lock_spin(&sc->target_lock); TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) { if (target->per_id == per_id) { target->state = MPI3MR_DEV_CREATED; break; } } mtx_unlock_spin(&sc->target_lock); if (target) { mpi3mr_update_device(sc, target, dev_pg0, true); } else { target = malloc(sizeof(*target), M_MPI3MR, M_NOWAIT | M_ZERO); if (target == NULL) { retval = -1; goto out; } target->exposed_to_os = 0; mpi3mr_update_device(sc, target, dev_pg0, true); mtx_lock_spin(&sc->target_lock); TAILQ_INSERT_TAIL(&sc->cam_sc->tgt_list, target, tgt_next); target->state = MPI3MR_DEV_CREATED; mtx_unlock_spin(&sc->target_lock); } out: return retval; } /** * mpi3mr_dev_rmhs_complete_iou - Device removal IOUC completion * @sc: Adapter instance reference * @drv_cmd: Internal command tracker * * Issues a target reset TM to the firmware from the device * removal TM pend list or retry the removal handshake sequence * based on the IOU control request IOC status. * * Return: Nothing */ static void mpi3mr_dev_rmhs_complete_iou(struct mpi3mr_softc *sc, struct mpi3mr_drvr_cmd *drv_cmd) { U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL; struct mpi3mr_target *tgtdev = NULL; mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :dev_rmhs_iouctrl_complete:handle(0x%04x), ioc_status(0x%04x), loginfo(0x%08x)\n", __func__, drv_cmd->dev_handle, drv_cmd->ioc_status, drv_cmd->ioc_loginfo); if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) { if (drv_cmd->retry_count < MPI3MR_DEVRMHS_RETRYCOUNT) { drv_cmd->retry_count++; mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :dev_rmhs_iouctrl_complete: handle(0x%04x)retrying handshake retry=%d\n", __func__, drv_cmd->dev_handle, drv_cmd->retry_count); mpi3mr_dev_rmhs_send_tm(sc, drv_cmd->dev_handle, drv_cmd, drv_cmd->iou_rc); return; } mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :dev removal handshake failed after all retries: handle(0x%04x)\n", __func__, drv_cmd->dev_handle); } else { mtx_lock_spin(&sc->target_lock); TAILQ_FOREACH(tgtdev, &sc->cam_sc->tgt_list, tgt_next) { if (tgtdev->dev_handle == drv_cmd->dev_handle) tgtdev->state = MPI3MR_DEV_REMOVE_HS_COMPLETED; } mtx_unlock_spin(&sc->target_lock); mpi3mr_dprint(sc, MPI3MR_INFO, "%s :dev removal handshake completed successfully: handle(0x%04x)\n", __func__, drv_cmd->dev_handle); mpi3mr_clear_bit(drv_cmd->dev_handle, sc->removepend_bitmap); } if (!TAILQ_EMPTY(&sc->delayed_rmhs_list)) { delayed_dev_rmhs = TAILQ_FIRST(&sc->delayed_rmhs_list); drv_cmd->dev_handle = delayed_dev_rmhs->handle; drv_cmd->retry_count = 0; drv_cmd->iou_rc = delayed_dev_rmhs->iou_rc; mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :dev_rmhs_iouctrl_complete: processing delayed TM: handle(0x%04x)\n", __func__, drv_cmd->dev_handle); mpi3mr_dev_rmhs_send_tm(sc, drv_cmd->dev_handle, drv_cmd, drv_cmd->iou_rc); TAILQ_REMOVE(&sc->delayed_rmhs_list, delayed_dev_rmhs, list); free(delayed_dev_rmhs, M_MPI3MR); return; } drv_cmd->state = MPI3MR_CMD_NOTUSED; drv_cmd->callback = NULL; drv_cmd->retry_count = 0; drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE; mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap); } /** * mpi3mr_dev_rmhs_complete_tm - Device removal TM completion * @sc: Adapter instance reference * @drv_cmd: Internal command tracker * * Issues a target reset TM to the firmware from the device * removal TM pend list or issue IO Unit control request as * part of device removal or hidden acknowledgment handshake. * * Return: Nothing */ static void mpi3mr_dev_rmhs_complete_tm(struct mpi3mr_softc *sc, struct mpi3mr_drvr_cmd *drv_cmd) { Mpi3IoUnitControlRequest_t iou_ctrl; U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; Mpi3SCSITaskMgmtReply_t *tm_reply = NULL; int retval; if (drv_cmd->state & MPI3MR_CMD_REPLYVALID) tm_reply = (Mpi3SCSITaskMgmtReply_t *)drv_cmd->reply; if (tm_reply) printf(IOCNAME "dev_rmhs_tr_complete:handle(0x%04x), ioc_status(0x%04x), loginfo(0x%08x), term_count(%d)\n", sc->name, drv_cmd->dev_handle, drv_cmd->ioc_status, drv_cmd->ioc_loginfo, le32toh(tm_reply->TerminationCount)); printf(IOCNAME "Issuing IOU CTL: handle(0x%04x) dev_rmhs idx(%d)\n", sc->name, drv_cmd->dev_handle, cmd_idx); memset(&iou_ctrl, 0, sizeof(iou_ctrl)); drv_cmd->state = MPI3MR_CMD_PENDING; drv_cmd->is_waiting = 0; drv_cmd->callback = mpi3mr_dev_rmhs_complete_iou; iou_ctrl.Operation = drv_cmd->iou_rc; iou_ctrl.Param16[0] = htole16(drv_cmd->dev_handle); iou_ctrl.HostTag = htole16(drv_cmd->host_tag); iou_ctrl.Function = MPI3_FUNCTION_IO_UNIT_CONTROL; retval = mpi3mr_submit_admin_cmd(sc, &iou_ctrl, sizeof(iou_ctrl)); if (retval) { printf(IOCNAME "Issue DevRmHsTMIOUCTL: Admin post failed\n", sc->name); goto out_failed; } return; out_failed: drv_cmd->state = MPI3MR_CMD_NOTUSED; drv_cmd->callback = NULL; drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE; drv_cmd->retry_count = 0; mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap); } /** * mpi3mr_dev_rmhs_send_tm - Issue TM for device removal * @sc: Adapter instance reference * @handle: Device handle * @cmdparam: Internal command tracker * @iou_rc: IO Unit reason code * * Issues a target reset TM to the firmware or add it to a pend * list as part of device removal or hidden acknowledgment * handshake. * * Return: Nothing */ static void mpi3mr_dev_rmhs_send_tm(struct mpi3mr_softc *sc, U16 handle, struct mpi3mr_drvr_cmd *cmdparam, U8 iou_rc) { Mpi3SCSITaskMgmtRequest_t tm_req; int retval = 0; U16 cmd_idx = MPI3MR_NUM_DEVRMCMD; U8 retrycount = 5; struct mpi3mr_drvr_cmd *drv_cmd = cmdparam; struct delayed_dev_rmhs_node *delayed_dev_rmhs = NULL; if (drv_cmd) goto issue_cmd; do { cmd_idx = mpi3mr_find_first_zero_bit(sc->devrem_bitmap, MPI3MR_NUM_DEVRMCMD); if (cmd_idx < MPI3MR_NUM_DEVRMCMD) { if (!mpi3mr_test_and_set_bit(cmd_idx, sc->devrem_bitmap)) break; cmd_idx = MPI3MR_NUM_DEVRMCMD; } } while (retrycount--); if (cmd_idx >= MPI3MR_NUM_DEVRMCMD) { delayed_dev_rmhs = malloc(sizeof(*delayed_dev_rmhs),M_MPI3MR, M_ZERO|M_NOWAIT); if (!delayed_dev_rmhs) return; delayed_dev_rmhs->handle = handle; delayed_dev_rmhs->iou_rc = iou_rc; TAILQ_INSERT_TAIL(&(sc->delayed_rmhs_list), delayed_dev_rmhs, list); mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :DevRmHs: tr:handle(0x%04x) is postponed\n", __func__, handle); return; } drv_cmd = &sc->dev_rmhs_cmds[cmd_idx]; issue_cmd: cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Issuing TR TM: for devhandle 0x%04x with dev_rmhs %d\n", __func__, handle, cmd_idx); memset(&tm_req, 0, sizeof(tm_req)); if (drv_cmd->state & MPI3MR_CMD_PENDING) { mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Issue TM: Command is in use\n", __func__); goto out; } drv_cmd->state = MPI3MR_CMD_PENDING; drv_cmd->is_waiting = 0; drv_cmd->callback = mpi3mr_dev_rmhs_complete_tm; drv_cmd->dev_handle = handle; drv_cmd->iou_rc = iou_rc; tm_req.DevHandle = htole16(handle); tm_req.TaskType = MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET; tm_req.HostTag = htole16(drv_cmd->host_tag); tm_req.TaskHostTag = htole16(MPI3MR_HOSTTAG_INVALID); tm_req.Function = MPI3_FUNCTION_SCSI_TASK_MGMT; mpi3mr_set_bit(handle, sc->removepend_bitmap); retval = mpi3mr_submit_admin_cmd(sc, &tm_req, sizeof(tm_req)); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :Issue DevRmHsTM: Admin Post failed\n", __func__); goto out_failed; } out: return; out_failed: drv_cmd->state = MPI3MR_CMD_NOTUSED; drv_cmd->callback = NULL; drv_cmd->dev_handle = MPI3MR_INVALID_DEV_HANDLE; drv_cmd->retry_count = 0; mpi3mr_clear_bit(cmd_idx, sc->devrem_bitmap); } /** * mpi3mr_complete_evt_ack - Event ack request completion * @sc: Adapter instance reference * @drv_cmd: Internal command tracker * * This is the completion handler for non blocking event * acknowledgment sent to the firmware and this will issue any * pending event acknowledgment request. * * Return: Nothing */ static void mpi3mr_complete_evt_ack(struct mpi3mr_softc *sc, struct mpi3mr_drvr_cmd *drv_cmd) { U16 cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN; struct delayed_evtack_node *delayed_evtack = NULL; if (drv_cmd->ioc_status != MPI3_IOCSTATUS_SUCCESS) { mpi3mr_dprint(sc, MPI3MR_EVENT, "%s: Failed IOCStatus(0x%04x) Loginfo(0x%08x)\n", __func__, (drv_cmd->ioc_status & MPI3_IOCSTATUS_STATUS_MASK), drv_cmd->ioc_loginfo); } if (!TAILQ_EMPTY(&sc->delayed_evtack_cmds_list)) { delayed_evtack = TAILQ_FIRST(&sc->delayed_evtack_cmds_list); mpi3mr_dprint(sc, MPI3MR_EVENT, "%s: processing delayed event ack for event %d\n", __func__, delayed_evtack->event); mpi3mr_send_evt_ack(sc, delayed_evtack->event, drv_cmd, delayed_evtack->event_ctx); TAILQ_REMOVE(&sc->delayed_evtack_cmds_list, delayed_evtack, list); free(delayed_evtack, M_MPI3MR); return; } drv_cmd->state = MPI3MR_CMD_NOTUSED; drv_cmd->callback = NULL; mpi3mr_clear_bit(cmd_idx, sc->evtack_cmds_bitmap); } /** * mpi3mr_send_evt_ack - Issue event acknwoledgment request * @sc: Adapter instance reference * @event: MPI3 event id * @cmdparam: Internal command tracker * @event_ctx: Event context * * Issues event acknowledgment request to the firmware if there * is a free command to send the event ack else it to a pend * list so that it will be processed on a completion of a prior * event acknowledgment . * * Return: Nothing */ static void mpi3mr_send_evt_ack(struct mpi3mr_softc *sc, U8 event, struct mpi3mr_drvr_cmd *cmdparam, U32 event_ctx) { Mpi3EventAckRequest_t evtack_req; int retval = 0; U8 retrycount = 5; U16 cmd_idx = MPI3MR_NUM_EVTACKCMD; struct mpi3mr_drvr_cmd *drv_cmd = cmdparam; struct delayed_evtack_node *delayed_evtack = NULL; if (drv_cmd) goto issue_cmd; do { cmd_idx = mpi3mr_find_first_zero_bit(sc->evtack_cmds_bitmap, MPI3MR_NUM_EVTACKCMD); if (cmd_idx < MPI3MR_NUM_EVTACKCMD) { if (!mpi3mr_test_and_set_bit(cmd_idx, sc->evtack_cmds_bitmap)) break; cmd_idx = MPI3MR_NUM_EVTACKCMD; } } while (retrycount--); if (cmd_idx >= MPI3MR_NUM_EVTACKCMD) { delayed_evtack = malloc(sizeof(*delayed_evtack),M_MPI3MR, M_ZERO | M_NOWAIT); if (!delayed_evtack) return; delayed_evtack->event = event; delayed_evtack->event_ctx = event_ctx; TAILQ_INSERT_TAIL(&(sc->delayed_evtack_cmds_list), delayed_evtack, list); mpi3mr_dprint(sc, MPI3MR_EVENT, "%s : Event ack for event:%d is postponed\n", __func__, event); return; } drv_cmd = &sc->evtack_cmds[cmd_idx]; issue_cmd: cmd_idx = drv_cmd->host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN; memset(&evtack_req, 0, sizeof(evtack_req)); if (drv_cmd->state & MPI3MR_CMD_PENDING) { mpi3mr_dprint(sc, MPI3MR_EVENT, "%s: Command is in use\n", __func__); goto out; } drv_cmd->state = MPI3MR_CMD_PENDING; drv_cmd->is_waiting = 0; drv_cmd->callback = mpi3mr_complete_evt_ack; evtack_req.HostTag = htole16(drv_cmd->host_tag); evtack_req.Function = MPI3_FUNCTION_EVENT_ACK; evtack_req.Event = event; evtack_req.EventContext = htole32(event_ctx); retval = mpi3mr_submit_admin_cmd(sc, &evtack_req, sizeof(evtack_req)); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Admin Post failed\n", __func__); goto out_failed; } out: return; out_failed: drv_cmd->state = MPI3MR_CMD_NOTUSED; drv_cmd->callback = NULL; mpi3mr_clear_bit(cmd_idx, sc->evtack_cmds_bitmap); } /* * mpi3mr_pcietopochg_evt_th - PCIETopologyChange evt tophalf * @sc: Adapter instance reference * @event_reply: Event data * * Checks for the reason code and based on that either block I/O * to device, or unblock I/O to the device, or start the device * removal handshake with reason as remove with the firmware for * PCIe devices. * * Return: Nothing */ static void mpi3mr_pcietopochg_evt_th(struct mpi3mr_softc *sc, Mpi3EventNotificationReply_t *event_reply) { Mpi3EventDataPcieTopologyChangeList_t *topo_evt = (Mpi3EventDataPcieTopologyChangeList_t *) event_reply->EventData; int i; U16 handle; U8 reason_code; struct mpi3mr_target *tgtdev = NULL; for (i = 0; i < topo_evt->NumEntries; i++) { handle = le16toh(topo_evt->PortEntry[i].AttachedDevHandle); if (!handle) continue; reason_code = topo_evt->PortEntry[i].PortStatus; tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle); switch (reason_code) { case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING: if (tgtdev) { tgtdev->dev_removed = 1; tgtdev->dev_removedelay = 0; mpi3mr_atomic_set(&tgtdev->block_io, 0); } mpi3mr_dev_rmhs_send_tm(sc, handle, NULL, MPI3_CTRL_OP_REMOVE_DEVICE); break; case MPI3_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING: if (tgtdev) { tgtdev->dev_removedelay = 1; mpi3mr_atomic_inc(&tgtdev->block_io); } break; case MPI3_EVENT_PCIE_TOPO_PS_RESPONDING: if (tgtdev && tgtdev->dev_removedelay) { tgtdev->dev_removedelay = 0; if (mpi3mr_atomic_read(&tgtdev->block_io) > 0) mpi3mr_atomic_dec(&tgtdev->block_io); } break; case MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED: default: break; } } } /** * mpi3mr_sastopochg_evt_th - SASTopologyChange evt tophalf * @sc: Adapter instance reference * @event_reply: Event data * * Checks for the reason code and based on that either block I/O * to device, or unblock I/O to the device, or start the device * removal handshake with reason as remove with the firmware for * SAS/SATA devices. * * Return: Nothing */ static void mpi3mr_sastopochg_evt_th(struct mpi3mr_softc *sc, Mpi3EventNotificationReply_t *event_reply) { Mpi3EventDataSasTopologyChangeList_t *topo_evt = (Mpi3EventDataSasTopologyChangeList_t *)event_reply->EventData; int i; U16 handle; U8 reason_code; struct mpi3mr_target *tgtdev = NULL; for (i = 0; i < topo_evt->NumEntries; i++) { handle = le16toh(topo_evt->PhyEntry[i].AttachedDevHandle); if (!handle) continue; - reason_code = topo_evt->PhyEntry[i].Status & + reason_code = topo_evt->PhyEntry[i].PhyStatus & MPI3_EVENT_SAS_TOPO_PHY_RC_MASK; tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle); switch (reason_code) { case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING: if (tgtdev) { tgtdev->dev_removed = 1; tgtdev->dev_removedelay = 0; mpi3mr_atomic_set(&tgtdev->block_io, 0); } mpi3mr_dev_rmhs_send_tm(sc, handle, NULL, MPI3_CTRL_OP_REMOVE_DEVICE); break; case MPI3_EVENT_SAS_TOPO_PHY_RC_DELAY_NOT_RESPONDING: if (tgtdev) { tgtdev->dev_removedelay = 1; mpi3mr_atomic_inc(&tgtdev->block_io); } break; case MPI3_EVENT_SAS_TOPO_PHY_RC_RESPONDING: if (tgtdev && tgtdev->dev_removedelay) { tgtdev->dev_removedelay = 0; if (mpi3mr_atomic_read(&tgtdev->block_io) > 0) mpi3mr_atomic_dec(&tgtdev->block_io); } case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED: default: break; } } } /** * mpi3mr_devstatuschg_evt_th - DeviceStatusChange evt tophalf * @sc: Adapter instance reference * @event_reply: Event data * * Checks for the reason code and based on that either block I/O * to device, or unblock I/O to the device, or start the device * removal handshake with reason as remove/hide acknowledgment * with the firmware. * * Return: Nothing */ static void mpi3mr_devstatuschg_evt_th(struct mpi3mr_softc *sc, Mpi3EventNotificationReply_t *event_reply) { U16 dev_handle = 0; U8 ublock = 0, block = 0, hide = 0, uhide = 0, delete = 0, remove = 0; struct mpi3mr_target *tgtdev = NULL; Mpi3EventDataDeviceStatusChange_t *evtdata = (Mpi3EventDataDeviceStatusChange_t *) event_reply->EventData; dev_handle = le16toh(evtdata->DevHandle); switch (evtdata->ReasonCode) { case MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_STRT: case MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_STRT: block = 1; break; case MPI3_EVENT_DEV_STAT_RC_HIDDEN: delete = 1; hide = 1; break; case MPI3_EVENT_DEV_STAT_RC_NOT_HIDDEN: uhide = 1; break; case MPI3_EVENT_DEV_STAT_RC_VD_NOT_RESPONDING: delete = 1; remove = 1; break; case MPI3_EVENT_DEV_STAT_RC_INT_DEVICE_RESET_CMP: case MPI3_EVENT_DEV_STAT_RC_INT_IT_NEXUS_RESET_CMP: ublock = 1; break; default: break; } tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, dev_handle); if (!tgtdev) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :target with dev_handle:0x%x not found\n", __func__, dev_handle); return; } if (block) mpi3mr_atomic_inc(&tgtdev->block_io); if (hide) tgtdev->is_hidden = hide; if (uhide) { tgtdev->is_hidden = 0; tgtdev->dev_removed = 0; } if (delete) tgtdev->dev_removed = 1; if (ublock) { if (mpi3mr_atomic_read(&tgtdev->block_io) > 0) mpi3mr_atomic_dec(&tgtdev->block_io); } if (remove) { mpi3mr_dev_rmhs_send_tm(sc, dev_handle, NULL, MPI3_CTRL_OP_REMOVE_DEVICE); } if (hide) mpi3mr_dev_rmhs_send_tm(sc, dev_handle, NULL, MPI3_CTRL_OP_HIDDEN_ACK); } /** * mpi3mr_preparereset_evt_th - Prepareforreset evt tophalf * @sc: Adapter instance reference * @event_reply: Event data * * Blocks and unblocks host level I/O based on the reason code * * Return: Nothing */ static void mpi3mr_preparereset_evt_th(struct mpi3mr_softc *sc, Mpi3EventNotificationReply_t *event_reply) { Mpi3EventDataPrepareForReset_t *evtdata = (Mpi3EventDataPrepareForReset_t *)event_reply->EventData; if (evtdata->ReasonCode == MPI3_EVENT_PREPARE_RESET_RC_START) { mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Recieved PrepForReset Event with RC=START\n", __func__); if (sc->prepare_for_reset) return; sc->prepare_for_reset = 1; sc->prepare_for_reset_timeout_counter = 0; } else if (evtdata->ReasonCode == MPI3_EVENT_PREPARE_RESET_RC_ABORT) { mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Recieved PrepForReset Event with RC=ABORT\n", __func__); sc->prepare_for_reset = 0; sc->prepare_for_reset_timeout_counter = 0; } if ((event_reply->MsgFlags & MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK) == MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED) mpi3mr_send_evt_ack(sc, event_reply->Event, NULL, le32toh(event_reply->EventContext)); } /** * mpi3mr_energypackchg_evt_th - Energypackchange evt tophalf * @sc: Adapter instance reference * @event_reply: Event data * * Identifies the new shutdown timeout value and update. * * Return: Nothing */ static void mpi3mr_energypackchg_evt_th(struct mpi3mr_softc *sc, Mpi3EventNotificationReply_t *event_reply) { Mpi3EventDataEnergyPackChange_t *evtdata = (Mpi3EventDataEnergyPackChange_t *)event_reply->EventData; U16 shutdown_timeout = le16toh(evtdata->ShutdownTimeout); if (shutdown_timeout <= 0) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :Invalid Shutdown Timeout received = %d\n", __func__, shutdown_timeout); return; } mpi3mr_dprint(sc, MPI3MR_EVENT, "%s :Previous Shutdown Timeout Value = %d New Shutdown Timeout Value = %d\n", __func__, sc->facts.shutdown_timeout, shutdown_timeout); sc->facts.shutdown_timeout = shutdown_timeout; } /** * mpi3mr_cablemgmt_evt_th - Cable mgmt evt tophalf * @sc: Adapter instance reference * @event_reply: Event data * * Displays Cable manegemt event details. * * Return: Nothing */ static void mpi3mr_cablemgmt_evt_th(struct mpi3mr_softc *sc, Mpi3EventNotificationReply_t *event_reply) { Mpi3EventDataCableManagement_t *evtdata = (Mpi3EventDataCableManagement_t *)event_reply->EventData; switch (evtdata->Status) { case MPI3_EVENT_CABLE_MGMT_STATUS_INSUFFICIENT_POWER: { mpi3mr_dprint(sc, MPI3MR_INFO, "An active cable with ReceptacleID %d cannot be powered.\n" "Devices connected to this cable are not detected.\n" "This cable requires %d mW of power.\n", evtdata->ReceptacleID, le32toh(evtdata->ActiveCablePowerRequirement)); break; } case MPI3_EVENT_CABLE_MGMT_STATUS_DEGRADED: { mpi3mr_dprint(sc, MPI3MR_INFO, "A cable with ReceptacleID %d is not running at optimal speed\n", evtdata->ReceptacleID); break; } default: break; } } /** * mpi3mr_process_events - Event's toph-half handler * @sc: Adapter instance reference * @event_reply: Event data * * Top half of event processing. * * Return: Nothing */ static void mpi3mr_process_events(struct mpi3mr_softc *sc, uintptr_t data, Mpi3EventNotificationReply_t *event_reply) { U16 evt_type; bool ack_req = 0, process_evt_bh = 0; struct mpi3mr_fw_event_work *fw_event; U16 sz; if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) goto out; if ((event_reply->MsgFlags & MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_MASK) == MPI3_EVENT_NOTIFY_MSGFLAGS_ACK_REQUIRED) ack_req = 1; evt_type = event_reply->Event; switch (evt_type) { case MPI3_EVENT_DEVICE_ADDED: { Mpi3DevicePage0_t *dev_pg0 = (Mpi3DevicePage0_t *) event_reply->EventData; if (mpi3mr_create_device(sc, dev_pg0)) mpi3mr_dprint(sc, MPI3MR_ERROR, "%s :Failed to add device in the device add event\n", __func__); else process_evt_bh = 1; break; } case MPI3_EVENT_DEVICE_STATUS_CHANGE: { process_evt_bh = 1; mpi3mr_devstatuschg_evt_th(sc, event_reply); break; } case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST: { process_evt_bh = 1; mpi3mr_sastopochg_evt_th(sc, event_reply); break; } case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: { process_evt_bh = 1; mpi3mr_pcietopochg_evt_th(sc, event_reply); break; } case MPI3_EVENT_PREPARE_FOR_RESET: { mpi3mr_preparereset_evt_th(sc, event_reply); ack_req = 0; break; } case MPI3_EVENT_DEVICE_INFO_CHANGED: case MPI3_EVENT_LOG_DATA: { process_evt_bh = 1; break; } case MPI3_EVENT_ENERGY_PACK_CHANGE: { mpi3mr_energypackchg_evt_th(sc, event_reply); break; } case MPI3_EVENT_CABLE_MGMT: { mpi3mr_cablemgmt_evt_th(sc, event_reply); break; } case MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE: case MPI3_EVENT_SAS_DISCOVERY: case MPI3_EVENT_SAS_DEVICE_DISCOVERY_ERROR: case MPI3_EVENT_SAS_BROADCAST_PRIMITIVE: case MPI3_EVENT_PCIE_ENUMERATION: break; default: mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Event 0x%02x is not handled by driver\n", __func__, evt_type); break; } if (process_evt_bh || ack_req) { fw_event = malloc(sizeof(struct mpi3mr_fw_event_work), M_MPI3MR, M_ZERO|M_NOWAIT); if (!fw_event) { printf("%s: allocate failed for fw_event\n", __func__); return; } sz = le16toh(event_reply->EventDataLength) * 4; fw_event->event_data = malloc(sz, M_MPI3MR, M_ZERO|M_NOWAIT); if (!fw_event->event_data) { printf("%s: allocate failed for event_data\n", __func__); free(fw_event, M_MPI3MR); return; } bcopy(event_reply->EventData, fw_event->event_data, sz); fw_event->event = event_reply->Event; if ((event_reply->Event == MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST || event_reply->Event == MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST || event_reply->Event == MPI3_EVENT_ENCL_DEVICE_STATUS_CHANGE ) && sc->track_mapping_events) sc->pending_map_events++; /* * Events should be processed after Port enable is completed. */ if ((event_reply->Event == MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST || event_reply->Event == MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST ) && !(sc->mpi3mr_flags & MPI3MR_FLAGS_PORT_ENABLE_DONE)) mpi3mr_startup_increment(sc->cam_sc); fw_event->send_ack = ack_req; fw_event->event_context = le32toh(event_reply->EventContext); fw_event->event_data_size = sz; fw_event->process_event = process_evt_bh; mtx_lock(&sc->fwevt_lock); TAILQ_INSERT_TAIL(&sc->cam_sc->ev_queue, fw_event, ev_link); taskqueue_enqueue(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task); mtx_unlock(&sc->fwevt_lock); } out: return; } static void mpi3mr_handle_events(struct mpi3mr_softc *sc, uintptr_t data, Mpi3DefaultReply_t *def_reply) { Mpi3EventNotificationReply_t *event_reply = (Mpi3EventNotificationReply_t *)def_reply; sc->change_count = event_reply->IOCChangeCount; mpi3mr_display_event_data(sc, event_reply); mpi3mr_process_events(sc, data, event_reply); } static void mpi3mr_process_admin_reply_desc(struct mpi3mr_softc *sc, Mpi3DefaultReplyDescriptor_t *reply_desc, U64 *reply_dma) { U16 reply_desc_type, host_tag = 0, idx; U16 ioc_status = MPI3_IOCSTATUS_SUCCESS; U32 ioc_loginfo = 0; Mpi3StatusReplyDescriptor_t *status_desc; Mpi3AddressReplyDescriptor_t *addr_desc; Mpi3SuccessReplyDescriptor_t *success_desc; Mpi3DefaultReply_t *def_reply = NULL; struct mpi3mr_drvr_cmd *cmdptr = NULL; Mpi3SCSIIOReply_t *scsi_reply; U8 *sense_buf = NULL; *reply_dma = 0; reply_desc_type = reply_desc->ReplyFlags & MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK; switch (reply_desc_type) { case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS: status_desc = (Mpi3StatusReplyDescriptor_t *)reply_desc; host_tag = status_desc->HostTag; ioc_status = status_desc->IOCStatus; - if (ioc_status & - MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) + if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK) ioc_loginfo = status_desc->IOCLogInfo; - ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; + ioc_status &= MPI3_IOCSTATUS_STATUS_MASK; break; case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY: addr_desc = (Mpi3AddressReplyDescriptor_t *)reply_desc; *reply_dma = addr_desc->ReplyFrameAddress; def_reply = mpi3mr_get_reply_virt_addr(sc, *reply_dma); if (def_reply == NULL) goto out; host_tag = def_reply->HostTag; ioc_status = def_reply->IOCStatus; - if (ioc_status & - MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) + if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK) ioc_loginfo = def_reply->IOCLogInfo; - ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; + ioc_status &= MPI3_IOCSTATUS_STATUS_MASK; if (def_reply->Function == MPI3_FUNCTION_SCSI_IO) { scsi_reply = (Mpi3SCSIIOReply_t *)def_reply; sense_buf = mpi3mr_get_sensebuf_virt_addr(sc, scsi_reply->SenseDataBufferAddress); } break; case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS: success_desc = (Mpi3SuccessReplyDescriptor_t *)reply_desc; host_tag = success_desc->HostTag; break; default: break; } switch (host_tag) { case MPI3MR_HOSTTAG_INITCMDS: cmdptr = &sc->init_cmds; break; case MPI3MR_HOSTTAG_IOCTLCMDS: cmdptr = &sc->ioctl_cmds; break; case MPI3MR_HOSTTAG_TMS: cmdptr = &sc->host_tm_cmds; wakeup((void *)&sc->tm_chan); break; case MPI3MR_HOSTTAG_PELABORT: cmdptr = &sc->pel_abort_cmd; break; case MPI3MR_HOSTTAG_PELWAIT: cmdptr = &sc->pel_cmds; break; case MPI3MR_HOSTTAG_INVALID: if (def_reply && def_reply->Function == MPI3_FUNCTION_EVENT_NOTIFICATION) mpi3mr_handle_events(sc, *reply_dma ,def_reply); default: break; } if (host_tag >= MPI3MR_HOSTTAG_DEVRMCMD_MIN && host_tag <= MPI3MR_HOSTTAG_DEVRMCMD_MAX ) { idx = host_tag - MPI3MR_HOSTTAG_DEVRMCMD_MIN; cmdptr = &sc->dev_rmhs_cmds[idx]; } if (host_tag >= MPI3MR_HOSTTAG_EVTACKCMD_MIN && host_tag <= MPI3MR_HOSTTAG_EVTACKCMD_MAX) { idx = host_tag - MPI3MR_HOSTTAG_EVTACKCMD_MIN; cmdptr = &sc->evtack_cmds[idx]; } if (cmdptr) { if (cmdptr->state & MPI3MR_CMD_PENDING) { cmdptr->state |= MPI3MR_CMD_COMPLETE; cmdptr->ioc_loginfo = ioc_loginfo; cmdptr->ioc_status = ioc_status; cmdptr->state &= ~MPI3MR_CMD_PENDING; if (def_reply) { cmdptr->state |= MPI3MR_CMD_REPLYVALID; memcpy((U8 *)cmdptr->reply, (U8 *)def_reply, sc->reply_sz); } if (sense_buf && cmdptr->sensebuf) { cmdptr->is_senseprst = 1; memcpy(cmdptr->sensebuf, sense_buf, MPI3MR_SENSEBUF_SZ); } if (cmdptr->is_waiting) { complete(&cmdptr->completion); cmdptr->is_waiting = 0; } else if (cmdptr->callback) cmdptr->callback(sc, cmdptr); } } out: if (sense_buf != NULL) mpi3mr_repost_sense_buf(sc, scsi_reply->SenseDataBufferAddress); return; } /* * mpi3mr_complete_admin_cmd: ISR routine for admin commands * @sc: Adapter's soft instance * * This function processes admin command completions. */ static int mpi3mr_complete_admin_cmd(struct mpi3mr_softc *sc) { U32 exp_phase = sc->admin_reply_ephase; U32 adm_reply_ci = sc->admin_reply_ci; U32 num_adm_reply = 0; U64 reply_dma = 0; Mpi3DefaultReplyDescriptor_t *reply_desc; U16 threshold_comps = 0; mtx_lock_spin(&sc->admin_reply_lock); if (sc->admin_in_use == false) { sc->admin_in_use = true; mtx_unlock_spin(&sc->admin_reply_lock); } else { mtx_unlock_spin(&sc->admin_reply_lock); return 0; } reply_desc = (Mpi3DefaultReplyDescriptor_t *)sc->admin_reply + adm_reply_ci; if ((reply_desc->ReplyFlags & MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) { mtx_lock_spin(&sc->admin_reply_lock); sc->admin_in_use = false; mtx_unlock_spin(&sc->admin_reply_lock); return 0; } do { sc->admin_req_ci = reply_desc->RequestQueueCI; mpi3mr_process_admin_reply_desc(sc, reply_desc, &reply_dma); if (reply_dma) mpi3mr_repost_reply_buf(sc, reply_dma); num_adm_reply++; if (++adm_reply_ci == sc->num_admin_replies) { adm_reply_ci = 0; exp_phase ^= 1; } reply_desc = (Mpi3DefaultReplyDescriptor_t *)sc->admin_reply + adm_reply_ci; if ((reply_desc->ReplyFlags & MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) break; if (++threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) { mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, adm_reply_ci); threshold_comps = 0; } } while (1); mpi3mr_regwrite(sc, MPI3_SYSIF_ADMIN_REPLY_Q_CI_OFFSET, adm_reply_ci); sc->admin_reply_ci = adm_reply_ci; sc->admin_reply_ephase = exp_phase; mtx_lock_spin(&sc->admin_reply_lock); sc->admin_in_use = false; mtx_unlock_spin(&sc->admin_reply_lock); return num_adm_reply; } static void mpi3mr_cmd_done(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cmd) { mpi3mr_unmap_request(sc, cmd); mtx_lock(&sc->mpi3mr_mtx); if (cmd->callout_owner) { callout_stop(&cmd->callout); cmd->callout_owner = false; } if (sc->unrecoverable) mpi3mr_set_ccbstatus(cmd->ccb, CAM_DEV_NOT_THERE); xpt_done(cmd->ccb); cmd->ccb = NULL; mtx_unlock(&sc->mpi3mr_mtx); mpi3mr_release_command(cmd); } void mpi3mr_process_op_reply_desc(struct mpi3mr_softc *sc, Mpi3DefaultReplyDescriptor_t *reply_desc, U64 *reply_dma) { U16 reply_desc_type, host_tag = 0; U16 ioc_status = MPI3_IOCSTATUS_SUCCESS; U32 ioc_loginfo = 0; Mpi3StatusReplyDescriptor_t *status_desc = NULL; Mpi3AddressReplyDescriptor_t *addr_desc = NULL; Mpi3SuccessReplyDescriptor_t *success_desc = NULL; Mpi3SCSIIOReply_t *scsi_reply = NULL; U8 *sense_buf = NULL; U8 scsi_state = 0, scsi_status = 0, sense_state = 0; U32 xfer_count = 0, sense_count =0, resp_data = 0; struct mpi3mr_cmd *cm = NULL; union ccb *ccb; struct ccb_scsiio *csio; struct mpi3mr_cam_softc *cam_sc; U32 target_id; U8 *scsi_cdb; struct mpi3mr_target *target = NULL; U32 ioc_pend_data_len = 0, tg_pend_data_len = 0, data_len_blks = 0; struct mpi3mr_throttle_group_info *tg = NULL; U8 throttle_enabled_dev = 0; static int ratelimit; *reply_dma = 0; reply_desc_type = reply_desc->ReplyFlags & MPI3_REPLY_DESCRIPT_FLAGS_TYPE_MASK; switch (reply_desc_type) { case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_STATUS: status_desc = (Mpi3StatusReplyDescriptor_t *)reply_desc; host_tag = status_desc->HostTag; ioc_status = status_desc->IOCStatus; - if (ioc_status & - MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) + if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK) ioc_loginfo = status_desc->IOCLogInfo; - ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; + ioc_status &= MPI3_IOCSTATUS_STATUS_MASK; break; case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_ADDRESS_REPLY: addr_desc = (Mpi3AddressReplyDescriptor_t *)reply_desc; *reply_dma = addr_desc->ReplyFrameAddress; scsi_reply = mpi3mr_get_reply_virt_addr(sc, *reply_dma); if (scsi_reply == NULL) { mpi3mr_dprint(sc, MPI3MR_ERROR, "scsi_reply is NULL, " "this shouldn't happen, reply_desc: %p\n", reply_desc); goto out; } host_tag = scsi_reply->HostTag; ioc_status = scsi_reply->IOCStatus; scsi_status = scsi_reply->SCSIStatus; scsi_state = scsi_reply->SCSIState; sense_state = (scsi_state & MPI3_SCSI_STATE_SENSE_MASK); xfer_count = scsi_reply->TransferCount; sense_count = scsi_reply->SenseCount; resp_data = scsi_reply->ResponseData; sense_buf = mpi3mr_get_sensebuf_virt_addr(sc, scsi_reply->SenseDataBufferAddress); - if (ioc_status & - MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_LOGINFOAVAIL) + if (ioc_status & MPI3_IOCSTATUS_STATUS_MASK) ioc_loginfo = scsi_reply->IOCLogInfo; - ioc_status &= MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK; + ioc_status &= MPI3_IOCSTATUS_STATUS_MASK; if (sense_state == MPI3_SCSI_STATE_SENSE_BUFF_Q_EMPTY) mpi3mr_dprint(sc, MPI3MR_ERROR, "Ran out of sense buffers\n"); break; case MPI3_REPLY_DESCRIPT_FLAGS_TYPE_SUCCESS: success_desc = (Mpi3SuccessReplyDescriptor_t *)reply_desc; host_tag = success_desc->HostTag; default: break; } cm = sc->cmd_list[host_tag]; if (cm->state == MPI3MR_CMD_STATE_FREE) goto out; cam_sc = sc->cam_sc; ccb = cm->ccb; csio = &ccb->csio; target_id = csio->ccb_h.target_id; scsi_cdb = scsiio_cdb_ptr(csio); target = mpi3mr_find_target_by_per_id(cam_sc, target_id); if (sc->iot_enable) { data_len_blks = csio->dxfer_len >> 9; if (target) { tg = target->throttle_group; throttle_enabled_dev = target->io_throttle_enabled; } if ((data_len_blks >= sc->io_throttle_data_length) && throttle_enabled_dev) { mpi3mr_atomic_sub(&sc->pend_large_data_sz, data_len_blks); ioc_pend_data_len = mpi3mr_atomic_read( &sc->pend_large_data_sz); if (tg) { mpi3mr_atomic_sub(&tg->pend_large_data_sz, data_len_blks); tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz); if (ratelimit % 1000) { mpi3mr_dprint(sc, MPI3MR_IOT, "large vd_io completion persist_id(%d), handle(0x%04x), data_len(%d)," "ioc_pending(%d), tg_pending(%d), ioc_low(%d), tg_low(%d)\n", target->per_id, target->dev_handle, data_len_blks, ioc_pend_data_len, tg_pend_data_len, sc->io_throttle_low, tg->low); ratelimit++; } if (tg->io_divert && ((ioc_pend_data_len <= sc->io_throttle_low) && (tg_pend_data_len <= tg->low))) { tg->io_divert = 0; mpi3mr_dprint(sc, MPI3MR_IOT, "VD: Coming out of divert perst_id(%d) tg_id(%d)\n", target->per_id, tg->id); mpi3mr_set_io_divert_for_all_vd_in_tg( sc, tg, 0); } } else { if (ratelimit % 1000) { mpi3mr_dprint(sc, MPI3MR_IOT, "large pd_io completion persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_low(%d)\n", target->per_id, target->dev_handle, data_len_blks, ioc_pend_data_len, sc->io_throttle_low); ratelimit++; } if (ioc_pend_data_len <= sc->io_throttle_low) { target->io_divert = 0; mpi3mr_dprint(sc, MPI3MR_IOT, "PD: Coming out of divert perst_id(%d)\n", target->per_id); } } } else if (target->io_divert) { ioc_pend_data_len = mpi3mr_atomic_read(&sc->pend_large_data_sz); if (!tg) { if (ratelimit % 1000) { mpi3mr_dprint(sc, MPI3MR_IOT, "pd_io completion persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_low(%d)\n", target->per_id, target->dev_handle, data_len_blks, ioc_pend_data_len, sc->io_throttle_low); ratelimit++; } if ( ioc_pend_data_len <= sc->io_throttle_low) { mpi3mr_dprint(sc, MPI3MR_IOT, "PD: Coming out of divert perst_id(%d)\n", target->per_id); target->io_divert = 0; } } else if (ioc_pend_data_len <= sc->io_throttle_low) { tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz); if (ratelimit % 1000) { mpi3mr_dprint(sc, MPI3MR_IOT, "vd_io completion persist_id(%d), handle(0x%04x), data_len(%d)," "ioc_pending(%d), tg_pending(%d), ioc_low(%d), tg_low(%d)\n", target->per_id, target->dev_handle, data_len_blks, ioc_pend_data_len, tg_pend_data_len, sc->io_throttle_low, tg->low); ratelimit++; } if (tg->io_divert && (tg_pend_data_len <= tg->low)) { tg->io_divert = 0; mpi3mr_dprint(sc, MPI3MR_IOT, "VD: Coming out of divert perst_id(%d) tg_id(%d)\n", target->per_id, tg->id); mpi3mr_set_io_divert_for_all_vd_in_tg( sc, tg, 0); } } } } if (success_desc) { mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); goto out_success; } if (ioc_status == MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_count == 0 && (scsi_status == MPI3_SCSI_STATUS_BUSY || scsi_status == MPI3_SCSI_STATUS_RESERVATION_CONFLICT || scsi_status == MPI3_SCSI_STATUS_TASK_SET_FULL)) ioc_status = MPI3_IOCSTATUS_SUCCESS; if ((sense_state == MPI3_SCSI_STATE_SENSE_VALID) && sense_count && sense_buf) { int sense_len, returned_sense_len; returned_sense_len = min(le32toh(sense_count), sizeof(struct scsi_sense_data)); if (returned_sense_len < csio->sense_len) csio->sense_resid = csio->sense_len - returned_sense_len; else csio->sense_resid = 0; sense_len = min(returned_sense_len, csio->sense_len - csio->sense_resid); bzero(&csio->sense_data, sizeof(csio->sense_data)); bcopy(sense_buf, &csio->sense_data, sense_len); ccb->ccb_h.status |= CAM_AUTOSNS_VALID; } switch (ioc_status) { case MPI3_IOCSTATUS_BUSY: case MPI3_IOCSTATUS_INSUFFICIENT_RESOURCES: mpi3mr_set_ccbstatus(ccb, CAM_REQUEUE_REQ); break; case MPI3_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* * If devinfo is 0 this will be a volume. In that case don't * tell CAM that the volume is not there. We want volumes to * be enumerated until they are deleted/removed, not just * failed. */ if (cm->targ->devinfo == 0) mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); else mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); break; case MPI3_IOCSTATUS_SCSI_TASK_TERMINATED: case MPI3_IOCSTATUS_SCSI_IOC_TERMINATED: case MPI3_IOCSTATUS_SCSI_EXT_TERMINATED: mpi3mr_set_ccbstatus(ccb, CAM_SCSI_BUSY); mpi3mr_dprint(sc, MPI3MR_TRACE, "func: %s line:%d tgt %u Hosttag %u loginfo %x\n", __func__, __LINE__, target_id, cm->hosttag, le32toh(scsi_reply->IOCLogInfo)); mpi3mr_dprint(sc, MPI3MR_TRACE, "SCSIStatus %x SCSIState %x xfercount %u\n", scsi_reply->SCSIStatus, scsi_reply->SCSIState, le32toh(xfer_count)); break; case MPI3_IOCSTATUS_SCSI_DATA_OVERRUN: /* resid is ignored for this condition */ csio->resid = 0; mpi3mr_set_ccbstatus(ccb, CAM_DATA_RUN_ERR); break; case MPI3_IOCSTATUS_SCSI_DATA_UNDERRUN: csio->resid = cm->length - le32toh(xfer_count); case MPI3_IOCSTATUS_SCSI_RECOVERED_ERROR: case MPI3_IOCSTATUS_SUCCESS: - if ((scsi_reply->IOCStatus & MPI3_REPLY_DESCRIPT_STATUS_IOCSTATUS_STATUS_MASK) == + if ((scsi_reply->IOCStatus & MPI3_IOCSTATUS_STATUS_MASK) == MPI3_IOCSTATUS_SCSI_RECOVERED_ERROR) mpi3mr_dprint(sc, MPI3MR_XINFO, "func: %s line: %d recovered error\n", __func__, __LINE__); /* Completion failed at the transport level. */ if (scsi_reply->SCSIState & (MPI3_SCSI_STATE_NO_SCSI_STATUS | MPI3_SCSI_STATE_TERMINATED)) { mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); break; } /* In a modern packetized environment, an autosense failure * implies that there's not much else that can be done to * recover the command. */ if (scsi_reply->SCSIState & MPI3_SCSI_STATE_SENSE_VALID) { mpi3mr_set_ccbstatus(ccb, CAM_AUTOSENSE_FAIL); break; } /* * Intentionally override the normal SCSI status reporting * for these two cases. These are likely to happen in a * multi-initiator environment, and we want to make sure that * CAM retries these commands rather than fail them. */ if ((scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_COMMAND_TERMINATED) || (scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_TASK_ABORTED)) { mpi3mr_set_ccbstatus(ccb, CAM_REQ_ABORTED); break; } /* Handle normal status and sense */ csio->scsi_status = scsi_reply->SCSIStatus; if (scsi_reply->SCSIStatus == MPI3_SCSI_STATUS_GOOD) mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); else mpi3mr_set_ccbstatus(ccb, CAM_SCSI_STATUS_ERROR); if (scsi_reply->SCSIState & MPI3_SCSI_STATE_SENSE_VALID) { int sense_len, returned_sense_len; returned_sense_len = min(le32toh(scsi_reply->SenseCount), sizeof(struct scsi_sense_data)); if (returned_sense_len < csio->sense_len) csio->sense_resid = csio->sense_len - returned_sense_len; else csio->sense_resid = 0; sense_len = min(returned_sense_len, csio->sense_len - csio->sense_resid); bzero(&csio->sense_data, sizeof(csio->sense_data)); bcopy(cm->sense, &csio->sense_data, sense_len); ccb->ccb_h.status |= CAM_AUTOSNS_VALID; } break; case MPI3_IOCSTATUS_INVALID_SGL: mpi3mr_set_ccbstatus(ccb, CAM_UNREC_HBA_ERROR); break; case MPI3_IOCSTATUS_EEDP_GUARD_ERROR: case MPI3_IOCSTATUS_EEDP_REF_TAG_ERROR: case MPI3_IOCSTATUS_EEDP_APP_TAG_ERROR: case MPI3_IOCSTATUS_SCSI_PROTOCOL_ERROR: case MPI3_IOCSTATUS_INVALID_FUNCTION: case MPI3_IOCSTATUS_INTERNAL_ERROR: case MPI3_IOCSTATUS_INVALID_FIELD: case MPI3_IOCSTATUS_INVALID_STATE: case MPI3_IOCSTATUS_SCSI_IO_DATA_ERROR: case MPI3_IOCSTATUS_SCSI_TASK_MGMT_FAILED: case MPI3_IOCSTATUS_INSUFFICIENT_POWER: case MPI3_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: default: csio->resid = cm->length; mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); break; } out_success: if (mpi3mr_get_ccbstatus(ccb) != CAM_REQ_CMP) { ccb->ccb_h.status |= CAM_DEV_QFRZN; xpt_freeze_devq(ccb->ccb_h.path, /*count*/ 1); } mpi3mr_atomic_dec(&cm->targ->outstanding); mpi3mr_cmd_done(sc, cm); mpi3mr_dprint(sc, MPI3MR_TRACE, "Completion IO path :" " cdb[0]: %x targetid: 0x%x SMID: %x ioc_status: 0x%x ioc_loginfo: 0x%x scsi_status: 0x%x " "scsi_state: 0x%x response_data: 0x%x\n", scsi_cdb[0], target_id, host_tag, ioc_status, ioc_loginfo, scsi_status, scsi_state, resp_data); mpi3mr_atomic_dec(&sc->fw_outstanding); out: if (sense_buf) mpi3mr_repost_sense_buf(sc, scsi_reply->SenseDataBufferAddress); return; } /* * mpi3mr_complete_io_cmd: ISR routine for IO commands * @sc: Adapter's soft instance * @irq_ctx: Driver's internal per IRQ structure * * This function processes IO command completions. */ int mpi3mr_complete_io_cmd(struct mpi3mr_softc *sc, struct mpi3mr_irq_context *irq_ctx) { struct mpi3mr_op_reply_queue *op_reply_q = irq_ctx->op_reply_q; U32 exp_phase = op_reply_q->ephase; U32 reply_ci = op_reply_q->ci; U32 num_op_replies = 0; U64 reply_dma = 0; Mpi3DefaultReplyDescriptor_t *reply_desc; U16 req_qid = 0, threshold_comps = 0; mtx_lock_spin(&op_reply_q->q_lock); if (op_reply_q->in_use == false) { op_reply_q->in_use = true; mtx_unlock_spin(&op_reply_q->q_lock); } else { mtx_unlock_spin(&op_reply_q->q_lock); return 0; } reply_desc = (Mpi3DefaultReplyDescriptor_t *)op_reply_q->q_base + reply_ci; mpi3mr_dprint(sc, MPI3MR_TRACE, "[QID:%d]:reply_desc: (%pa) reply_ci: %x" " reply_desc->ReplyFlags: 0x%x\n" "reply_q_base_phys: %#016jx reply_q_base: (%pa) exp_phase: %x\n", op_reply_q->qid, reply_desc, reply_ci, reply_desc->ReplyFlags, op_reply_q->q_base_phys, op_reply_q->q_base, exp_phase); if (((reply_desc->ReplyFlags & MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) || !op_reply_q->qid) { mtx_lock_spin(&op_reply_q->q_lock); op_reply_q->in_use = false; mtx_unlock_spin(&op_reply_q->q_lock); return 0; } do { req_qid = reply_desc->RequestQueueID; sc->op_req_q[req_qid - 1].ci = reply_desc->RequestQueueCI; mpi3mr_process_op_reply_desc(sc, reply_desc, &reply_dma); mpi3mr_atomic_dec(&op_reply_q->pend_ios); if (reply_dma) mpi3mr_repost_reply_buf(sc, reply_dma); num_op_replies++; if (++reply_ci == op_reply_q->num_replies) { reply_ci = 0; exp_phase ^= 1; } reply_desc = (Mpi3DefaultReplyDescriptor_t *)op_reply_q->q_base + reply_ci; if ((reply_desc->ReplyFlags & MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) != exp_phase) break; if (++threshold_comps == MPI3MR_THRESHOLD_REPLY_COUNT) { mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(op_reply_q->qid), reply_ci); threshold_comps = 0; } } while (1); mpi3mr_regwrite(sc, MPI3_SYSIF_OPER_REPLY_Q_N_CI_OFFSET(op_reply_q->qid), reply_ci); op_reply_q->ci = reply_ci; op_reply_q->ephase = exp_phase; mtx_lock_spin(&op_reply_q->q_lock); op_reply_q->in_use = false; mtx_unlock_spin(&op_reply_q->q_lock); return num_op_replies; } /* * mpi3mr_isr: Primary ISR function * privdata: Driver's internal per IRQ structure * * This is driver's primary ISR function which is being called whenever any admin/IO * command completion. */ void mpi3mr_isr(void *privdata) { struct mpi3mr_irq_context *irq_ctx = (struct mpi3mr_irq_context *)privdata; struct mpi3mr_softc *sc = irq_ctx->sc; U16 msi_idx; if (!irq_ctx) return; msi_idx = irq_ctx->msix_index; if (!sc->intr_enabled) return; if (!msi_idx) mpi3mr_complete_admin_cmd(sc); if (irq_ctx->op_reply_q && irq_ctx->op_reply_q->qid) { mpi3mr_complete_io_cmd(sc, irq_ctx); } } /* * mpi3mr_alloc_requests - Allocates host commands * @sc: Adapter reference * * This function allocates controller supported host commands * * Return: 0 on success and proper error codes on failure */ int mpi3mr_alloc_requests(struct mpi3mr_softc *sc) { struct mpi3mr_cmd *cmd; int i, j, nsegs, ret; nsegs = MPI3MR_SG_DEPTH; ret = bus_dma_tag_create( sc->mpi3mr_parent_dmat, /* parent */ 1, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ BUS_SPACE_MAXSIZE, /* maxsize */ nsegs, /* nsegments */ BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ BUS_DMA_ALLOCNOW, /* flags */ busdma_lock_mutex, /* lockfunc */ &sc->io_lock, /* lockarg */ &sc->buffer_dmat); if (ret) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate buffer DMA tag ret: %d\n", ret); return (ENOMEM); } /* * sc->cmd_list is an array of struct mpi3mr_cmd pointers. * Allocate the dynamic array first and then allocate individual * commands. */ sc->cmd_list = malloc(sizeof(struct mpi3mr_cmd *) * sc->max_host_ios, M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->cmd_list) { device_printf(sc->mpi3mr_dev, "Cannot alloc memory for mpt_cmd_list.\n"); return (ENOMEM); } for (i = 0; i < sc->max_host_ios; i++) { sc->cmd_list[i] = malloc(sizeof(struct mpi3mr_cmd), M_MPI3MR, M_NOWAIT | M_ZERO); if (!sc->cmd_list[i]) { for (j = 0; j < i; j++) free(sc->cmd_list[j], M_MPI3MR); free(sc->cmd_list, M_MPI3MR); sc->cmd_list = NULL; return (ENOMEM); } } for (i = 1; i < sc->max_host_ios; i++) { cmd = sc->cmd_list[i]; cmd->hosttag = i; cmd->sc = sc; cmd->state = MPI3MR_CMD_STATE_BUSY; callout_init_mtx(&cmd->callout, &sc->mpi3mr_mtx, 0); cmd->ccb = NULL; TAILQ_INSERT_TAIL(&(sc->cmd_list_head), cmd, next); if (bus_dmamap_create(sc->buffer_dmat, 0, &cmd->dmamap)) return ENOMEM; } return (0); } /* * mpi3mr_get_command: Get a coomand structure from free command pool * @sc: Adapter soft instance * Return: MPT command reference * * This function returns an MPT command to the caller. */ struct mpi3mr_cmd * mpi3mr_get_command(struct mpi3mr_softc *sc) { struct mpi3mr_cmd *cmd = NULL; mtx_lock(&sc->cmd_pool_lock); if (!TAILQ_EMPTY(&sc->cmd_list_head)) { cmd = TAILQ_FIRST(&sc->cmd_list_head); TAILQ_REMOVE(&sc->cmd_list_head, cmd, next); } else { goto out; } mpi3mr_dprint(sc, MPI3MR_TRACE, "Get command SMID: 0x%x\n", cmd->hosttag); memset((uint8_t *)&cmd->io_request, 0, MPI3MR_AREQ_FRAME_SZ); cmd->data_dir = 0; cmd->ccb = NULL; cmd->targ = NULL; cmd->state = MPI3MR_CMD_STATE_BUSY; cmd->data = NULL; cmd->length = 0; out: mtx_unlock(&sc->cmd_pool_lock); return cmd; } /* * mpi3mr_release_command: Return a cmd to free command pool * input: Command packet for return to free command pool * * This function returns an MPT command to the free command list. */ void mpi3mr_release_command(struct mpi3mr_cmd *cmd) { struct mpi3mr_softc *sc = cmd->sc; mtx_lock(&sc->cmd_pool_lock); TAILQ_INSERT_HEAD(&(sc->cmd_list_head), cmd, next); cmd->state = MPI3MR_CMD_STATE_FREE; cmd->req_qidx = 0; mpi3mr_dprint(sc, MPI3MR_TRACE, "Release command SMID: 0x%x\n", cmd->hosttag); mtx_unlock(&sc->cmd_pool_lock); return; } /** * mpi3mr_free_ioctl_dma_memory - free memory for ioctl dma * @sc: Adapter instance reference * * Free the DMA memory allocated for IOCTL handling purpose. * * Return: None */ static void mpi3mr_free_ioctl_dma_memory(struct mpi3mr_softc *sc) { U16 i; struct dma_memory_desc *mem_desc; for (i=0; iioctl_sge[i]; if (mem_desc->addr && mem_desc->dma_addr) { bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap); bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap); mem_desc->addr = NULL; if (mem_desc->tag != NULL) bus_dma_tag_destroy(mem_desc->tag); } } mem_desc = &sc->ioctl_chain_sge; if (mem_desc->addr && mem_desc->dma_addr) { bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap); bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap); mem_desc->addr = NULL; if (mem_desc->tag != NULL) bus_dma_tag_destroy(mem_desc->tag); } mem_desc = &sc->ioctl_resp_sge; if (mem_desc->addr && mem_desc->dma_addr) { bus_dmamap_unload(mem_desc->tag, mem_desc->dmamap); bus_dmamem_free(mem_desc->tag, mem_desc->addr, mem_desc->dmamap); mem_desc->addr = NULL; if (mem_desc->tag != NULL) bus_dma_tag_destroy(mem_desc->tag); } sc->ioctl_sges_allocated = false; } /** * mpi3mr_alloc_ioctl_dma_memory - Alloc memory for ioctl dma * @sc: Adapter instance reference * * This function allocates dmaable memory required to handle the * application issued MPI3 IOCTL requests. * * Return: None */ void mpi3mr_alloc_ioctl_dma_memory(struct mpi3mr_softc *sc) { struct dma_memory_desc *mem_desc; U16 i; for (i=0; iioctl_sge[i]; mem_desc->size = MPI3MR_IOCTL_SGE_SIZE; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ mem_desc->size, /* maxsize */ 1, /* nsegments */ mem_desc->size, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &mem_desc->tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); goto out_failed; } if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr, BUS_DMA_NOWAIT, &mem_desc->dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); goto out_failed; } bzero(mem_desc->addr, mem_desc->size); bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size, mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT); if (!mem_desc->addr) goto out_failed; } mem_desc = &sc->ioctl_chain_sge; mem_desc->size = MPI3MR_4K_PGSZ; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ mem_desc->size, /* maxsize */ 1, /* nsegments */ mem_desc->size, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &mem_desc->tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); goto out_failed; } if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr, BUS_DMA_NOWAIT, &mem_desc->dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Cannot allocate replies memory\n", __func__); goto out_failed; } bzero(mem_desc->addr, mem_desc->size); bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size, mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT); if (!mem_desc->addr) goto out_failed; mem_desc = &sc->ioctl_resp_sge; mem_desc->size = MPI3MR_4K_PGSZ; if (bus_dma_tag_create(sc->mpi3mr_parent_dmat, /* parent */ 4, 0, /* algnmnt, boundary */ sc->dma_loaddr, /* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ mem_desc->size, /* maxsize */ 1, /* nsegments */ mem_desc->size, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &mem_desc->tag)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate request DMA tag\n"); goto out_failed; } if (bus_dmamem_alloc(mem_desc->tag, (void **)&mem_desc->addr, BUS_DMA_NOWAIT, &mem_desc->dmamap)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Cannot allocate replies memory\n"); goto out_failed; } bzero(mem_desc->addr, mem_desc->size); bus_dmamap_load(mem_desc->tag, mem_desc->dmamap, mem_desc->addr, mem_desc->size, mpi3mr_memaddr_cb, &mem_desc->dma_addr, BUS_DMA_NOWAIT); if (!mem_desc->addr) goto out_failed; sc->ioctl_sges_allocated = true; return; out_failed: printf("cannot allocate DMA memory for the mpt commands" " from the applications, application interface for MPT command is disabled\n"); mpi3mr_free_ioctl_dma_memory(sc); } void mpi3mr_destory_mtx(struct mpi3mr_softc *sc) { int i; struct mpi3mr_op_req_queue *op_req_q; struct mpi3mr_op_reply_queue *op_reply_q; if (sc->admin_reply) { if (mtx_initialized(&sc->admin_reply_lock)) mtx_destroy(&sc->admin_reply_lock); } if (sc->op_reply_q) { for(i = 0; i < sc->num_queues; i++) { op_reply_q = sc->op_reply_q + i; if (mtx_initialized(&op_reply_q->q_lock)) mtx_destroy(&op_reply_q->q_lock); } } if (sc->op_req_q) { for(i = 0; i < sc->num_queues; i++) { op_req_q = sc->op_req_q + i; if (mtx_initialized(&op_req_q->q_lock)) mtx_destroy(&op_req_q->q_lock); } } if (mtx_initialized(&sc->init_cmds.completion.lock)) mtx_destroy(&sc->init_cmds.completion.lock); if (mtx_initialized(&sc->ioctl_cmds.completion.lock)) mtx_destroy(&sc->ioctl_cmds.completion.lock); if (mtx_initialized(&sc->host_tm_cmds.completion.lock)) mtx_destroy(&sc->host_tm_cmds.completion.lock); for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { if (mtx_initialized(&sc->dev_rmhs_cmds[i].completion.lock)) mtx_destroy(&sc->dev_rmhs_cmds[i].completion.lock); } if (mtx_initialized(&sc->reset_mutex)) mtx_destroy(&sc->reset_mutex); if (mtx_initialized(&sc->target_lock)) mtx_destroy(&sc->target_lock); if (mtx_initialized(&sc->fwevt_lock)) mtx_destroy(&sc->fwevt_lock); if (mtx_initialized(&sc->cmd_pool_lock)) mtx_destroy(&sc->cmd_pool_lock); if (mtx_initialized(&sc->reply_free_q_lock)) mtx_destroy(&sc->reply_free_q_lock); if (mtx_initialized(&sc->sense_buf_q_lock)) mtx_destroy(&sc->sense_buf_q_lock); if (mtx_initialized(&sc->chain_buf_lock)) mtx_destroy(&sc->chain_buf_lock); if (mtx_initialized(&sc->admin_req_lock)) mtx_destroy(&sc->admin_req_lock); if (mtx_initialized(&sc->mpi3mr_mtx)) mtx_destroy(&sc->mpi3mr_mtx); } /** * mpi3mr_free_mem - Freeup adapter level data structures * @sc: Adapter reference * * Return: Nothing. */ void mpi3mr_free_mem(struct mpi3mr_softc *sc) { int i; struct mpi3mr_op_req_queue *op_req_q; struct mpi3mr_op_reply_queue *op_reply_q; struct mpi3mr_irq_context *irq_ctx; if (sc->cmd_list) { for (i = 0; i < sc->max_host_ios; i++) { free(sc->cmd_list[i], M_MPI3MR); } free(sc->cmd_list, M_MPI3MR); sc->cmd_list = NULL; } if (sc->pel_seq_number && sc->pel_seq_number_dma) { bus_dmamap_unload(sc->pel_seq_num_dmatag, sc->pel_seq_num_dmamap); bus_dmamem_free(sc->pel_seq_num_dmatag, sc->pel_seq_number, sc->pel_seq_num_dmamap); sc->pel_seq_number = NULL; if (sc->pel_seq_num_dmatag != NULL) bus_dma_tag_destroy(sc->pel_seq_num_dmatag); } if (sc->throttle_groups) { free(sc->throttle_groups, M_MPI3MR); sc->throttle_groups = NULL; } /* Free up operational queues*/ if (sc->op_req_q) { for (i = 0; i < sc->num_queues; i++) { op_req_q = sc->op_req_q + i; if (op_req_q->q_base && op_req_q->q_base_phys) { bus_dmamap_unload(op_req_q->q_base_tag, op_req_q->q_base_dmamap); bus_dmamem_free(op_req_q->q_base_tag, op_req_q->q_base, op_req_q->q_base_dmamap); op_req_q->q_base = NULL; if (op_req_q->q_base_tag != NULL) bus_dma_tag_destroy(op_req_q->q_base_tag); } } free(sc->op_req_q, M_MPI3MR); sc->op_req_q = NULL; } if (sc->op_reply_q) { for (i = 0; i < sc->num_queues; i++) { op_reply_q = sc->op_reply_q + i; if (op_reply_q->q_base && op_reply_q->q_base_phys) { bus_dmamap_unload(op_reply_q->q_base_tag, op_reply_q->q_base_dmamap); bus_dmamem_free(op_reply_q->q_base_tag, op_reply_q->q_base, op_reply_q->q_base_dmamap); op_reply_q->q_base = NULL; if (op_reply_q->q_base_tag != NULL) bus_dma_tag_destroy(op_reply_q->q_base_tag); } } free(sc->op_reply_q, M_MPI3MR); sc->op_reply_q = NULL; } /* Free up chain buffers*/ if (sc->chain_sgl_list) { for (i = 0; i < sc->chain_buf_count; i++) { if (sc->chain_sgl_list[i].buf && sc->chain_sgl_list[i].buf_phys) { bus_dmamap_unload(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf_dmamap); bus_dmamem_free(sc->chain_sgl_list_tag, sc->chain_sgl_list[i].buf, sc->chain_sgl_list[i].buf_dmamap); sc->chain_sgl_list[i].buf = NULL; } } if (sc->chain_sgl_list_tag != NULL) bus_dma_tag_destroy(sc->chain_sgl_list_tag); free(sc->chain_sgl_list, M_MPI3MR); sc->chain_sgl_list = NULL; } if (sc->chain_bitmap) { free(sc->chain_bitmap, M_MPI3MR); sc->chain_bitmap = NULL; } for (i = 0; i < sc->msix_count; i++) { irq_ctx = sc->irq_ctx + i; if (irq_ctx) irq_ctx->op_reply_q = NULL; } /* Free reply_buf_tag */ if (sc->reply_buf && sc->reply_buf_phys) { bus_dmamap_unload(sc->reply_buf_tag, sc->reply_buf_dmamap); bus_dmamem_free(sc->reply_buf_tag, sc->reply_buf, sc->reply_buf_dmamap); sc->reply_buf = NULL; if (sc->reply_buf_tag != NULL) bus_dma_tag_destroy(sc->reply_buf_tag); } /* Free reply_free_q_tag */ if (sc->reply_free_q && sc->reply_free_q_phys) { bus_dmamap_unload(sc->reply_free_q_tag, sc->reply_free_q_dmamap); bus_dmamem_free(sc->reply_free_q_tag, sc->reply_free_q, sc->reply_free_q_dmamap); sc->reply_free_q = NULL; if (sc->reply_free_q_tag != NULL) bus_dma_tag_destroy(sc->reply_free_q_tag); } /* Free sense_buf_tag */ if (sc->sense_buf && sc->sense_buf_phys) { bus_dmamap_unload(sc->sense_buf_tag, sc->sense_buf_dmamap); bus_dmamem_free(sc->sense_buf_tag, sc->sense_buf, sc->sense_buf_dmamap); sc->sense_buf = NULL; if (sc->sense_buf_tag != NULL) bus_dma_tag_destroy(sc->sense_buf_tag); } /* Free sense_buf_q_tag */ if (sc->sense_buf_q && sc->sense_buf_q_phys) { bus_dmamap_unload(sc->sense_buf_q_tag, sc->sense_buf_q_dmamap); bus_dmamem_free(sc->sense_buf_q_tag, sc->sense_buf_q, sc->sense_buf_q_dmamap); sc->sense_buf_q = NULL; if (sc->sense_buf_q_tag != NULL) bus_dma_tag_destroy(sc->sense_buf_q_tag); } /* Free up internal(non-IO) commands*/ if (sc->init_cmds.reply) { free(sc->init_cmds.reply, M_MPI3MR); sc->init_cmds.reply = NULL; } if (sc->ioctl_cmds.reply) { free(sc->ioctl_cmds.reply, M_MPI3MR); sc->ioctl_cmds.reply = NULL; } if (sc->pel_cmds.reply) { free(sc->pel_cmds.reply, M_MPI3MR); sc->pel_cmds.reply = NULL; } if (sc->pel_abort_cmd.reply) { free(sc->pel_abort_cmd.reply, M_MPI3MR); sc->pel_abort_cmd.reply = NULL; } if (sc->host_tm_cmds.reply) { free(sc->host_tm_cmds.reply, M_MPI3MR); sc->host_tm_cmds.reply = NULL; } if (sc->log_data_buffer) { free(sc->log_data_buffer, M_MPI3MR); sc->log_data_buffer = NULL; } for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { if (sc->dev_rmhs_cmds[i].reply) { free(sc->dev_rmhs_cmds[i].reply, M_MPI3MR); sc->dev_rmhs_cmds[i].reply = NULL; } } for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) { if (sc->evtack_cmds[i].reply) { free(sc->evtack_cmds[i].reply, M_MPI3MR); sc->evtack_cmds[i].reply = NULL; } } if (sc->removepend_bitmap) { free(sc->removepend_bitmap, M_MPI3MR); sc->removepend_bitmap = NULL; } if (sc->devrem_bitmap) { free(sc->devrem_bitmap, M_MPI3MR); sc->devrem_bitmap = NULL; } if (sc->evtack_cmds_bitmap) { free(sc->evtack_cmds_bitmap, M_MPI3MR); sc->evtack_cmds_bitmap = NULL; } /* Free Admin reply*/ if (sc->admin_reply && sc->admin_reply_phys) { bus_dmamap_unload(sc->admin_reply_tag, sc->admin_reply_dmamap); bus_dmamem_free(sc->admin_reply_tag, sc->admin_reply, sc->admin_reply_dmamap); sc->admin_reply = NULL; if (sc->admin_reply_tag != NULL) bus_dma_tag_destroy(sc->admin_reply_tag); } /* Free Admin request*/ if (sc->admin_req && sc->admin_req_phys) { bus_dmamap_unload(sc->admin_req_tag, sc->admin_req_dmamap); bus_dmamem_free(sc->admin_req_tag, sc->admin_req, sc->admin_req_dmamap); sc->admin_req = NULL; if (sc->admin_req_tag != NULL) bus_dma_tag_destroy(sc->admin_req_tag); } mpi3mr_free_ioctl_dma_memory(sc); } /** * mpi3mr_drv_cmd_comp_reset - Flush a internal driver command * @sc: Adapter instance reference * @cmdptr: Internal command tracker * * Complete an internal driver commands with state indicating it * is completed due to reset. * * Return: Nothing. */ static inline void mpi3mr_drv_cmd_comp_reset(struct mpi3mr_softc *sc, struct mpi3mr_drvr_cmd *cmdptr) { if (cmdptr->state & MPI3MR_CMD_PENDING) { cmdptr->state |= MPI3MR_CMD_RESET; cmdptr->state &= ~MPI3MR_CMD_PENDING; if (cmdptr->is_waiting) { complete(&cmdptr->completion); cmdptr->is_waiting = 0; } else if (cmdptr->callback) cmdptr->callback(sc, cmdptr); } } /** * mpi3mr_flush_drv_cmds - Flush internal driver commands * @sc: Adapter instance reference * * Flush all internal driver commands post reset * * Return: Nothing. */ static void mpi3mr_flush_drv_cmds(struct mpi3mr_softc *sc) { int i = 0; struct mpi3mr_drvr_cmd *cmdptr; cmdptr = &sc->init_cmds; mpi3mr_drv_cmd_comp_reset(sc, cmdptr); cmdptr = &sc->ioctl_cmds; mpi3mr_drv_cmd_comp_reset(sc, cmdptr); cmdptr = &sc->host_tm_cmds; mpi3mr_drv_cmd_comp_reset(sc, cmdptr); for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) { cmdptr = &sc->dev_rmhs_cmds[i]; mpi3mr_drv_cmd_comp_reset(sc, cmdptr); } for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) { cmdptr = &sc->evtack_cmds[i]; mpi3mr_drv_cmd_comp_reset(sc, cmdptr); } cmdptr = &sc->pel_cmds; mpi3mr_drv_cmd_comp_reset(sc, cmdptr); cmdptr = &sc->pel_abort_cmd; mpi3mr_drv_cmd_comp_reset(sc, cmdptr); } /** * mpi3mr_memset_buffers - memset memory for a controller * @sc: Adapter instance reference * * clear all the memory allocated for a controller, typically * called post reset to reuse the memory allocated during the * controller init. * * Return: Nothing. */ static void mpi3mr_memset_buffers(struct mpi3mr_softc *sc) { U16 i; struct mpi3mr_throttle_group_info *tg; memset(sc->admin_req, 0, sc->admin_req_q_sz); memset(sc->admin_reply, 0, sc->admin_reply_q_sz); memset(sc->init_cmds.reply, 0, sc->reply_sz); memset(sc->ioctl_cmds.reply, 0, sc->reply_sz); memset(sc->host_tm_cmds.reply, 0, sc->reply_sz); memset(sc->pel_cmds.reply, 0, sc->reply_sz); memset(sc->pel_abort_cmd.reply, 0, sc->reply_sz); for (i = 0; i < MPI3MR_NUM_DEVRMCMD; i++) memset(sc->dev_rmhs_cmds[i].reply, 0, sc->reply_sz); for (i = 0; i < MPI3MR_NUM_EVTACKCMD; i++) memset(sc->evtack_cmds[i].reply, 0, sc->reply_sz); memset(sc->removepend_bitmap, 0, sc->dev_handle_bitmap_sz); memset(sc->devrem_bitmap, 0, sc->devrem_bitmap_sz); memset(sc->evtack_cmds_bitmap, 0, sc->evtack_cmds_bitmap_sz); for (i = 0; i < sc->num_queues; i++) { sc->op_reply_q[i].qid = 0; sc->op_reply_q[i].ci = 0; sc->op_reply_q[i].num_replies = 0; sc->op_reply_q[i].ephase = 0; mpi3mr_atomic_set(&sc->op_reply_q[i].pend_ios, 0); memset(sc->op_reply_q[i].q_base, 0, sc->op_reply_q[i].qsz); sc->op_req_q[i].ci = 0; sc->op_req_q[i].pi = 0; sc->op_req_q[i].num_reqs = 0; sc->op_req_q[i].qid = 0; sc->op_req_q[i].reply_qid = 0; memset(sc->op_req_q[i].q_base, 0, sc->op_req_q[i].qsz); } mpi3mr_atomic_set(&sc->pend_large_data_sz, 0); if (sc->throttle_groups) { tg = sc->throttle_groups; for (i = 0; i < sc->num_io_throttle_group; i++, tg++) { tg->id = 0; tg->fw_qd = 0; tg->modified_qd = 0; tg->io_divert= 0; tg->high = 0; tg->low = 0; mpi3mr_atomic_set(&tg->pend_large_data_sz, 0); } } } /** * mpi3mr_invalidate_devhandles -Invalidate device handles * @sc: Adapter instance reference * * Invalidate the device handles in the target device structures * . Called post reset prior to reinitializing the controller. * * Return: Nothing. */ static void mpi3mr_invalidate_devhandles(struct mpi3mr_softc *sc) { struct mpi3mr_target *target = NULL; mtx_lock_spin(&sc->target_lock); TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) { if (target) { target->dev_handle = MPI3MR_INVALID_DEV_HANDLE; target->io_throttle_enabled = 0; target->io_divert = 0; target->throttle_group = NULL; } } mtx_unlock_spin(&sc->target_lock); } /** * mpi3mr_rfresh_tgtdevs - Refresh target device exposure * @sc: Adapter instance reference * * This is executed post controller reset to identify any * missing devices during reset and remove from the upper layers * or expose any newly detected device to the upper layers. * * Return: Nothing. */ static void mpi3mr_rfresh_tgtdevs(struct mpi3mr_softc *sc) { struct mpi3mr_target *target = NULL; struct mpi3mr_target *target_temp = NULL; TAILQ_FOREACH_SAFE(target, &sc->cam_sc->tgt_list, tgt_next, target_temp) { if (target->dev_handle == MPI3MR_INVALID_DEV_HANDLE) { if (target->exposed_to_os) mpi3mr_remove_device_from_os(sc, target->dev_handle); mpi3mr_remove_device_from_list(sc, target, true); } else if (target->is_hidden && target->exposed_to_os) { mpi3mr_remove_device_from_os(sc, target->dev_handle); } } TAILQ_FOREACH(target, &sc->cam_sc->tgt_list, tgt_next) { if ((target->dev_handle != MPI3MR_INVALID_DEV_HANDLE) && !target->is_hidden && !target->exposed_to_os) { mpi3mr_add_device(sc, target->per_id); } } } static void mpi3mr_flush_io(struct mpi3mr_softc *sc) { int i; struct mpi3mr_cmd *cmd = NULL; union ccb *ccb = NULL; for (i = 0; i < sc->max_host_ios; i++) { cmd = sc->cmd_list[i]; if (cmd && cmd->ccb) { if (cmd->callout_owner) { ccb = (union ccb *)(cmd->ccb); ccb->ccb_h.status = CAM_SCSI_BUS_RESET; mpi3mr_atomic_dec(&sc->fw_outstanding); mpi3mr_atomic_dec(&cmd->targ->outstanding); mpi3mr_cmd_done(sc, cmd); } else { cmd->ccb = NULL; mpi3mr_release_command(cmd); } } } } /** * mpi3mr_clear_reset_history - Clear reset history * @sc: Adapter instance reference * * Write the reset history bit in IOC Status to clear the bit, * if it is already set. * * Return: Nothing. */ static inline void mpi3mr_clear_reset_history(struct mpi3mr_softc *sc) { U32 ioc_status; ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_STATUS_OFFSET, ioc_status); } /** * mpi3mr_set_diagsave - Set diag save bit for snapdump * @sc: Adapter reference * * Set diag save bit in IOC configuration register to enable * snapdump. * * Return: Nothing. */ static inline void mpi3mr_set_diagsave(struct mpi3mr_softc *sc) { U32 ioc_config; ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); ioc_config |= MPI3_SYSIF_IOC_CONFIG_DIAG_SAVE; mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); } /** * mpi3mr_issue_reset - Issue reset to the controller * @sc: Adapter reference * @reset_type: Reset type * @reset_reason: Reset reason code * * Unlock the host diagnostic registers and write the specific * reset type to that, wait for reset acknowledgement from the * controller, if the reset is not successful retry for the * predefined number of times. * * Return: 0 on success, non-zero on failure. */ static int mpi3mr_issue_reset(struct mpi3mr_softc *sc, U16 reset_type, U16 reset_reason) { int retval = -1; U8 unlock_retry_count = 0; U32 host_diagnostic, ioc_status, ioc_config, scratch_pad0; U32 timeout = MPI3MR_RESET_ACK_TIMEOUT * 10; if ((reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) && (reset_type != MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT)) return retval; if (sc->unrecoverable) return retval; if (reset_reason == MPI3MR_RESET_FROM_FIRMWARE) { retval = 0; return retval; } mpi3mr_dprint(sc, MPI3MR_INFO, "%s reset due to %s(0x%x)\n", mpi3mr_reset_type_name(reset_type), mpi3mr_reset_rc_name(reset_reason), reset_reason); mpi3mr_clear_reset_history(sc); do { mpi3mr_dprint(sc, MPI3MR_INFO, "Write magic sequence to unlock host diag register (retry=%d)\n", ++unlock_retry_count); if (unlock_retry_count >= MPI3MR_HOSTDIAG_UNLOCK_RETRY_COUNT) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s reset failed! due to host diag register unlock failure" "host_diagnostic(0x%08x)\n", mpi3mr_reset_type_name(reset_type), host_diagnostic); sc->unrecoverable = 1; return retval; } mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_FLUSH); mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_1ST); mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND); mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_3RD); mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_4TH); mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_5TH); mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_6TH); DELAY(1000); /* delay in usec */ host_diagnostic = mpi3mr_regread(sc, MPI3_SYSIF_HOST_DIAG_OFFSET); mpi3mr_dprint(sc, MPI3MR_INFO, "wrote magic sequence: retry_count(%d), host_diagnostic(0x%08x)\n", unlock_retry_count, host_diagnostic); } while (!(host_diagnostic & MPI3_SYSIF_HOST_DIAG_DIAG_WRITE_ENABLE)); scratch_pad0 = ((MPI3MR_RESET_REASON_OSTYPE_FREEBSD << MPI3MR_RESET_REASON_OSTYPE_SHIFT) | (sc->facts.ioc_num << MPI3MR_RESET_REASON_IOCNUM_SHIFT) | reset_reason); mpi3mr_regwrite(sc, MPI3_SYSIF_SCRATCHPAD0_OFFSET, scratch_pad0); mpi3mr_regwrite(sc, MPI3_SYSIF_HOST_DIAG_OFFSET, host_diagnostic | reset_type); if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET) { do { ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); if (ioc_status & MPI3_SYSIF_IOC_STATUS_RESET_HISTORY) { ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); if (mpi3mr_soft_reset_success(ioc_status, ioc_config)) { mpi3mr_clear_reset_history(sc); retval = 0; break; } } DELAY(100 * 1000); } while (--timeout); } else if (reset_type == MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT) { do { ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); if (mpi3mr_diagfault_success(sc, ioc_status)) { retval = 0; break; } DELAY(100 * 1000); } while (--timeout); } mpi3mr_regwrite(sc, MPI3_SYSIF_WRITE_SEQUENCE_OFFSET, MPI3_SYSIF_WRITE_SEQUENCE_KEY_VALUE_2ND); ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); mpi3mr_dprint(sc, MPI3MR_INFO, "IOC Status/Config after %s reset is (0x%x)/(0x%x)\n", !retval ? "successful":"failed", ioc_status, ioc_config); if (retval) sc->unrecoverable = 1; return retval; } inline void mpi3mr_cleanup_event_taskq(struct mpi3mr_softc *sc) { /* * Block the taskqueue before draining. This means any new tasks won't * be queued to the taskqueue worker thread. But it doesn't stop the * current workers that are running. taskqueue_drain waits for those * correctly in the case of thread backed taskqueues. The while loop * ensures that all taskqueue threads have finished their current tasks. */ taskqueue_block(sc->cam_sc->ev_tq); while (taskqueue_cancel(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task, NULL) != 0) { taskqueue_drain(sc->cam_sc->ev_tq, &sc->cam_sc->ev_task); } } /** * mpi3mr_soft_reset_handler - Reset the controller * @sc: Adapter instance reference * @reset_reason: Reset reason code * @snapdump: snapdump enable/disbale bit * * This is an handler for recovering controller by issuing soft * reset or diag fault reset. This is a blocking function and * when one reset is executed if any other resets they will be * blocked. All IOCTLs/IO will be blocked during the reset. If * controller reset is successful then the controller will be * reinitalized, otherwise the controller will be marked as not * recoverable * * Return: 0 on success, non-zero on failure. */ int mpi3mr_soft_reset_handler(struct mpi3mr_softc *sc, U16 reset_reason, bool snapdump) { int retval = 0, i = 0; enum mpi3mr_iocstate ioc_state; mpi3mr_dprint(sc, MPI3MR_INFO, "soft reset invoked: reason code: %s\n", mpi3mr_reset_rc_name(reset_reason)); if ((reset_reason == MPI3MR_RESET_FROM_IOCTL) && (sc->reset.ioctl_reset_snapdump != true)) snapdump = false; mpi3mr_dprint(sc, MPI3MR_INFO, "soft_reset_handler: wait if diag save is in progress\n"); while (sc->diagsave_timeout) DELAY(1000 * 1000); ioc_state = mpi3mr_get_iocstate(sc); if (ioc_state == MRIOC_STATE_UNRECOVERABLE) { mpi3mr_dprint(sc, MPI3MR_ERROR, "controller is in unrecoverable state, exit\n"); sc->reset.type = MPI3MR_NO_RESET; sc->reset.reason = MPI3MR_DEFAULT_RESET_REASON; sc->reset.status = -1; sc->reset.ioctl_reset_snapdump = false; return -1; } if (sc->reset_in_progress) { mpi3mr_dprint(sc, MPI3MR_INFO, "reset is already in progress, exit\n"); return -1; } /* Pause IOs, drain and block the event taskqueue */ xpt_freeze_simq(sc->cam_sc->sim, 1); mpi3mr_cleanup_event_taskq(sc); sc->reset_in_progress = 1; sc->block_ioctls = 1; while (mpi3mr_atomic_read(&sc->pend_ioctls) && (i < PEND_IOCTLS_COMP_WAIT_TIME)) { ioc_state = mpi3mr_get_iocstate(sc); if (ioc_state == MRIOC_STATE_FAULT) break; i++; if (!(i % 5)) { mpi3mr_dprint(sc, MPI3MR_INFO, "[%2ds]waiting for IOCTL to be finished from %s\n", i, __func__); } DELAY(1000 * 1000); } if ((!snapdump) && (reset_reason != MPI3MR_RESET_FROM_FAULT_WATCH) && (reset_reason != MPI3MR_RESET_FROM_FIRMWARE) && (reset_reason != MPI3MR_RESET_FROM_CIACTIV_FAULT)) { mpi3mr_dprint(sc, MPI3MR_INFO, "Turn off events prior to reset\n"); for (i = 0; i < MPI3_EVENT_NOTIFY_EVENTMASK_WORDS; i++) sc->event_masks[i] = -1; mpi3mr_issue_event_notification(sc); } mpi3mr_disable_interrupts(sc); if (snapdump) mpi3mr_trigger_snapdump(sc, reset_reason); retval = mpi3mr_issue_reset(sc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, reset_reason); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to issue soft reset to the ioc\n"); goto out; } mpi3mr_flush_drv_cmds(sc); mpi3mr_flush_io(sc); mpi3mr_invalidate_devhandles(sc); mpi3mr_memset_buffers(sc); if (sc->prepare_for_reset) { sc->prepare_for_reset = 0; sc->prepare_for_reset_timeout_counter = 0; } retval = mpi3mr_initialize_ioc(sc, MPI3MR_INIT_TYPE_RESET); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "reinit after soft reset failed: reason %d\n", reset_reason); goto out; } DELAY((1000 * 1000) * 10); out: if (!retval) { sc->diagsave_timeout = 0; sc->reset_in_progress = 0; mpi3mr_rfresh_tgtdevs(sc); sc->ts_update_counter = 0; sc->block_ioctls = 0; sc->pel_abort_requested = 0; if (sc->pel_wait_pend) { sc->pel_cmds.retry_count = 0; mpi3mr_issue_pel_wait(sc, &sc->pel_cmds); mpi3mr_app_send_aen(sc); } } else { mpi3mr_issue_reset(sc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_DIAG_FAULT, reset_reason); sc->unrecoverable = 1; sc->reset_in_progress = 0; } mpi3mr_dprint(sc, MPI3MR_INFO, "Soft Reset: %s\n", ((retval == 0) ? "SUCCESS" : "FAILED")); taskqueue_unblock(sc->cam_sc->ev_tq); xpt_release_simq(sc->cam_sc->sim, 1); sc->reset.type = MPI3MR_NO_RESET; sc->reset.reason = MPI3MR_DEFAULT_RESET_REASON; sc->reset.status = retval; sc->reset.ioctl_reset_snapdump = false; return retval; } /** * mpi3mr_issue_ioc_shutdown - shutdown controller * @sc: Adapter instance reference * * Send shutodwn notification to the controller and wait for the * shutdown_timeout for it to be completed. * * Return: Nothing. */ static void mpi3mr_issue_ioc_shutdown(struct mpi3mr_softc *sc) { U32 ioc_config, ioc_status; U8 retval = 1, retry = 0; U32 timeout = MPI3MR_DEFAULT_SHUTDOWN_TIME * 10; mpi3mr_dprint(sc, MPI3MR_INFO, "sending shutdown notification\n"); if (sc->unrecoverable) { mpi3mr_dprint(sc, MPI3MR_ERROR, "controller is unrecoverable, shutdown not issued\n"); return; } ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK) == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS) { mpi3mr_dprint(sc, MPI3MR_ERROR, "shutdown already in progress\n"); return; } ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); ioc_config |= MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL; ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ; mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); if (sc->facts.shutdown_timeout) timeout = sc->facts.shutdown_timeout * 10; do { ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK) == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_COMPLETE) { retval = 0; break; } if (sc->unrecoverable) break; if ((ioc_status & MPI3_SYSIF_IOC_STATUS_FAULT)) { mpi3mr_print_fault_info(sc); if (retry >= MPI3MR_MAX_SHUTDOWN_RETRY_COUNT) break; if (mpi3mr_issue_reset(sc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, MPI3MR_RESET_FROM_CTLR_CLEANUP)) break; ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); ioc_config |= MPI3_SYSIF_IOC_CONFIG_SHUTDOWN_NORMAL; ioc_config |= MPI3_SYSIF_IOC_CONFIG_DEVICE_SHUTDOWN_SEND_REQ; mpi3mr_regwrite(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET, ioc_config); if (sc->facts.shutdown_timeout) timeout = sc->facts.shutdown_timeout * 10; retry++; } DELAY(100 * 1000); } while (--timeout); ioc_status = mpi3mr_regread(sc, MPI3_SYSIF_IOC_STATUS_OFFSET); ioc_config = mpi3mr_regread(sc, MPI3_SYSIF_IOC_CONFIG_OFFSET); if (retval) { if ((ioc_status & MPI3_SYSIF_IOC_STATUS_SHUTDOWN_MASK) == MPI3_SYSIF_IOC_STATUS_SHUTDOWN_IN_PROGRESS) mpi3mr_dprint(sc, MPI3MR_ERROR, "shutdown still in progress after timeout\n"); } mpi3mr_dprint(sc, MPI3MR_INFO, "ioc_status/ioc_config after %s shutdown is (0x%x)/(0x%x)\n", (!retval)?"successful":"failed", ioc_status, ioc_config); } /** * mpi3mr_cleanup_ioc - Cleanup controller * @sc: Adapter instance reference * controller cleanup handler, Message unit reset or soft reset * and shutdown notification is issued to the controller. * * Return: Nothing. */ void mpi3mr_cleanup_ioc(struct mpi3mr_softc *sc) { enum mpi3mr_iocstate ioc_state; mpi3mr_dprint(sc, MPI3MR_INFO, "cleaning up the controller\n"); mpi3mr_disable_interrupts(sc); ioc_state = mpi3mr_get_iocstate(sc); if ((!sc->unrecoverable) && (!sc->reset_in_progress) && (ioc_state == MRIOC_STATE_READY)) { if (mpi3mr_mur_ioc(sc, MPI3MR_RESET_FROM_CTLR_CLEANUP)) mpi3mr_issue_reset(sc, MPI3_SYSIF_HOST_DIAG_RESET_ACTION_SOFT_RESET, MPI3MR_RESET_FROM_MUR_FAILURE); mpi3mr_issue_ioc_shutdown(sc); } mpi3mr_dprint(sc, MPI3MR_INFO, "controller cleanup completed\n"); } diff --git a/sys/dev/mpi3mr/mpi3mr_cam.c b/sys/dev/mpi3mr/mpi3mr_cam.c index da6342063e87..337ad6cb7336 100644 --- a/sys/dev/mpi3mr/mpi3mr_cam.c +++ b/sys/dev/mpi3mr/mpi3mr_cam.c @@ -1,2224 +1,2224 @@ /* * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2020-2023, Broadcom Inc. All rights reserved. * Support: * * Authors: Sumit Saxena * Chandrakanth Patil * * 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. * 3. Neither the name of the Broadcom Inc. nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing * official policies,either expressed or implied, of the FreeBSD Project. * * Mail to: Broadcom Inc 1320 Ridder Park Dr, San Jose, CA 95131 * * Broadcom Inc. (Broadcom) MPI3MR Adapter FreeBSD */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mpi/mpi30_api.h" #include "mpi3mr_cam.h" #include "mpi3mr.h" #include /* XXX for pcpu.h */ #include /* XXX for PCPU_GET */ #define smp_processor_id() PCPU_GET(cpuid) static void mpi3mr_enqueue_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cm); static void mpi3mr_map_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cm); void mpi3mr_release_simq_reinit(struct mpi3mr_cam_softc *cam_sc); static void mpi3mr_freeup_events(struct mpi3mr_softc *sc); extern int mpi3mr_register_events(struct mpi3mr_softc *sc); extern void mpi3mr_add_sg_single(void *paddr, U8 flags, U32 length, bus_addr_t dma_addr); static U32 event_count; static void mpi3mr_prepare_sgls(void *arg, bus_dma_segment_t *segs, int nsegs, int error) { struct mpi3mr_softc *sc; struct mpi3mr_cmd *cm; u_int i; bus_addr_t chain_dma; void *chain; U8 *sg_local; U32 chain_length; int sges_left; U32 sges_in_segment; U8 simple_sgl_flags; U8 simple_sgl_flags_last; U8 last_chain_sgl_flags; struct mpi3mr_chain *chain_req; Mpi3SCSIIORequest_t *scsiio_req; union ccb *ccb; cm = (struct mpi3mr_cmd *)arg; sc = cm->sc; scsiio_req = (Mpi3SCSIIORequest_t *) &cm->io_request; ccb = cm->ccb; if (error) { device_printf(sc->mpi3mr_dev, "%s: error=%d\n",__func__, error); if (error == EFBIG) { mpi3mr_set_ccbstatus(ccb, CAM_REQ_TOO_BIG); } else { mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); } mpi3mr_release_command(cm); xpt_done(ccb); return; } if (cm->data_dir == MPI3MR_READ) bus_dmamap_sync(sc->buffer_dmat, cm->dmamap, BUS_DMASYNC_PREREAD); if (cm->data_dir == MPI3MR_WRITE) bus_dmamap_sync(sc->buffer_dmat, cm->dmamap, BUS_DMASYNC_PREWRITE); KASSERT(nsegs <= MPI3MR_SG_DEPTH && nsegs > 0, ("%s: bad SGE count: %d\n", device_get_nameunit(sc->mpi3mr_dev), nsegs)); KASSERT(scsiio_req->DataLength != 0, ("%s: Data segments (%d), but DataLength == 0\n", device_get_nameunit(sc->mpi3mr_dev), nsegs)); simple_sgl_flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_SIMPLE | MPI3_SGE_FLAGS_DLAS_SYSTEM; simple_sgl_flags_last = simple_sgl_flags | MPI3_SGE_FLAGS_END_OF_LIST; last_chain_sgl_flags = MPI3_SGE_FLAGS_ELEMENT_TYPE_LAST_CHAIN | MPI3_SGE_FLAGS_DLAS_SYSTEM; sg_local = (U8 *)&scsiio_req->SGL; sges_left = nsegs; sges_in_segment = (sc->facts.op_req_sz - offsetof(Mpi3SCSIIORequest_t, SGL))/sizeof(Mpi3SGESimple_t); i = 0; mpi3mr_dprint(sc, MPI3MR_TRACE, "SGE count: %d IO size: %d\n", nsegs, scsiio_req->DataLength); if (sges_left <= sges_in_segment) goto fill_in_last_segment; /* fill in main message segment when there is a chain following */ while (sges_in_segment > 1) { mpi3mr_add_sg_single(sg_local, simple_sgl_flags, segs[i].ds_len, segs[i].ds_addr); sg_local += sizeof(Mpi3SGESimple_t); sges_left--; sges_in_segment--; i++; } chain_req = &sc->chain_sgl_list[cm->hosttag]; chain = chain_req->buf; chain_dma = chain_req->buf_phys; memset(chain_req->buf, 0, PAGE_SIZE); sges_in_segment = sges_left; chain_length = sges_in_segment * sizeof(Mpi3SGESimple_t); mpi3mr_add_sg_single(sg_local, last_chain_sgl_flags, chain_length, chain_dma); sg_local = chain; fill_in_last_segment: while (sges_left > 0) { if (sges_left == 1) mpi3mr_add_sg_single(sg_local, simple_sgl_flags_last, segs[i].ds_len, segs[i].ds_addr); else mpi3mr_add_sg_single(sg_local, simple_sgl_flags, segs[i].ds_len, segs[i].ds_addr); sg_local += sizeof(Mpi3SGESimple_t); sges_left--; i++; } /* * Now that we've created the sgls, we send the request to the device. * Unlike in Linux, dmaload isn't guaranteed to load every time, but * this function is always called when the resources are available, so * we can send the request to hardware here always. mpi3mr_map_request * knows about this quirk and will only take evasive action when an * error other than EINPROGRESS is returned from dmaload. */ mpi3mr_enqueue_request(sc, cm); return; } static void mpi3mr_map_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cm) { u_int32_t retcode = 0; union ccb *ccb; ccb = cm->ccb; if (cm->data != NULL) { mtx_lock(&sc->io_lock); /* Map data buffer into bus space */ retcode = bus_dmamap_load_ccb(sc->buffer_dmat, cm->dmamap, ccb, mpi3mr_prepare_sgls, cm, 0); mtx_unlock(&sc->io_lock); if (retcode != 0 && retcode != EINPROGRESS) { device_printf(sc->mpi3mr_dev, "bus_dmamap_load(): retcode = %d\n", retcode); /* * Any other error means prepare_sgls wasn't called, and * will never be called, so we have to mop up. This error * should never happen, though. */ mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP_ERR); mpi3mr_release_command(cm); xpt_done(ccb); } } else { /* * No data, we enqueue it directly here. */ mpi3mr_enqueue_request(sc, cm); } } void mpi3mr_unmap_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cmd) { if (cmd->data != NULL) { if (cmd->data_dir == MPI3MR_READ) bus_dmamap_sync(sc->buffer_dmat, cmd->dmamap, BUS_DMASYNC_POSTREAD); if (cmd->data_dir == MPI3MR_WRITE) bus_dmamap_sync(sc->buffer_dmat, cmd->dmamap, BUS_DMASYNC_POSTWRITE); mtx_lock(&sc->io_lock); bus_dmamap_unload(sc->buffer_dmat, cmd->dmamap); mtx_unlock(&sc->io_lock); } } /** * mpi3mr_allow_unmap_to_fw - Whether an unmap is allowed to fw * @sc: Adapter instance reference * @ccb: SCSI Command reference * * The controller hardware cannot handle certain unmap commands * for NVMe drives, this routine checks those and return true * and completes the SCSI command with proper status and sense * data. * * Return: TRUE for allowed unmap, FALSE otherwise. */ static bool mpi3mr_allow_unmap_to_fw(struct mpi3mr_softc *sc, union ccb *ccb) { struct ccb_scsiio *csio; uint16_t param_list_len, block_desc_len, trunc_param_len = 0; csio = &ccb->csio; param_list_len = (uint16_t) ((scsiio_cdb_ptr(csio)[7] << 8) | scsiio_cdb_ptr(csio)[8]); switch(pci_get_revid(sc->mpi3mr_dev)) { case SAS4116_CHIP_REV_A0: if (!param_list_len) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: CDB received with zero parameter length\n", __func__); mpi3mr_print_cdb(ccb); mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); xpt_done(ccb); return false; } if (param_list_len < 24) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: CDB received with invalid param_list_len: %d\n", __func__, param_list_len); mpi3mr_print_cdb(ccb); scsi_set_sense_data(&ccb->csio.sense_data, /*sense_format*/ SSD_TYPE_FIXED, /*current_error*/ 1, /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, /*asc*/ 0x1A, /*ascq*/ 0x00, /*extra args*/ SSD_ELEM_NONE); ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; return false; } if (param_list_len != csio->dxfer_len) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: CDB received with param_list_len: %d bufflen: %d\n", __func__, param_list_len, csio->dxfer_len); mpi3mr_print_cdb(ccb); scsi_set_sense_data(&ccb->csio.sense_data, /*sense_format*/ SSD_TYPE_FIXED, /*current_error*/ 1, /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, /*asc*/ 0x1A, /*ascq*/ 0x00, /*extra args*/ SSD_ELEM_NONE); ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; xpt_done(ccb); return false; } block_desc_len = (uint16_t) (csio->data_ptr[2] << 8 | csio->data_ptr[3]); if (block_desc_len < 16) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: Invalid descriptor length in param list: %d\n", __func__, block_desc_len); mpi3mr_print_cdb(ccb); scsi_set_sense_data(&ccb->csio.sense_data, /*sense_format*/ SSD_TYPE_FIXED, /*current_error*/ 1, /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, /*asc*/ 0x26, /*ascq*/ 0x00, /*extra args*/ SSD_ELEM_NONE); ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; xpt_done(ccb); return false; } if (param_list_len > (block_desc_len + 8)) { mpi3mr_print_cdb(ccb); mpi3mr_dprint(sc, MPI3MR_INFO, "%s: Truncating param_list_len(%d) to block_desc_len+8(%d)\n", __func__, param_list_len, (block_desc_len + 8)); param_list_len = block_desc_len + 8; scsiio_cdb_ptr(csio)[7] = (param_list_len >> 8) | 0xff; scsiio_cdb_ptr(csio)[8] = param_list_len | 0xff; mpi3mr_print_cdb(ccb); } break; case SAS4116_CHIP_REV_B0: if ((param_list_len > 24) && ((param_list_len - 8) & 0xF)) { trunc_param_len -= (param_list_len - 8) & 0xF; mpi3mr_print_cdb(ccb); mpi3mr_dprint(sc, MPI3MR_INFO, "%s: Truncating param_list_len from (%d) to (%d)\n", __func__, param_list_len, trunc_param_len); scsiio_cdb_ptr(csio)[7] = (param_list_len >> 8) | 0xff; scsiio_cdb_ptr(csio)[8] = param_list_len | 0xff; mpi3mr_print_cdb(ccb); } break; } return true; } /** * mpi3mr_tm_response_name - get TM response as a string * @resp_code: TM response code * * Convert known task management response code as a readable * string. * * Return: response code string. */ static const char* mpi3mr_tm_response_name(U8 resp_code) { char *desc; switch (resp_code) { case MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE: desc = "task management request completed"; break; case MPI3_SCSITASKMGMT_RSPCODE_INVALID_FRAME: desc = "invalid frame"; break; case MPI3_SCSITASKMGMT_RSPCODE_TM_FUNCTION_NOT_SUPPORTED: desc = "task management request not supported"; break; case MPI3_SCSITASKMGMT_RSPCODE_TM_FAILED: desc = "task management request failed"; break; case MPI3_SCSITASKMGMT_RSPCODE_TM_SUCCEEDED: desc = "task management request succeeded"; break; case MPI3_SCSITASKMGMT_RSPCODE_TM_INVALID_LUN: desc = "invalid LUN"; break; case MPI3_SCSITASKMGMT_RSPCODE_TM_OVERLAPPED_TAG: desc = "overlapped tag attempted"; break; case MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC: desc = "task queued, however not sent to target"; break; case MPI3_SCSITASKMGMT_RSPCODE_TM_NVME_DENIED: desc = "task management request denied by NVMe device"; break; default: desc = "unknown"; break; } return desc; } void mpi3mr_poll_pend_io_completions(struct mpi3mr_softc *sc) { int i; int num_of_reply_queues = sc->num_queues; struct mpi3mr_irq_context *irq_ctx; for (i = 0; i < num_of_reply_queues; i++) { irq_ctx = &sc->irq_ctx[i]; mpi3mr_complete_io_cmd(sc, irq_ctx); } } void trigger_reset_from_watchdog(struct mpi3mr_softc *sc, U8 reset_type, U16 reset_reason) { if (sc->reset_in_progress) { mpi3mr_dprint(sc, MPI3MR_INFO, "Another reset is in progress, no need to trigger the reset\n"); return; } sc->reset.type = reset_type; sc->reset.reason = reset_reason; return; } /** * mpi3mr_issue_tm - Issue Task Management request * @sc: Adapter instance reference * @tm_type: Task Management type * @handle: Device handle * @lun: lun ID * @htag: Host tag of the TM request * @timeout: TM timeout value * @drv_cmd: Internal command tracker * @resp_code: Response code place holder * @cmd: Timed out command reference * * Issues a Task Management Request to the controller for a * specified target, lun and command and wait for its completion * and check TM response. Recover the TM if it timed out by * issuing controller reset. * * Return: 0 on success, non-zero on errors */ static int mpi3mr_issue_tm(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cmd, U8 tm_type, unsigned long timeout) { int retval = 0; MPI3_SCSI_TASK_MGMT_REQUEST tm_req; MPI3_SCSI_TASK_MGMT_REPLY *tm_reply = NULL; struct mpi3mr_drvr_cmd *drv_cmd = NULL; struct mpi3mr_target *tgtdev = NULL; struct mpi3mr_op_req_queue *op_req_q = NULL; union ccb *ccb; U8 resp_code; if (sc->unrecoverable) { mpi3mr_dprint(sc, MPI3MR_INFO, "Controller is in unrecoverable state!! TM not required\n"); return retval; } if (sc->reset_in_progress) { mpi3mr_dprint(sc, MPI3MR_INFO, "controller reset in progress!! TM not required\n"); return retval; } if (!cmd->ccb) { mpi3mr_dprint(sc, MPI3MR_ERROR, "SCSIIO command timed-out with NULL ccb\n"); return retval; } ccb = cmd->ccb; tgtdev = cmd->targ; if (tgtdev == NULL) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Device does not exist target ID:0x%x," "TM is not required\n", ccb->ccb_h.target_id); return retval; } if (tgtdev->dev_removed == 1) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Device(0x%x) is removed, TM is not required\n", ccb->ccb_h.target_id); return retval; } drv_cmd = &sc->host_tm_cmds; mtx_lock(&drv_cmd->lock); memset(&tm_req, 0, sizeof(tm_req)); tm_req.DevHandle = htole16(tgtdev->dev_handle); tm_req.TaskType = tm_type; tm_req.HostTag = htole16(MPI3MR_HOSTTAG_TMS); int_to_lun(ccb->ccb_h.target_lun, tm_req.LUN); tm_req.Function = MPI3_FUNCTION_SCSI_TASK_MGMT; drv_cmd->state = MPI3MR_CMD_PENDING; drv_cmd->is_waiting = 1; drv_cmd->callback = NULL; if (ccb) { if (tm_type == MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { op_req_q = &sc->op_req_q[cmd->req_qidx]; tm_req.TaskHostTag = htole16(cmd->hosttag); tm_req.TaskRequestQueueID = htole16(op_req_q->qid); } } if (tgtdev) mpi3mr_atomic_inc(&tgtdev->block_io); if (tgtdev && (tgtdev->dev_type == MPI3_DEVICE_DEVFORM_PCIE)) { if ((tm_type == MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK) && tgtdev->dev_spec.pcie_inf.abort_to) timeout = tgtdev->dev_spec.pcie_inf.abort_to; else if ((tm_type == MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET) && tgtdev->dev_spec.pcie_inf.reset_to) timeout = tgtdev->dev_spec.pcie_inf.reset_to; } sc->tm_chan = (void *)&drv_cmd; mpi3mr_dprint(sc, MPI3MR_DEBUG_TM, "posting task management request: type(%d), handle(0x%04x)\n", tm_type, tgtdev->dev_handle); init_completion(&drv_cmd->completion); retval = mpi3mr_submit_admin_cmd(sc, &tm_req, sizeof(tm_req)); if (retval) { mpi3mr_dprint(sc, MPI3MR_ERROR, "posting task management request is failed\n"); retval = -1; goto out_unlock; } wait_for_completion_timeout_tm(&drv_cmd->completion, timeout, sc); if (!(drv_cmd->state & MPI3MR_CMD_COMPLETE)) { drv_cmd->is_waiting = 0; retval = -1; if (!(drv_cmd->state & MPI3MR_CMD_RESET)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "task management request timed out after %ld seconds\n", timeout); if (sc->mpi3mr_debug & MPI3MR_DEBUG_TM) { mpi3mr_dprint(sc, MPI3MR_INFO, "tm_request dump\n"); mpi3mr_hexdump(&tm_req, sizeof(tm_req), 8); } trigger_reset_from_watchdog(sc, MPI3MR_TRIGGER_SOFT_RESET, MPI3MR_RESET_FROM_TM_TIMEOUT); retval = ETIMEDOUT; } goto out_unlock; } if (!(drv_cmd->state & MPI3MR_CMD_REPLYVALID)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "invalid task management reply message\n"); retval = -1; goto out_unlock; } tm_reply = (MPI3_SCSI_TASK_MGMT_REPLY *)drv_cmd->reply; switch (drv_cmd->ioc_status) { case MPI3_IOCSTATUS_SUCCESS: resp_code = tm_reply->ResponseData & MPI3MR_RI_MASK_RESPCODE; break; case MPI3_IOCSTATUS_SCSI_IOC_TERMINATED: resp_code = MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE; break; default: mpi3mr_dprint(sc, MPI3MR_ERROR, "task management request to handle(0x%04x) is failed with ioc_status(0x%04x) log_info(0x%08x)\n", tgtdev->dev_handle, drv_cmd->ioc_status, drv_cmd->ioc_loginfo); retval = -1; goto out_unlock; } switch (resp_code) { case MPI3_SCSITASKMGMT_RSPCODE_TM_SUCCEEDED: case MPI3_SCSITASKMGMT_RSPCODE_TM_COMPLETE: break; case MPI3_SCSITASKMGMT_RSPCODE_IO_QUEUED_ON_IOC: if (tm_type != MPI3_SCSITASKMGMT_TASKTYPE_QUERY_TASK) retval = -1; break; default: retval = -1; break; } mpi3mr_dprint(sc, MPI3MR_DEBUG_TM, "task management request type(%d) completed for handle(0x%04x) with ioc_status(0x%04x), log_info(0x%08x)" "termination_count(%u), response:%s(0x%x)\n", tm_type, tgtdev->dev_handle, drv_cmd->ioc_status, drv_cmd->ioc_loginfo, tm_reply->TerminationCount, mpi3mr_tm_response_name(resp_code), resp_code); if (retval) goto out_unlock; mpi3mr_disable_interrupts(sc); mpi3mr_poll_pend_io_completions(sc); mpi3mr_enable_interrupts(sc); mpi3mr_poll_pend_io_completions(sc); switch (tm_type) { case MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK: if (cmd->state == MPI3MR_CMD_STATE_IN_TM) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: task abort returned success from firmware but corresponding CCB (%p) was not terminated" "marking task abort failed!\n", sc->name, cmd->ccb); retval = -1; } break; case MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET: if (mpi3mr_atomic_read(&tgtdev->outstanding)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s: target reset returned success from firmware but IOs are still pending on the target (%p)" "marking target reset failed!\n", sc->name, tgtdev); retval = -1; } break; default: break; } out_unlock: drv_cmd->state = MPI3MR_CMD_NOTUSED; mtx_unlock(&drv_cmd->lock); if (tgtdev && mpi3mr_atomic_read(&tgtdev->block_io) > 0) mpi3mr_atomic_dec(&tgtdev->block_io); return retval; } /** * mpi3mr_task_abort- Abort error handling callback * @cmd: Timed out command reference * * Issue Abort Task Management if the command is in LLD scope * and verify if it is aborted successfully and return status * accordingly. * * Return: SUCCESS of successful abort the SCSI command else FAILED */ static int mpi3mr_task_abort(struct mpi3mr_cmd *cmd) { int retval = 0; struct mpi3mr_softc *sc; union ccb *ccb; sc = cmd->sc; if (!cmd->ccb) { mpi3mr_dprint(sc, MPI3MR_ERROR, "SCSIIO command timed-out with NULL ccb\n"); return retval; } ccb = cmd->ccb; mpi3mr_dprint(sc, MPI3MR_INFO, "attempting abort task for ccb(%p)\n", ccb); mpi3mr_print_cdb(ccb); if (cmd->state != MPI3MR_CMD_STATE_BUSY) { mpi3mr_dprint(sc, MPI3MR_INFO, "%s: ccb is not in driver scope, abort task is not required\n", sc->name); return retval; } cmd->state = MPI3MR_CMD_STATE_IN_TM; retval = mpi3mr_issue_tm(sc, cmd, MPI3_SCSITASKMGMT_TASKTYPE_ABORT_TASK, MPI3MR_ABORTTM_TIMEOUT); mpi3mr_dprint(sc, MPI3MR_INFO, "abort task is %s for ccb(%p)\n", ((retval == 0) ? "SUCCESS" : "FAILED"), ccb); return retval; } /** * mpi3mr_target_reset - Target reset error handling callback * @cmd: Timed out command reference * * Issue Target reset Task Management and verify the SCSI commands are * terminated successfully and return status accordingly. * * Return: SUCCESS of successful termination of the SCSI commands else * FAILED */ static int mpi3mr_target_reset(struct mpi3mr_cmd *cmd) { int retval = 0; struct mpi3mr_softc *sc; struct mpi3mr_target *target; sc = cmd->sc; target = cmd->targ; if (target == NULL) { mpi3mr_dprint(sc, MPI3MR_XINFO, "Device does not exist for target:0x%p," "target reset is not required\n", target); return retval; } mpi3mr_dprint(sc, MPI3MR_INFO, "attempting target reset on target(%d)\n", target->per_id); if (mpi3mr_atomic_read(&target->outstanding)) { mpi3mr_dprint(sc, MPI3MR_INFO, "no outstanding IOs on the target(%d)," " target reset not required.\n", target->per_id); return retval; } retval = mpi3mr_issue_tm(sc, cmd, MPI3_SCSITASKMGMT_TASKTYPE_TARGET_RESET, MPI3MR_RESETTM_TIMEOUT); mpi3mr_dprint(sc, MPI3MR_INFO, "target reset is %s for target(%d)\n", ((retval == 0) ? "SUCCESS" : "FAILED"), target->per_id); return retval; } /** * mpi3mr_get_fw_pending_ios - Calculate pending I/O count * @sc: Adapter instance reference * * Calculate the pending I/Os for the controller and return. * * Return: Number of pending I/Os */ static inline int mpi3mr_get_fw_pending_ios(struct mpi3mr_softc *sc) { U16 i, pend_ios = 0; for (i = 0; i < sc->num_queues; i++) pend_ios += mpi3mr_atomic_read(&sc->op_reply_q[i].pend_ios); return pend_ios; } /** * mpi3mr_wait_for_host_io - block for I/Os to complete * @sc: Adapter instance reference * @timeout: time out in seconds * * Waits for pending I/Os for the given adapter to complete or * to hit the timeout. * * Return: Nothing */ static int mpi3mr_wait_for_host_io(struct mpi3mr_softc *sc, U32 timeout) { enum mpi3mr_iocstate iocstate; iocstate = mpi3mr_get_iocstate(sc); if (iocstate != MRIOC_STATE_READY) { mpi3mr_dprint(sc, MPI3MR_XINFO, "%s :Controller is in NON-READY state! Proceed with Reset\n", __func__); return -1; } if (!mpi3mr_get_fw_pending_ios(sc)) return 0; mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Waiting for %d seconds prior to reset for %d pending I/Os to complete\n", __func__, timeout, mpi3mr_get_fw_pending_ios(sc)); int i; for (i = 0; i < timeout; i++) { if (!mpi3mr_get_fw_pending_ios(sc)) { mpi3mr_dprint(sc, MPI3MR_INFO, "%s :All pending I/Os got completed while waiting! Reset not required\n", __func__); return 0; } iocstate = mpi3mr_get_iocstate(sc); if (iocstate != MRIOC_STATE_READY) { mpi3mr_dprint(sc, MPI3MR_XINFO, "%s :Controller state becomes NON-READY while waiting! dont wait further" "Proceed with Reset\n", __func__); return -1; } DELAY(1000 * 1000); } mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Pending I/Os after wait exaust is %d! Proceed with Reset\n", __func__, mpi3mr_get_fw_pending_ios(sc)); return -1; } static void mpi3mr_scsiio_timeout(void *data) { int retval = 0; struct mpi3mr_softc *sc; struct mpi3mr_cmd *cmd; struct mpi3mr_target *targ_dev = NULL; if (!data) return; cmd = (struct mpi3mr_cmd *)data; sc = cmd->sc; if (cmd->ccb == NULL) { mpi3mr_dprint(sc, MPI3MR_ERROR, "SCSIIO command timed-out with NULL ccb\n"); return; } /* * TMs are not supported for IO timeouts on VD/LD, so directly issue controller reset * with max timeout for outstanding IOs to complete is 180sec. */ targ_dev = cmd->targ; if (targ_dev && (targ_dev->dev_type == MPI3_DEVICE_DEVFORM_VD)) { if (mpi3mr_wait_for_host_io(sc, MPI3MR_RAID_ERRREC_RESET_TIMEOUT)) trigger_reset_from_watchdog(sc, MPI3MR_TRIGGER_SOFT_RESET, MPI3MR_RESET_FROM_SCSIIO_TIMEOUT); return; } /* Issue task abort to recover the timed out IO */ retval = mpi3mr_task_abort(cmd); if (!retval || (retval == ETIMEDOUT)) return; /* * task abort has failed to recover the timed out IO, * try with the target reset */ retval = mpi3mr_target_reset(cmd); if (!retval || (retval == ETIMEDOUT)) return; /* * task abort and target reset has failed. So issue Controller reset(soft reset) * through OCR thread context */ trigger_reset_from_watchdog(sc, MPI3MR_TRIGGER_SOFT_RESET, MPI3MR_RESET_FROM_SCSIIO_TIMEOUT); return; } void int_to_lun(unsigned int lun, U8 *req_lun) { int i; memset(req_lun, 0, sizeof(*req_lun)); for (i = 0; i < sizeof(lun); i += 2) { req_lun[i] = (lun >> 8) & 0xFF; req_lun[i+1] = lun & 0xFF; lun = lun >> 16; } } static U16 get_req_queue_index(struct mpi3mr_softc *sc) { U16 i = 0, reply_q_index = 0, reply_q_pend_ios = 0; reply_q_pend_ios = mpi3mr_atomic_read(&sc->op_reply_q[0].pend_ios); for (i = 0; i < sc->num_queues; i++) { if (reply_q_pend_ios > mpi3mr_atomic_read(&sc->op_reply_q[i].pend_ios)) { reply_q_pend_ios = mpi3mr_atomic_read(&sc->op_reply_q[i].pend_ios); reply_q_index = i; } } return reply_q_index; } static void mpi3mr_action_scsiio(struct mpi3mr_cam_softc *cam_sc, union ccb *ccb) { Mpi3SCSIIORequest_t *req = NULL; struct ccb_scsiio *csio; struct mpi3mr_softc *sc; struct mpi3mr_target *targ; struct mpi3mr_cmd *cm; uint8_t scsi_opcode, queue_idx; uint32_t mpi_control; sc = cam_sc->sc; mtx_assert(&sc->mpi3mr_mtx, MA_OWNED); if (sc->unrecoverable) { mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } csio = &ccb->csio; KASSERT(csio->ccb_h.target_id < cam_sc->maxtargets, ("Target %d out of bounds in XPT_SCSI_IO\n", csio->ccb_h.target_id)); scsi_opcode = scsiio_cdb_ptr(csio)[0]; if ((sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) && !((scsi_opcode == SYNCHRONIZE_CACHE) || (scsi_opcode == START_STOP_UNIT))) { mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); xpt_done(ccb); return; } targ = mpi3mr_find_target_by_per_id(cam_sc, csio->ccb_h.target_id); if (targ == NULL) { mpi3mr_dprint(sc, MPI3MR_XINFO, "Device with target ID: 0x%x does not exist\n", csio->ccb_h.target_id); mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } if (targ && targ->is_hidden) { mpi3mr_dprint(sc, MPI3MR_XINFO, "Device with target ID: 0x%x is hidden\n", csio->ccb_h.target_id); mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } if (targ->dev_removed == 1) { mpi3mr_dprint(sc, MPI3MR_XINFO, "Device with target ID: 0x%x is removed\n", csio->ccb_h.target_id); mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } if (targ->dev_handle == 0x0) { mpi3mr_dprint(sc, MPI3MR_ERROR, "%s NULL handle for target 0x%x\n", __func__, csio->ccb_h.target_id); mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); xpt_done(ccb); return; } if (mpi3mr_atomic_read(&targ->block_io) || (sc->reset_in_progress == 1) || (sc->prepare_for_reset == 1)) { mpi3mr_dprint(sc, MPI3MR_TRACE, "%s target is busy target_id: 0x%x\n", __func__, csio->ccb_h.target_id); mpi3mr_set_ccbstatus(ccb, CAM_REQUEUE_REQ); xpt_done(ccb); return; } /* * Sometimes, it is possible to get a command that is not "In * Progress" and was actually aborted by the upper layer. Check for * this here and complete the command without error. */ if (mpi3mr_get_ccbstatus(ccb) != CAM_REQ_INPROG) { mpi3mr_dprint(sc, MPI3MR_TRACE, "%s Command is not in progress for " "target %u\n", __func__, csio->ccb_h.target_id); xpt_done(ccb); return; } /* * If devinfo is 0 this will be a volume. In that case don't tell CAM * that the volume has timed out. We want volumes to be enumerated * until they are deleted/removed, not just failed. */ if (targ->flags & MPI3MRSAS_TARGET_INREMOVAL) { if (targ->devinfo == 0) mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); else mpi3mr_set_ccbstatus(ccb, CAM_SEL_TIMEOUT); xpt_done(ccb); return; } if ((scsi_opcode == UNMAP) && (pci_get_device(sc->mpi3mr_dev) == MPI3_MFGPAGE_DEVID_SAS4116) && (targ->dev_type == MPI3_DEVICE_DEVFORM_PCIE) && (mpi3mr_allow_unmap_to_fw(sc, ccb) == false)) return; cm = mpi3mr_get_command(sc); if (cm == NULL || (sc->mpi3mr_flags & MPI3MR_FLAGS_DIAGRESET)) { if (cm != NULL) { mpi3mr_release_command(cm); } if ((cam_sc->flags & MPI3MRSAS_QUEUE_FROZEN) == 0) { xpt_freeze_simq(cam_sc->sim, 1); cam_sc->flags |= MPI3MRSAS_QUEUE_FROZEN; } ccb->ccb_h.status &= ~CAM_SIM_QUEUED; mpi3mr_set_ccbstatus(ccb, CAM_REQUEUE_REQ); xpt_done(ccb); return; } switch (csio->ccb_h.flags & CAM_DIR_MASK) { case CAM_DIR_IN: mpi_control = MPI3_SCSIIO_FLAGS_DATADIRECTION_READ; cm->data_dir = MPI3MR_READ; break; case CAM_DIR_OUT: mpi_control = MPI3_SCSIIO_FLAGS_DATADIRECTION_WRITE; cm->data_dir = MPI3MR_WRITE; break; case CAM_DIR_NONE: default: mpi_control = MPI3_SCSIIO_FLAGS_DATADIRECTION_NO_DATA_TRANSFER; break; } if (csio->cdb_len > 16) mpi_control |= MPI3_SCSIIO_FLAGS_CDB_GREATER_THAN_16; req = (Mpi3SCSIIORequest_t *)&cm->io_request; bzero(req, sizeof(*req)); req->Function = MPI3_FUNCTION_SCSI_IO; req->HostTag = cm->hosttag; req->DataLength = htole32(csio->dxfer_len); req->DevHandle = htole16(targ->dev_handle); /* * It looks like the hardware doesn't require an explicit tag * number for each transaction. SAM Task Management not supported * at the moment. */ switch (csio->tag_action) { case MSG_HEAD_OF_Q_TAG: mpi_control |= MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_HEADOFQ; break; case MSG_ORDERED_Q_TAG: mpi_control |= MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_ORDEREDQ; break; case MSG_ACA_TASK: mpi_control |= MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_ACAQ; break; case CAM_TAG_ACTION_NONE: case MSG_SIMPLE_Q_TAG: default: mpi_control |= MPI3_SCSIIO_FLAGS_TASKATTRIBUTE_SIMPLEQ; break; } req->Flags = htole32(mpi_control); if (csio->ccb_h.flags & CAM_CDB_POINTER) bcopy(csio->cdb_io.cdb_ptr, &req->CDB.CDB32[0], csio->cdb_len); else { KASSERT(csio->cdb_len <= IOCDBLEN, ("cdb_len %d is greater than IOCDBLEN but CAM_CDB_POINTER " "is not set", csio->cdb_len)); bcopy(csio->cdb_io.cdb_bytes, &req->CDB.CDB32[0],csio->cdb_len); } cm->length = csio->dxfer_len; cm->targ = targ; int_to_lun(csio->ccb_h.target_lun, req->LUN); cm->ccb = ccb; csio->ccb_h.qos.sim_data = sbinuptime(); queue_idx = get_req_queue_index(sc); cm->req_qidx = queue_idx; mpi3mr_dprint(sc, MPI3MR_TRACE, "[QID:%d]: func: %s line:%d CDB: 0x%x targetid: %x SMID: 0x%x\n", (queue_idx + 1), __func__, __LINE__, scsi_opcode, csio->ccb_h.target_id, cm->hosttag); switch ((ccb->ccb_h.flags & CAM_DATA_MASK)) { case CAM_DATA_PADDR: case CAM_DATA_SG_PADDR: device_printf(sc->mpi3mr_dev, "%s: physical addresses not supported\n", __func__); mpi3mr_set_ccbstatus(ccb, CAM_REQ_INVALID); mpi3mr_release_command(cm); xpt_done(ccb); return; case CAM_DATA_SG: device_printf(sc->mpi3mr_dev, "%s: scatter gather is not supported\n", __func__); mpi3mr_set_ccbstatus(ccb, CAM_REQ_INVALID); mpi3mr_release_command(cm); xpt_done(ccb); return; case CAM_DATA_VADDR: case CAM_DATA_BIO: if (csio->dxfer_len > (MPI3MR_SG_DEPTH * MPI3MR_4K_PGSZ)) { mpi3mr_set_ccbstatus(ccb, CAM_REQ_TOO_BIG); mpi3mr_release_command(cm); xpt_done(ccb); return; } ccb->ccb_h.status |= CAM_SIM_QUEUED; cm->length = csio->dxfer_len; if (cm->length) cm->data = csio->data_ptr; break; default: mpi3mr_set_ccbstatus(ccb, CAM_REQ_INVALID); mpi3mr_release_command(cm); xpt_done(ccb); return; } /* Prepare SGEs and queue to hardware */ mpi3mr_map_request(sc, cm); } static void mpi3mr_enqueue_request(struct mpi3mr_softc *sc, struct mpi3mr_cmd *cm) { static int ratelimit; struct mpi3mr_op_req_queue *opreqq = &sc->op_req_q[cm->req_qidx]; struct mpi3mr_throttle_group_info *tg = NULL; uint32_t data_len_blks = 0; uint32_t tracked_io_sz = 0; uint32_t ioc_pend_data_len = 0, tg_pend_data_len = 0; struct mpi3mr_target *targ = cm->targ; union ccb *ccb = cm->ccb; Mpi3SCSIIORequest_t *req = (Mpi3SCSIIORequest_t *)&cm->io_request; if (sc->iot_enable) { data_len_blks = ccb->csio.dxfer_len >> 9; if ((data_len_blks >= sc->io_throttle_data_length) && targ->io_throttle_enabled) { tracked_io_sz = data_len_blks; tg = targ->throttle_group; if (tg) { mpi3mr_atomic_add(&sc->pend_large_data_sz, data_len_blks); mpi3mr_atomic_add(&tg->pend_large_data_sz, data_len_blks); ioc_pend_data_len = mpi3mr_atomic_read(&sc->pend_large_data_sz); tg_pend_data_len = mpi3mr_atomic_read(&tg->pend_large_data_sz); if (ratelimit % 1000) { mpi3mr_dprint(sc, MPI3MR_IOT, "large vd_io persist_id(%d), handle(0x%04x), data_len(%d)," "ioc_pending(%d), tg_pending(%d), ioc_high(%d), tg_high(%d)\n", targ->per_id, targ->dev_handle, data_len_blks, ioc_pend_data_len, tg_pend_data_len, sc->io_throttle_high, tg->high); ratelimit++; } if (!tg->io_divert && ((ioc_pend_data_len >= sc->io_throttle_high) || (tg_pend_data_len >= tg->high))) { tg->io_divert = 1; mpi3mr_dprint(sc, MPI3MR_IOT, "VD: Setting divert flag for tg_id(%d), persist_id(%d)\n", tg->id, targ->per_id); if (sc->mpi3mr_debug & MPI3MR_IOT) mpi3mr_print_cdb(ccb); mpi3mr_set_io_divert_for_all_vd_in_tg(sc, tg, 1); } } else { mpi3mr_atomic_add(&sc->pend_large_data_sz, data_len_blks); ioc_pend_data_len = mpi3mr_atomic_read(&sc->pend_large_data_sz); if (ratelimit % 1000) { mpi3mr_dprint(sc, MPI3MR_IOT, "large pd_io persist_id(%d), handle(0x%04x), data_len(%d), ioc_pending(%d), ioc_high(%d)\n", targ->per_id, targ->dev_handle, data_len_blks, ioc_pend_data_len, sc->io_throttle_high); ratelimit++; } if (ioc_pend_data_len >= sc->io_throttle_high) { targ->io_divert = 1; mpi3mr_dprint(sc, MPI3MR_IOT, "PD: Setting divert flag for persist_id(%d)\n", targ->per_id); if (sc->mpi3mr_debug & MPI3MR_IOT) mpi3mr_print_cdb(ccb); } } } if (targ->io_divert) { req->MsgFlags |= MPI3_SCSIIO_MSGFLAGS_DIVERT_TO_FIRMWARE; req->Flags = htole32(le32toh(req->Flags) | MPI3_SCSIIO_FLAGS_DIVERT_REASON_IO_THROTTLING); } } if (mpi3mr_submit_io(sc, opreqq, (U8 *)&cm->io_request)) { if (tracked_io_sz) { mpi3mr_atomic_sub(&sc->pend_large_data_sz, tracked_io_sz); if (tg) mpi3mr_atomic_sub(&tg->pend_large_data_sz, tracked_io_sz); } mpi3mr_set_ccbstatus(ccb, CAM_RESRC_UNAVAIL); mpi3mr_release_command(cm); xpt_done(ccb); } else { callout_reset_sbt(&cm->callout, mstosbt(ccb->ccb_h.timeout), 0, mpi3mr_scsiio_timeout, cm, 0); cm->callout_owner = true; mpi3mr_atomic_inc(&sc->fw_outstanding); mpi3mr_atomic_inc(&targ->outstanding); if (mpi3mr_atomic_read(&sc->fw_outstanding) > sc->io_cmds_highwater) sc->io_cmds_highwater++; } return; } static void mpi3mr_cam_poll(struct cam_sim *sim) { struct mpi3mr_cam_softc *cam_sc; struct mpi3mr_irq_context *irq_ctx; struct mpi3mr_softc *sc; int i; cam_sc = cam_sim_softc(sim); sc = cam_sc->sc; mpi3mr_dprint(cam_sc->sc, MPI3MR_TRACE, "func: %s line: %d is called\n", __func__, __LINE__); for (i = 0; i < sc->num_queues; i++) { irq_ctx = sc->irq_ctx + i; if (irq_ctx->op_reply_q->qid) { mpi3mr_complete_io_cmd(sc, irq_ctx); } } } static void mpi3mr_cam_action(struct cam_sim *sim, union ccb *ccb) { struct mpi3mr_cam_softc *cam_sc; struct mpi3mr_target *targ; cam_sc = cam_sim_softc(sim); mpi3mr_dprint(cam_sc->sc, MPI3MR_TRACE, "ccb func_code 0x%x target id: 0x%x\n", ccb->ccb_h.func_code, ccb->ccb_h.target_id); mtx_assert(&cam_sc->sc->mpi3mr_mtx, MA_OWNED); switch (ccb->ccb_h.func_code) { case XPT_PATH_INQ: { struct ccb_pathinq *cpi = &ccb->cpi; cpi->version_num = 1; cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; cpi->target_sprt = 0; cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED | PIM_NOSCAN; cpi->hba_eng_cnt = 0; cpi->max_target = cam_sc->maxtargets - 1; cpi->max_lun = 0; /* * initiator_id is set here to an ID outside the set of valid * target IDs (including volumes). */ cpi->initiator_id = cam_sc->maxtargets; strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); strlcpy(cpi->hba_vid, "Broadcom", HBA_IDLEN); strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); cpi->bus_id = cam_sim_bus(sim); /* * XXXSLM-I think this needs to change based on config page or * something instead of hardcoded to 150000. */ cpi->base_transfer_speed = 150000; cpi->transport = XPORT_SAS; cpi->transport_version = 0; cpi->protocol = PROTO_SCSI; cpi->protocol_version = SCSI_REV_SPC; targ = mpi3mr_find_target_by_per_id(cam_sc, ccb->ccb_h.target_id); if (targ && (targ->dev_type == MPI3_DEVICE_DEVFORM_PCIE) && ((targ->dev_spec.pcie_inf.dev_info & MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_MASK) == MPI3_DEVICE0_PCIE_DEVICE_INFO_TYPE_NVME_DEVICE)) { cpi->maxio = targ->dev_spec.pcie_inf.mdts; mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO, "PCI device target_id: %u max io size: %u\n", ccb->ccb_h.target_id, cpi->maxio); } else { cpi->maxio = PAGE_SIZE * (MPI3MR_SG_DEPTH - 1); } mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); break; } case XPT_GET_TRAN_SETTINGS: { struct ccb_trans_settings *cts; struct ccb_trans_settings_sas *sas; struct ccb_trans_settings_scsi *scsi; cts = &ccb->cts; sas = &cts->xport_specific.sas; scsi = &cts->proto_specific.scsi; KASSERT(cts->ccb_h.target_id < cam_sc->maxtargets, ("Target %d out of bounds in XPT_GET_TRAN_SETTINGS\n", cts->ccb_h.target_id)); targ = mpi3mr_find_target_by_per_id(cam_sc, cts->ccb_h.target_id); if (targ == NULL) { mpi3mr_dprint(cam_sc->sc, MPI3MR_TRACE, "Device with target ID: 0x%x does not exist\n", cts->ccb_h.target_id); mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); break; } if ((targ->dev_handle == 0x0) || (targ->dev_removed == 1)) { mpi3mr_set_ccbstatus(ccb, CAM_DEV_NOT_THERE); break; } cts->protocol_version = SCSI_REV_SPC2; cts->transport = XPORT_SAS; cts->transport_version = 0; sas->valid = CTS_SAS_VALID_SPEED; switch (targ->link_rate) { case 0x08: sas->bitrate = 150000; break; case 0x09: sas->bitrate = 300000; break; case 0x0a: sas->bitrate = 600000; break; case 0x0b: sas->bitrate = 1200000; break; default: sas->valid = 0; } cts->protocol = PROTO_SCSI; scsi->valid = CTS_SCSI_VALID_TQ; scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); break; } case XPT_CALC_GEOMETRY: cam_calc_geometry(&ccb->ccg, /*extended*/1); mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); break; case XPT_RESET_DEV: mpi3mr_dprint(cam_sc->sc, MPI3MR_INFO, "mpi3mr_action " "XPT_RESET_DEV\n"); return; case XPT_RESET_BUS: case XPT_ABORT: case XPT_TERM_IO: mpi3mr_dprint(cam_sc->sc, MPI3MR_INFO, "mpi3mr_action faking success " "for abort or reset\n"); mpi3mr_set_ccbstatus(ccb, CAM_REQ_CMP); break; case XPT_SCSI_IO: mpi3mr_action_scsiio(cam_sc, ccb); return; default: mpi3mr_set_ccbstatus(ccb, CAM_FUNC_NOTAVAIL); break; } xpt_done(ccb); } void mpi3mr_startup_increment(struct mpi3mr_cam_softc *cam_sc) { if ((cam_sc->flags & MPI3MRSAS_IN_STARTUP) != 0) { if (cam_sc->startup_refcount++ == 0) { /* just starting, freeze the simq */ mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO, "%s freezing simq\n", __func__); xpt_hold_boot(); } mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO, "%s refcount %u\n", __func__, cam_sc->startup_refcount); } } void mpi3mr_release_simq_reinit(struct mpi3mr_cam_softc *cam_sc) { if (cam_sc->flags & MPI3MRSAS_QUEUE_FROZEN) { cam_sc->flags &= ~MPI3MRSAS_QUEUE_FROZEN; xpt_release_simq(cam_sc->sim, 1); mpi3mr_dprint(cam_sc->sc, MPI3MR_INFO, "Unfreezing SIM queue\n"); } } void mpi3mr_rescan_target(struct mpi3mr_softc *sc, struct mpi3mr_target *targ) { struct mpi3mr_cam_softc *cam_sc = sc->cam_sc; path_id_t pathid; target_id_t targetid; union ccb *ccb; pathid = cam_sim_path(cam_sc->sim); if (targ == NULL) targetid = CAM_TARGET_WILDCARD; else targetid = targ->per_id; /* * Allocate a CCB and schedule a rescan. */ ccb = xpt_alloc_ccb_nowait(); if (ccb == NULL) { mpi3mr_dprint(sc, MPI3MR_ERROR, "unable to alloc CCB for rescan\n"); return; } if (xpt_create_path(&ccb->ccb_h.path, NULL, pathid, targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { mpi3mr_dprint(sc, MPI3MR_ERROR, "unable to create path for rescan\n"); xpt_free_ccb(ccb); return; } if (targetid == CAM_TARGET_WILDCARD) ccb->ccb_h.func_code = XPT_SCAN_BUS; else ccb->ccb_h.func_code = XPT_SCAN_TGT; mpi3mr_dprint(sc, MPI3MR_EVENT, "%s target id 0x%x\n", __func__, targetid); xpt_rescan(ccb); } void mpi3mr_startup_decrement(struct mpi3mr_cam_softc *cam_sc) { if ((cam_sc->flags & MPI3MRSAS_IN_STARTUP) != 0) { if (--cam_sc->startup_refcount == 0) { /* finished all discovery-related actions, release * the simq and rescan for the latest topology. */ mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO, "%s releasing simq\n", __func__); cam_sc->flags &= ~MPI3MRSAS_IN_STARTUP; xpt_release_simq(cam_sc->sim, 1); xpt_release_boot(); } mpi3mr_dprint(cam_sc->sc, MPI3MR_XINFO, "%s refcount %u\n", __func__, cam_sc->startup_refcount); } } static void mpi3mr_fw_event_free(struct mpi3mr_softc *sc, struct mpi3mr_fw_event_work *fw_event) { if (!fw_event) return; if (fw_event->event_data != NULL) { free(fw_event->event_data, M_MPI3MR); fw_event->event_data = NULL; } free(fw_event, M_MPI3MR); fw_event = NULL; } static void mpi3mr_freeup_events(struct mpi3mr_softc *sc) { struct mpi3mr_fw_event_work *fw_event = NULL; mtx_lock(&sc->mpi3mr_mtx); while ((fw_event = TAILQ_FIRST(&sc->cam_sc->ev_queue)) != NULL) { TAILQ_REMOVE(&sc->cam_sc->ev_queue, fw_event, ev_link); mpi3mr_fw_event_free(sc, fw_event); } mtx_unlock(&sc->mpi3mr_mtx); } static void mpi3mr_sastopochg_evt_debug(struct mpi3mr_softc *sc, Mpi3EventDataSasTopologyChangeList_t *event_data) { int i; U16 handle; U8 reason_code, phy_number; char *status_str = NULL; U8 link_rate, prev_link_rate; switch (event_data->ExpStatus) { case MPI3_EVENT_SAS_TOPO_ES_NOT_RESPONDING: status_str = "remove"; break; case MPI3_EVENT_SAS_TOPO_ES_RESPONDING: status_str = "responding"; break; case MPI3_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING: status_str = "remove delay"; break; case MPI3_EVENT_SAS_TOPO_ES_NO_EXPANDER: status_str = "direct attached"; break; default: status_str = "unknown status"; break; } mpi3mr_dprint(sc, MPI3MR_INFO, "%s :sas topology change: (%s)\n", __func__, status_str); mpi3mr_dprint(sc, MPI3MR_INFO, "%s :\texpander_handle(0x%04x), enclosure_handle(0x%04x) " "start_phy(%02d), num_entries(%d)\n", __func__, (event_data->ExpanderDevHandle), (event_data->EnclosureHandle), event_data->StartPhyNum, event_data->NumEntries); for (i = 0; i < event_data->NumEntries; i++) { handle = (event_data->PhyEntry[i].AttachedDevHandle); if (!handle) continue; phy_number = event_data->StartPhyNum + i; - reason_code = event_data->PhyEntry[i].Status & + reason_code = event_data->PhyEntry[i].PhyStatus & MPI3_EVENT_SAS_TOPO_PHY_RC_MASK; switch (reason_code) { case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING: status_str = "target remove"; break; case MPI3_EVENT_SAS_TOPO_PHY_RC_DELAY_NOT_RESPONDING: status_str = "delay target remove"; break; case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED: status_str = "link rate change"; break; case MPI3_EVENT_SAS_TOPO_PHY_RC_NO_CHANGE: status_str = "target responding"; break; default: status_str = "unknown"; break; } link_rate = event_data->PhyEntry[i].LinkRate >> 4; prev_link_rate = event_data->PhyEntry[i].LinkRate & 0xF; mpi3mr_dprint(sc, MPI3MR_INFO, "%s :\tphy(%02d), attached_handle(0x%04x): %s:" " link rate: new(0x%02x), old(0x%02x)\n", __func__, phy_number, handle, status_str, link_rate, prev_link_rate); } } static void mpi3mr_process_sastopochg_evt(struct mpi3mr_softc *sc, struct mpi3mr_fw_event_work *fwevt) { Mpi3EventDataSasTopologyChangeList_t *event_data = (Mpi3EventDataSasTopologyChangeList_t *)fwevt->event_data; int i; U16 handle; U8 reason_code, link_rate; struct mpi3mr_target *target = NULL; mpi3mr_sastopochg_evt_debug(sc, event_data); for (i = 0; i < event_data->NumEntries; i++) { handle = le16toh(event_data->PhyEntry[i].AttachedDevHandle); link_rate = event_data->PhyEntry[i].LinkRate >> 4; if (!handle) continue; target = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle); if (!target) continue; target->link_rate = link_rate; - reason_code = event_data->PhyEntry[i].Status & + reason_code = event_data->PhyEntry[i].PhyStatus & MPI3_EVENT_SAS_TOPO_PHY_RC_MASK; switch (reason_code) { case MPI3_EVENT_SAS_TOPO_PHY_RC_TARG_NOT_RESPONDING: if (target->exposed_to_os) mpi3mr_remove_device_from_os(sc, target->dev_handle); mpi3mr_remove_device_from_list(sc, target, false); break; case MPI3_EVENT_SAS_TOPO_PHY_RC_PHY_CHANGED: break; default: break; } } /* * refcount was incremented for this event in * mpi3mr_evt_handler. Decrement it here because the event has * been processed. */ mpi3mr_startup_decrement(sc->cam_sc); return; } static inline void mpi3mr_logdata_evt_bh(struct mpi3mr_softc *sc, struct mpi3mr_fw_event_work *fwevt) { mpi3mr_app_save_logdata(sc, fwevt->event_data, fwevt->event_data_size); } static void mpi3mr_pcietopochg_evt_debug(struct mpi3mr_softc *sc, Mpi3EventDataPcieTopologyChangeList_t *event_data) { int i; U16 handle; U16 reason_code; U8 port_number; char *status_str = NULL; U8 link_rate, prev_link_rate; switch (event_data->SwitchStatus) { case MPI3_EVENT_PCIE_TOPO_SS_NOT_RESPONDING: status_str = "remove"; break; case MPI3_EVENT_PCIE_TOPO_SS_RESPONDING: status_str = "responding"; break; case MPI3_EVENT_PCIE_TOPO_SS_DELAY_NOT_RESPONDING: status_str = "remove delay"; break; case MPI3_EVENT_PCIE_TOPO_SS_NO_PCIE_SWITCH: status_str = "direct attached"; break; default: status_str = "unknown status"; break; } mpi3mr_dprint(sc, MPI3MR_INFO, "%s :pcie topology change: (%s)\n", __func__, status_str); mpi3mr_dprint(sc, MPI3MR_INFO, "%s :\tswitch_handle(0x%04x), enclosure_handle(0x%04x)" "start_port(%02d), num_entries(%d)\n", __func__, le16toh(event_data->SwitchDevHandle), le16toh(event_data->EnclosureHandle), event_data->StartPortNum, event_data->NumEntries); for (i = 0; i < event_data->NumEntries; i++) { handle = le16toh(event_data->PortEntry[i].AttachedDevHandle); if (!handle) continue; port_number = event_data->StartPortNum + i; reason_code = event_data->PortEntry[i].PortStatus; switch (reason_code) { case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING: status_str = "target remove"; break; case MPI3_EVENT_PCIE_TOPO_PS_DELAY_NOT_RESPONDING: status_str = "delay target remove"; break; case MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED: status_str = "link rate change"; break; case MPI3_EVENT_PCIE_TOPO_PS_NO_CHANGE: status_str = "target responding"; break; default: status_str = "unknown"; break; } link_rate = event_data->PortEntry[i].CurrentPortInfo & MPI3_EVENT_PCIE_TOPO_PI_RATE_MASK; prev_link_rate = event_data->PortEntry[i].PreviousPortInfo & MPI3_EVENT_PCIE_TOPO_PI_RATE_MASK; mpi3mr_dprint(sc, MPI3MR_INFO, "%s :\tport(%02d), attached_handle(0x%04x): %s:" " link rate: new(0x%02x), old(0x%02x)\n", __func__, port_number, handle, status_str, link_rate, prev_link_rate); } } static void mpi3mr_process_pcietopochg_evt(struct mpi3mr_softc *sc, struct mpi3mr_fw_event_work *fwevt) { Mpi3EventDataPcieTopologyChangeList_t *event_data = (Mpi3EventDataPcieTopologyChangeList_t *)fwevt->event_data; int i; U16 handle; U8 reason_code, link_rate; struct mpi3mr_target *target = NULL; mpi3mr_pcietopochg_evt_debug(sc, event_data); for (i = 0; i < event_data->NumEntries; i++) { handle = le16toh(event_data->PortEntry[i].AttachedDevHandle); if (!handle) continue; target = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle); if (!target) continue; link_rate = event_data->PortEntry[i].CurrentPortInfo & MPI3_EVENT_PCIE_TOPO_PI_RATE_MASK; target->link_rate = link_rate; reason_code = event_data->PortEntry[i].PortStatus; switch (reason_code) { case MPI3_EVENT_PCIE_TOPO_PS_NOT_RESPONDING: if (target->exposed_to_os) mpi3mr_remove_device_from_os(sc, target->dev_handle); mpi3mr_remove_device_from_list(sc, target, false); break; case MPI3_EVENT_PCIE_TOPO_PS_PORT_CHANGED: break; default: break; } } /* * refcount was incremented for this event in * mpi3mr_evt_handler. Decrement it here because the event has * been processed. */ mpi3mr_startup_decrement(sc->cam_sc); return; } void mpi3mr_add_device(struct mpi3mr_softc *sc, U16 per_id) { struct mpi3mr_target *target; mpi3mr_dprint(sc, MPI3MR_EVENT, "Adding device(persistent id: 0x%x)\n", per_id); mpi3mr_startup_increment(sc->cam_sc); target = mpi3mr_find_target_by_per_id(sc->cam_sc, per_id); if (!target) { mpi3mr_dprint(sc, MPI3MR_INFO, "Not available in driver's" "internal target list, persistent_id: %d\n", per_id); goto out; } if (target->is_hidden) { mpi3mr_dprint(sc, MPI3MR_EVENT, "Target is hidden, persistent_id: %d\n", per_id); goto out; } if (!target->exposed_to_os && !sc->reset_in_progress) { mpi3mr_rescan_target(sc, target); mpi3mr_dprint(sc, MPI3MR_INFO, "Added device persistent_id: %d dev_handle: %d\n", per_id, target->dev_handle); target->exposed_to_os = 1; } out: mpi3mr_startup_decrement(sc->cam_sc); } int mpi3mr_remove_device_from_os(struct mpi3mr_softc *sc, U16 handle) { int retval = 0; struct mpi3mr_target *target; mpi3mr_dprint(sc, MPI3MR_EVENT, "Removing Device (dev_handle: %d)\n", handle); target = mpi3mr_find_target_by_dev_handle(sc->cam_sc, handle); if (!target) { mpi3mr_dprint(sc, MPI3MR_INFO, "Device (persistent_id: %d dev_handle: %d) is already removed from driver's list\n", target->per_id, handle); mpi3mr_rescan_target(sc, NULL); retval = -1; goto out; } target->flags |= MPI3MRSAS_TARGET_INREMOVAL; if (mpi3mr_atomic_read(&target->outstanding)) { mpi3mr_dprint(sc, MPI3MR_ERROR, "there are [%2d] outstanding IOs on target: %d" "Poll reply queue once\n", mpi3mr_atomic_read(&target->outstanding), target->per_id); mpi3mr_poll_pend_io_completions(sc); if (mpi3mr_atomic_read(&target->outstanding)) mpi3mr_dprint(sc, MPI3MR_ERROR, "[%2d] outstanding IOs present on target: %d" "despite poll\n", mpi3mr_atomic_read(&target->outstanding), target->per_id); } if (target->exposed_to_os && !sc->reset_in_progress) { mpi3mr_rescan_target(sc, target); mpi3mr_dprint(sc, MPI3MR_INFO, "Removed device(persistent_id: %d dev_handle: %d)\n", target->per_id, handle); target->exposed_to_os = 0; } target->flags &= ~MPI3MRSAS_TARGET_INREMOVAL; out: return retval; } void mpi3mr_remove_device_from_list(struct mpi3mr_softc *sc, struct mpi3mr_target *target, bool must_delete) { if ((must_delete == false) && (target->state != MPI3MR_DEV_REMOVE_HS_COMPLETED)) return; mtx_lock_spin(&sc->target_lock); TAILQ_REMOVE(&sc->cam_sc->tgt_list, target, tgt_next); mtx_unlock_spin(&sc->target_lock); free(target, M_MPI3MR); target = NULL; return; } /** * mpi3mr_devstatuschg_evt_bh - DevStatusChange evt bottomhalf * @sc: Adapter instance reference * @fwevt: Firmware event * * Process Device Status Change event and based on device's new * information, either expose the device to the upper layers, or * remove the device from upper layers. * * Return: Nothing. */ static void mpi3mr_devstatuschg_evt_bh(struct mpi3mr_softc *sc, struct mpi3mr_fw_event_work *fwevt) { U16 dev_handle = 0; U8 uhide = 0, delete = 0, cleanup = 0; struct mpi3mr_target *tgtdev = NULL; Mpi3EventDataDeviceStatusChange_t *evtdata = (Mpi3EventDataDeviceStatusChange_t *)fwevt->event_data; dev_handle = le16toh(evtdata->DevHandle); mpi3mr_dprint(sc, MPI3MR_INFO, "%s :device status change: handle(0x%04x): reason code(0x%x)\n", __func__, dev_handle, evtdata->ReasonCode); switch (evtdata->ReasonCode) { case MPI3_EVENT_DEV_STAT_RC_HIDDEN: delete = 1; break; case MPI3_EVENT_DEV_STAT_RC_NOT_HIDDEN: uhide = 1; break; case MPI3_EVENT_DEV_STAT_RC_VD_NOT_RESPONDING: delete = 1; cleanup = 1; break; default: mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Unhandled reason code(0x%x)\n", __func__, evtdata->ReasonCode); break; } tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, dev_handle); if (!tgtdev) return; if (uhide) { if (!tgtdev->exposed_to_os) mpi3mr_add_device(sc, tgtdev->per_id); } if (delete) mpi3mr_remove_device_from_os(sc, dev_handle); if (cleanup) mpi3mr_remove_device_from_list(sc, tgtdev, false); } /** * mpi3mr_devinfochg_evt_bh - DeviceInfoChange evt bottomhalf * @sc: Adapter instance reference * @dev_pg0: New device page0 * * Process Device Info Change event and based on device's new * information, either expose the device to the upper layers, or * remove the device from upper layers or update the details of * the device. * * Return: Nothing. */ static void mpi3mr_devinfochg_evt_bh(struct mpi3mr_softc *sc, Mpi3DevicePage0_t *dev_pg0) { struct mpi3mr_target *tgtdev = NULL; U16 dev_handle = 0, perst_id = 0; perst_id = le16toh(dev_pg0->PersistentID); dev_handle = le16toh(dev_pg0->DevHandle); mpi3mr_dprint(sc, MPI3MR_INFO, "%s :Device info change: handle(0x%04x): persist_id(0x%x)\n", __func__, dev_handle, perst_id); tgtdev = mpi3mr_find_target_by_dev_handle(sc->cam_sc, dev_handle); if (!tgtdev) return; mpi3mr_update_device(sc, tgtdev, dev_pg0, false); if (!tgtdev->is_hidden && !tgtdev->exposed_to_os) mpi3mr_add_device(sc, perst_id); if (tgtdev->is_hidden && tgtdev->exposed_to_os) mpi3mr_remove_device_from_os(sc, tgtdev->dev_handle); } static void mpi3mr_fw_work(struct mpi3mr_softc *sc, struct mpi3mr_fw_event_work *fw_event) { if (sc->mpi3mr_flags & MPI3MR_FLAGS_SHUTDOWN) goto out; if (!fw_event->process_event) goto evt_ack; mpi3mr_dprint(sc, MPI3MR_EVENT, "(%d)->(%s) Working on Event: [%x]\n", event_count++, __func__, fw_event->event); switch (fw_event->event) { case MPI3_EVENT_DEVICE_ADDED: { Mpi3DevicePage0_t *dev_pg0 = (Mpi3DevicePage0_t *) fw_event->event_data; mpi3mr_add_device(sc, dev_pg0->PersistentID); break; } case MPI3_EVENT_DEVICE_INFO_CHANGED: { mpi3mr_devinfochg_evt_bh(sc, (Mpi3DevicePage0_t *) fw_event->event_data); break; } case MPI3_EVENT_DEVICE_STATUS_CHANGE: { mpi3mr_devstatuschg_evt_bh(sc, fw_event); break; } case MPI3_EVENT_SAS_TOPOLOGY_CHANGE_LIST: { mpi3mr_process_sastopochg_evt(sc, fw_event); break; } case MPI3_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: { mpi3mr_process_pcietopochg_evt(sc, fw_event); break; } case MPI3_EVENT_LOG_DATA: { mpi3mr_logdata_evt_bh(sc, fw_event); break; } default: mpi3mr_dprint(sc, MPI3MR_TRACE,"Unhandled event 0x%0X\n", fw_event->event); break; } evt_ack: if (fw_event->send_ack) { mpi3mr_dprint(sc, MPI3MR_EVENT,"Process event ACK for event 0x%0X\n", fw_event->event); mpi3mr_process_event_ack(sc, fw_event->event, fw_event->event_context); } out: mpi3mr_dprint(sc, MPI3MR_EVENT, "(%d)->(%s) Event Free: [%x]\n", event_count, __func__, fw_event->event); mpi3mr_fw_event_free(sc, fw_event); } void mpi3mr_firmware_event_work(void *arg, int pending) { struct mpi3mr_fw_event_work *fw_event; struct mpi3mr_softc *sc; sc = (struct mpi3mr_softc *)arg; mtx_lock(&sc->fwevt_lock); while ((fw_event = TAILQ_FIRST(&sc->cam_sc->ev_queue)) != NULL) { TAILQ_REMOVE(&sc->cam_sc->ev_queue, fw_event, ev_link); mtx_unlock(&sc->fwevt_lock); mpi3mr_fw_work(sc, fw_event); mtx_lock(&sc->fwevt_lock); } mtx_unlock(&sc->fwevt_lock); } /* * mpi3mr_cam_attach - CAM layer registration * @sc: Adapter reference * * This function does simq allocation, cam registration, xpt_bus registration, * event taskqueue initialization and async event handler registration. * * Return: 0 on success and proper error codes on failure */ int mpi3mr_cam_attach(struct mpi3mr_softc *sc) { struct mpi3mr_cam_softc *cam_sc; cam_status status; int unit, error = 0, reqs; mpi3mr_dprint(sc, MPI3MR_XINFO, "Starting CAM Attach\n"); cam_sc = malloc(sizeof(struct mpi3mr_cam_softc), M_MPI3MR, M_WAITOK|M_ZERO); if (!cam_sc) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate memory for controller CAM instance\n"); return (ENOMEM); } cam_sc->maxtargets = sc->facts.max_perids + 1; TAILQ_INIT(&cam_sc->tgt_list); sc->cam_sc = cam_sc; cam_sc->sc = sc; reqs = sc->max_host_ios; if ((cam_sc->devq = cam_simq_alloc(reqs)) == NULL) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate SIMQ\n"); error = ENOMEM; goto out; } unit = device_get_unit(sc->mpi3mr_dev); cam_sc->sim = cam_sim_alloc(mpi3mr_cam_action, mpi3mr_cam_poll, "mpi3mr", cam_sc, unit, &sc->mpi3mr_mtx, reqs, reqs, cam_sc->devq); if (cam_sc->sim == NULL) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Failed to allocate SIM\n"); error = EINVAL; goto out; } TAILQ_INIT(&cam_sc->ev_queue); /* Initialize taskqueue for Event Handling */ TASK_INIT(&cam_sc->ev_task, 0, mpi3mr_firmware_event_work, sc); cam_sc->ev_tq = taskqueue_create("mpi3mr_taskq", M_NOWAIT | M_ZERO, taskqueue_thread_enqueue, &cam_sc->ev_tq); taskqueue_start_threads(&cam_sc->ev_tq, 1, PRIBIO, "%s taskq", device_get_nameunit(sc->mpi3mr_dev)); mtx_lock(&sc->mpi3mr_mtx); /* * XXX There should be a bus for every port on the adapter, but since * we're just going to fake the topology for now, we'll pretend that * everything is just a target on a single bus. */ if ((error = xpt_bus_register(cam_sc->sim, sc->mpi3mr_dev, 0)) != 0) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Error 0x%x registering SCSI bus\n", error); mtx_unlock(&sc->mpi3mr_mtx); goto out; } /* * Assume that discovery events will start right away. * * Hold off boot until discovery is complete. */ cam_sc->flags |= MPI3MRSAS_IN_STARTUP | MPI3MRSAS_IN_DISCOVERY; sc->cam_sc->startup_refcount = 0; mpi3mr_startup_increment(cam_sc); callout_init(&cam_sc->discovery_callout, 1 /*mpsafe*/); /* * Register for async events so we can determine the EEDP * capabilities of devices. */ status = xpt_create_path(&cam_sc->path, /*periph*/NULL, cam_sim_path(sc->cam_sc->sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); if (status != CAM_REQ_CMP) { mpi3mr_dprint(sc, MPI3MR_ERROR, "Error 0x%x creating sim path\n", status); cam_sc->path = NULL; } if (status != CAM_REQ_CMP) { /* * EEDP use is the exception, not the rule. * Warn the user, but do not fail to attach. */ mpi3mr_dprint(sc, MPI3MR_INFO, "EEDP capabilities disabled.\n"); } mtx_unlock(&sc->mpi3mr_mtx); error = mpi3mr_register_events(sc); out: mpi3mr_dprint(sc, MPI3MR_XINFO, "%s Exiting CAM attach, error: 0x%x n", __func__, error); return (error); } int mpi3mr_cam_detach(struct mpi3mr_softc *sc) { struct mpi3mr_cam_softc *cam_sc; struct mpi3mr_target *target; mpi3mr_dprint(sc, MPI3MR_XINFO, "%s, Starting CAM detach\n", __func__); if (sc->cam_sc == NULL) return (0); cam_sc = sc->cam_sc; mpi3mr_freeup_events(sc); /* * Drain and free the event handling taskqueue with the lock * unheld so that any parallel processing tasks drain properly * without deadlocking. */ if (cam_sc->ev_tq != NULL) taskqueue_free(cam_sc->ev_tq); mtx_lock(&sc->mpi3mr_mtx); while (cam_sc->startup_refcount != 0) mpi3mr_startup_decrement(cam_sc); /* Deregister our async handler */ if (cam_sc->path != NULL) { xpt_free_path(cam_sc->path); cam_sc->path = NULL; } if (cam_sc->flags & MPI3MRSAS_IN_STARTUP) xpt_release_simq(cam_sc->sim, 1); if (cam_sc->sim != NULL) { xpt_bus_deregister(cam_sim_path(cam_sc->sim)); cam_sim_free(cam_sc->sim, FALSE); } mtx_unlock(&sc->mpi3mr_mtx); if (cam_sc->devq != NULL) cam_simq_free(cam_sc->devq); get_target: mtx_lock_spin(&sc->target_lock); TAILQ_FOREACH(target, &cam_sc->tgt_list, tgt_next) { TAILQ_REMOVE(&sc->cam_sc->tgt_list, target, tgt_next); mtx_unlock_spin(&sc->target_lock); goto out_tgt_free; } mtx_unlock_spin(&sc->target_lock); out_tgt_free: if (target) { free(target, M_MPI3MR); target = NULL; goto get_target; } free(cam_sc, M_MPI3MR); sc->cam_sc = NULL; mpi3mr_dprint(sc, MPI3MR_XINFO, "%s, Exiting CAM detach\n", __func__); return (0); }