Index: stable/11/sys/dev/mpr/mpi/mpi2_ioc.h =================================================================== --- stable/11/sys/dev/mpr/mpi/mpi2_ioc.h (revision 315187) +++ stable/11/sys/dev/mpr/mpi/mpi2_ioc.h (revision 315188) @@ -1,1994 +1,1997 @@ /*- * Copyright (c) 2012-2015 LSI Corp. * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ /* * Copyright (c) 2000-2015 LSI Corporation. * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * * Name: mpi2_ioc.h * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages * Creation Date: October 11, 2006 * * mpi2_ioc.h Version: 02.00.27 * * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 * prefix are for use only on MPI v2.5 products, and must not be used * with MPI v2.0 products. Unless otherwise noted, names beginning with * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. * * Version History * --------------- * * Date Version Description * -------- -------- ------------------------------------------------------ * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. * 06-04-07 02.00.01 In IOCFacts Reply structure, renamed MaxDevices to * MaxTargets. * Added TotalImageSize field to FWDownload Request. * Added reserved words to FWUpload Request. * 06-26-07 02.00.02 Added IR Configuration Change List Event. * 08-31-07 02.00.03 Removed SystemReplyQueueDepth field from the IOCInit * request and replaced it with * ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth. * Replaced the MinReplyQueueDepth field of the IOCFacts * reply with MaxReplyDescriptorPostQueueDepth. * Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum * depth for the Reply Descriptor Post Queue. * Added SASAddress field to Initiator Device Table * Overflow Event data. * 10-31-07 02.00.04 Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING * for SAS Initiator Device Status Change Event data. * Modified Reason Code defines for SAS Topology Change * List Event data, including adding a bit for PHY Vacant * status, and adding a mask for the Reason Code. * Added define for * MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING. * Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID. * 12-18-07 02.00.05 Added Boot Status defines for the IOCExceptions field of * the IOCFacts Reply. * Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. * Moved MPI2_VERSION_UNION to mpi2.h. * Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks * instead of enables, and added SASBroadcastPrimitiveMasks * field. * Added Log Entry Added Event and related structure. * 02-29-08 02.00.06 Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID. * Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET. * Added MaxVolumes and MaxPersistentEntries fields to * IOCFacts reply. * Added ProtocalFlags and IOCCapabilities fields to * MPI2_FW_IMAGE_HEADER. * Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT. * 03-03-08 02.00.07 Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to * a U16 (from a U32). * Removed extra 's' from EventMasks name. * 06-27-08 02.00.08 Fixed an offset in a comment. * 10-02-08 02.00.09 Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST. * Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and * renamed MinReplyFrameSize to ReplyFrameSize. * Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX. * Added two new RAIDOperation values for Integrated RAID * Operations Status Event data. * Added four new IR Configuration Change List Event data * ReasonCode values. * Added two new ReasonCode defines for SAS Device Status * Change Event data. * Added three new DiscoveryStatus bits for the SAS * Discovery event data. * Added Multiplexing Status Change bit to the PhyStatus * field of the SAS Topology Change List event data. * Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY. * BootFlags are now product-specific. * Added defines for the indivdual signature bytes * for MPI2_INIT_IMAGE_FOOTER. * 01-19-09 02.00.10 Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define. * Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR * define. * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE * define. * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define. * 05-06-09 02.00.11 Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define. * Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define. * Added two new reason codes for SAS Device Status Change * Event. * Added new event: SAS PHY Counter. * 07-30-09 02.00.12 Added GPIO Interrupt event define and structure. * Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. * Added new product id family for 2208. * 10-28-09 02.00.13 Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST. * Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY. * Added MinDevHandle field to MPI2_IOC_FACTS_REPLY. * Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY. * Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define. * Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define. * Added Host Based Discovery Phy Event data. * Added defines for ProductID Product field * (MPI2_FW_HEADER_PID_). * Modified values for SAS ProductID Family * (MPI2_FW_HEADER_PID_FAMILY_). * 02-10-10 02.00.14 Added SAS Quiesce Event structure and defines. * Added PowerManagementControl Request structures and * defines. * 05-12-10 02.00.15 Marked Task Set Full Event as obsolete. * Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define. * 11-10-10 02.00.16 Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC. * 02-23-11 02.00.17 Added SAS NOTIFY Primitive event, and added * SASNotifyPrimitiveMasks field to * MPI2_EVENT_NOTIFICATION_REQUEST. * Added Temperature Threshold Event. * Added Host Message Event. * Added Send Host Message request and reply. * 05-25-11 02.00.18 For Extended Image Header, added * MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC and * MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC defines. * Deprecated MPI2_EXT_IMAGE_TYPE_MAX define. * 08-24-11 02.00.19 Added PhysicalPort field to * MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE structure. * Marked MPI2_PM_CONTROL_FEATURE_PCIE_LINK as obsolete. * 11-18-11 02.00.20 Incorporating additions for MPI v2.5. * 03-29-12 02.00.21 Added a product specific range to event values. * 07-26-12 02.00.22 Added MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE. * Added ElapsedSeconds field to * MPI2_EVENT_DATA_IR_OPERATION_STATUS. * 08-19-13 02.00.23 For IOCInit, added MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE * and MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY. * Added MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE. * Added MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY. * Added Encrypted Hash Extended Image. * 12-05-13 02.00.24 Added MPI25_HASH_IMAGE_TYPE_BIOS. * 11-18-14 02.00.25 Updated copyright information. * 03-16-15 02.00.26 Updated for MPI v2.6. * Added MPI2_EVENT_ACTIVE_CABLE_EXCEPTION and * MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT. * Added MPI2_EVENT_PCIE_LINK_COUNTER and * MPI26_EVENT_DATA_PCIE_LINK_COUNTER. * Added MPI26_CTRL_OP_SHUTDOWN. * Added MPI26_CTRL_OP_LINK_CLEAR_ERROR_LOG * Added MPI26_FW_HEADER_PID_FAMILY_3324_SAS * 08-25-15 02.00.27 Added IC ARCH Class based signature defines * * -------------------------------------------------------------------------- */ #ifndef MPI2_IOC_H #define MPI2_IOC_H /***************************************************************************** * * IOC Messages * *****************************************************************************/ /**************************************************************************** * IOCInit message ****************************************************************************/ /* IOCInit Request message */ typedef struct _MPI2_IOC_INIT_REQUEST { U8 WhoInit; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U16 MsgVersion; /* 0x0C */ U16 HeaderVersion; /* 0x0E */ U32 Reserved5; /* 0x10 */ U16 ConfigurationFlags; /* 0x14 */ U8 HostPageSize; /* 0x16 */ U8 HostMSIxVectors; /* 0x17 */ U16 Reserved8; /* 0x18 */ U16 SystemRequestFrameSize; /* 0x1A */ U16 ReplyDescriptorPostQueueDepth; /* 0x1C */ U16 ReplyFreeQueueDepth; /* 0x1E */ U32 SenseBufferAddressHigh; /* 0x20 */ U32 SystemReplyAddressHigh; /* 0x24 */ U64 SystemRequestFrameBaseAddress; /* 0x28 */ U64 ReplyDescriptorPostQueueAddress;/* 0x30 */ U64 ReplyFreeQueueAddress; /* 0x38 */ U64 TimeStamp; /* 0x40 */ } MPI2_IOC_INIT_REQUEST, MPI2_POINTER PTR_MPI2_IOC_INIT_REQUEST, Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t; /* WhoInit values */ #define MPI2_WHOINIT_NOT_INITIALIZED (0x00) #define MPI2_WHOINIT_SYSTEM_BIOS (0x01) #define MPI2_WHOINIT_ROM_BIOS (0x02) #define MPI2_WHOINIT_PCI_PEER (0x03) #define MPI2_WHOINIT_HOST_DRIVER (0x04) #define MPI2_WHOINIT_MANUFACTURER (0x05) /* MsgFlags */ #define MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE (0x01) /* MsgVersion */ #define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00) #define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT (8) #define MPI2_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF) #define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT (0) /* HeaderVersion */ #define MPI2_IOCINIT_HDRVERSION_UNIT_MASK (0xFF00) #define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT (8) #define MPI2_IOCINIT_HDRVERSION_DEV_MASK (0x00FF) #define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT (0) /* minimum depth for a Reply Descriptor Post Queue */ #define MPI2_RDPQ_DEPTH_MIN (16) /* Reply Descriptor Post Queue Array Entry */ typedef struct _MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY { U64 RDPQBaseAddress; /* 0x00 */ U32 Reserved1; /* 0x08 */ U32 Reserved2; /* 0x0C */ } MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY, MPI2_POINTER PTR_MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY, Mpi2IOCInitRDPQArrayEntry, MPI2_POINTER pMpi2IOCInitRDPQArrayEntry; /* IOCInit Reply message */ typedef struct _MPI2_IOC_INIT_REPLY { U8 WhoInit; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U16 Reserved5; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ } MPI2_IOC_INIT_REPLY, MPI2_POINTER PTR_MPI2_IOC_INIT_REPLY, Mpi2IOCInitReply_t, MPI2_POINTER pMpi2IOCInitReply_t; /**************************************************************************** * IOCFacts message ****************************************************************************/ /* IOCFacts Request message */ typedef struct _MPI2_IOC_FACTS_REQUEST { U16 Reserved1; /* 0x00 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ } MPI2_IOC_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_IOC_FACTS_REQUEST, Mpi2IOCFactsRequest_t, MPI2_POINTER pMpi2IOCFactsRequest_t; /* IOCFacts Reply message */ typedef struct _MPI2_IOC_FACTS_REPLY { U16 MsgVersion; /* 0x00 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U16 HeaderVersion; /* 0x04 */ U8 IOCNumber; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved1; /* 0x0A */ U16 IOCExceptions; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ U8 MaxChainDepth; /* 0x14 */ U8 WhoInit; /* 0x15 */ U8 NumberOfPorts; /* 0x16 */ U8 MaxMSIxVectors; /* 0x17 */ U16 RequestCredit; /* 0x18 */ U16 ProductID; /* 0x1A */ U32 IOCCapabilities; /* 0x1C */ MPI2_VERSION_UNION FWVersion; /* 0x20 */ U16 IOCRequestFrameSize; /* 0x24 */ U16 IOCMaxChainSegmentSize; /* 0x26 */ /* MPI 2.5 only; Reserved in MPI 2.0 */ U16 MaxInitiators; /* 0x28 */ U16 MaxTargets; /* 0x2A */ U16 MaxSasExpanders; /* 0x2C */ U16 MaxEnclosures; /* 0x2E */ U16 ProtocolFlags; /* 0x30 */ U16 HighPriorityCredit; /* 0x32 */ U16 MaxReplyDescriptorPostQueueDepth; /* 0x34 */ U8 ReplyFrameSize; /* 0x36 */ U8 MaxVolumes; /* 0x37 */ U16 MaxDevHandle; /* 0x38 */ U16 MaxPersistentEntries; /* 0x3A */ U16 MinDevHandle; /* 0x3C */ U8 CurrentHostPageSize; /* 0x3E */ U8 Reserved4; /* 0x3F */ U8 SGEModifierMask; /* 0x40 */ U8 SGEModifierValue; /* 0x41 */ U8 SGEModifierShift; /* 0x42 */ U8 Reserved5; /* 0x43 */ } MPI2_IOC_FACTS_REPLY, MPI2_POINTER PTR_MPI2_IOC_FACTS_REPLY, Mpi2IOCFactsReply_t, MPI2_POINTER pMpi2IOCFactsReply_t; /* MsgVersion */ #define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00) #define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8) #define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF) #define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT (0) /* HeaderVersion */ #define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00) #define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT (8) #define MPI2_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF) #define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0) /* IOCExceptions */ #define MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE (0x0200) #define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100) #define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x00E0) #define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD (0x0000) #define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP (0x0020) #define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED (0x0040) #define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP (0x0060) #define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010) #define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0008) #define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004) #define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002) #define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001) /* defines for WhoInit field are after the IOCInit Request */ /* ProductID field uses MPI2_FW_HEADER_PID_ */ /* IOCCapabilities */ #define MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE (0x00040000) #define MPI25_IOCFACTS_CAPABILITY_FAST_PATH_CAPABLE (0x00020000) #define MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY (0x00010000) #define MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX (0x00008000) #define MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR (0x00004000) #define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY (0x00002000) #define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID (0x00001000) #define MPI2_IOCFACTS_CAPABILITY_TLR (0x00000800) #define MPI2_IOCFACTS_CAPABILITY_MULTICAST (0x00000100) #define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET (0x00000080) #define MPI2_IOCFACTS_CAPABILITY_EEDP (0x00000040) #define MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020) #define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010) #define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008) #define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004) /* ProtocolFlags */ #define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002) #define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001) /**************************************************************************** * PortFacts message ****************************************************************************/ /* PortFacts Request message */ typedef struct _MPI2_PORT_FACTS_REQUEST { U16 Reserved1; /* 0x00 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 PortNumber; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved3; /* 0x0A */ } MPI2_PORT_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_PORT_FACTS_REQUEST, Mpi2PortFactsRequest_t, MPI2_POINTER pMpi2PortFactsRequest_t; /* PortFacts Reply message */ typedef struct _MPI2_PORT_FACTS_REPLY { U16 Reserved1; /* 0x00 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 PortNumber; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved3; /* 0x0A */ U16 Reserved4; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ U8 Reserved5; /* 0x14 */ U8 PortType; /* 0x15 */ U16 Reserved6; /* 0x16 */ U16 MaxPostedCmdBuffers; /* 0x18 */ U16 Reserved7; /* 0x1A */ } MPI2_PORT_FACTS_REPLY, MPI2_POINTER PTR_MPI2_PORT_FACTS_REPLY, Mpi2PortFactsReply_t, MPI2_POINTER pMpi2PortFactsReply_t; /* PortType values */ #define MPI2_PORTFACTS_PORTTYPE_INACTIVE (0x00) #define MPI2_PORTFACTS_PORTTYPE_FC (0x10) #define MPI2_PORTFACTS_PORTTYPE_ISCSI (0x20) #define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30) #define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31) /**************************************************************************** * PortEnable message ****************************************************************************/ /* PortEnable Request message */ typedef struct _MPI2_PORT_ENABLE_REQUEST { U16 Reserved1; /* 0x00 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U8 Reserved2; /* 0x04 */ U8 PortFlags; /* 0x05 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ } MPI2_PORT_ENABLE_REQUEST, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REQUEST, Mpi2PortEnableRequest_t, MPI2_POINTER pMpi2PortEnableRequest_t; /* PortEnable Reply message */ typedef struct _MPI2_PORT_ENABLE_REPLY { U16 Reserved1; /* 0x00 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U8 Reserved2; /* 0x04 */ U8 PortFlags; /* 0x05 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U16 Reserved5; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ } MPI2_PORT_ENABLE_REPLY, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REPLY, Mpi2PortEnableReply_t, MPI2_POINTER pMpi2PortEnableReply_t; /**************************************************************************** * EventNotification message ****************************************************************************/ /* EventNotification Request message */ #define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS (4) typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST { U16 Reserved1; /* 0x00 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U32 Reserved5; /* 0x0C */ U32 Reserved6; /* 0x10 */ U32 EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];/* 0x14 */ U16 SASBroadcastPrimitiveMasks; /* 0x24 */ U16 SASNotifyPrimitiveMasks; /* 0x26 */ U32 Reserved8; /* 0x28 */ } MPI2_EVENT_NOTIFICATION_REQUEST, MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REQUEST, Mpi2EventNotificationRequest_t, MPI2_POINTER pMpi2EventNotificationRequest_t; /* EventNotification Reply message */ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY { U16 EventDataLength; /* 0x00 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved1; /* 0x04 */ U8 AckRequired; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved2; /* 0x0A */ U16 Reserved3; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ U16 Event; /* 0x14 */ U16 Reserved4; /* 0x16 */ U32 EventContext; /* 0x18 */ U32 EventData[1]; /* 0x1C */ } MPI2_EVENT_NOTIFICATION_REPLY, MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REPLY, Mpi2EventNotificationReply_t, MPI2_POINTER pMpi2EventNotificationReply_t; /* AckRequired */ #define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00) #define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED (0x01) /* Event */ #define MPI2_EVENT_LOG_DATA (0x0001) #define MPI2_EVENT_STATE_CHANGE (0x0002) #define MPI2_EVENT_HARD_RESET_RECEIVED (0x0005) #define MPI2_EVENT_EVENT_CHANGE (0x000A) #define MPI2_EVENT_TASK_SET_FULL (0x000E) /* obsolete */ #define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE (0x000F) #define MPI2_EVENT_IR_OPERATION_STATUS (0x0014) #define MPI2_EVENT_SAS_DISCOVERY (0x0016) #define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE (0x0017) #define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x0018) #define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW (0x0019) #define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x001C) #define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x001D) #define MPI2_EVENT_IR_VOLUME (0x001E) #define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F) #define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020) #define MPI2_EVENT_LOG_ENTRY_ADDED (0x0021) #define MPI2_EVENT_SAS_PHY_COUNTER (0x0022) #define MPI2_EVENT_GPIO_INTERRUPT (0x0023) #define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY (0x0024) #define MPI2_EVENT_SAS_QUIESCE (0x0025) #define MPI2_EVENT_SAS_NOTIFY_PRIMITIVE (0x0026) #define MPI2_EVENT_TEMP_THRESHOLD (0x0027) #define MPI2_EVENT_HOST_MESSAGE (0x0028) #define MPI2_EVENT_POWER_PERFORMANCE_CHANGE (0x0029) #define MPI2_EVENT_ACTIVE_CABLE_EXCEPTION (0x0034) /* MPI v2.6 and later */ #define MPI2_EVENT_MIN_PRODUCT_SPECIFIC (0x006E) #define MPI2_EVENT_MAX_PRODUCT_SPECIFIC (0x007F) /* Log Entry Added Event data */ /* the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */ #define MPI2_EVENT_DATA_LOG_DATA_LENGTH (0x1C) typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED { U64 TimeStamp; /* 0x00 */ U32 Reserved1; /* 0x08 */ U16 LogSequence; /* 0x0C */ U16 LogEntryQualifier; /* 0x0E */ U8 VP_ID; /* 0x10 */ U8 VF_ID; /* 0x11 */ U16 Reserved2; /* 0x12 */ U8 LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH];/* 0x14 */ } MPI2_EVENT_DATA_LOG_ENTRY_ADDED, MPI2_POINTER PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED, Mpi2EventDataLogEntryAdded_t, MPI2_POINTER pMpi2EventDataLogEntryAdded_t; /* GPIO Interrupt Event data */ typedef struct _MPI2_EVENT_DATA_GPIO_INTERRUPT { U8 GPIONum; /* 0x00 */ U8 Reserved1; /* 0x01 */ U16 Reserved2; /* 0x02 */ } MPI2_EVENT_DATA_GPIO_INTERRUPT, MPI2_POINTER PTR_MPI2_EVENT_DATA_GPIO_INTERRUPT, Mpi2EventDataGpioInterrupt_t, MPI2_POINTER pMpi2EventDataGpioInterrupt_t; /* Temperature Threshold Event data */ typedef struct _MPI2_EVENT_DATA_TEMPERATURE { U16 Status; /* 0x00 */ U8 SensorNum; /* 0x02 */ U8 Reserved1; /* 0x03 */ U16 CurrentTemperature; /* 0x04 */ U16 Reserved2; /* 0x06 */ U32 Reserved3; /* 0x08 */ U32 Reserved4; /* 0x0C */ } MPI2_EVENT_DATA_TEMPERATURE, MPI2_POINTER PTR_MPI2_EVENT_DATA_TEMPERATURE, Mpi2EventDataTemperature_t, MPI2_POINTER pMpi2EventDataTemperature_t; /* Temperature Threshold Event data Status bits */ #define MPI2_EVENT_TEMPERATURE3_EXCEEDED (0x0008) #define MPI2_EVENT_TEMPERATURE2_EXCEEDED (0x0004) #define MPI2_EVENT_TEMPERATURE1_EXCEEDED (0x0002) #define MPI2_EVENT_TEMPERATURE0_EXCEEDED (0x0001) /* Host Message Event data */ typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE { U8 SourceVF_ID; /* 0x00 */ U8 Reserved1; /* 0x01 */ U16 Reserved2; /* 0x02 */ U32 Reserved3; /* 0x04 */ U32 HostData[1]; /* 0x08 */ } MPI2_EVENT_DATA_HOST_MESSAGE, MPI2_POINTER PTR_MPI2_EVENT_DATA_HOST_MESSAGE, Mpi2EventDataHostMessage_t, MPI2_POINTER pMpi2EventDataHostMessage_t; /* Power Performance Change Event data */ typedef struct _MPI2_EVENT_DATA_POWER_PERF_CHANGE { U8 CurrentPowerMode; /* 0x00 */ U8 PreviousPowerMode; /* 0x01 */ U16 Reserved1; /* 0x02 */ } MPI2_EVENT_DATA_POWER_PERF_CHANGE, MPI2_POINTER PTR_MPI2_EVENT_DATA_POWER_PERF_CHANGE, Mpi2EventDataPowerPerfChange_t, MPI2_POINTER pMpi2EventDataPowerPerfChange_t; /* defines for CurrentPowerMode and PreviousPowerMode fields */ #define MPI2_EVENT_PM_INIT_MASK (0xC0) #define MPI2_EVENT_PM_INIT_UNAVAILABLE (0x00) #define MPI2_EVENT_PM_INIT_HOST (0x40) #define MPI2_EVENT_PM_INIT_IO_UNIT (0x80) #define MPI2_EVENT_PM_INIT_PCIE_DPA (0xC0) #define MPI2_EVENT_PM_MODE_MASK (0x07) #define MPI2_EVENT_PM_MODE_UNAVAILABLE (0x00) #define MPI2_EVENT_PM_MODE_UNKNOWN (0x01) #define MPI2_EVENT_PM_MODE_FULL_POWER (0x04) #define MPI2_EVENT_PM_MODE_REDUCED_POWER (0x05) #define MPI2_EVENT_PM_MODE_STANDBY (0x06) /* Active Cable Exception Event data */ typedef struct _MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT { U32 ActiveCablePowerRequirement; /* 0x00 */ U8 ReasonCode; /* 0x04 */ U8 ReceptacleID; /* 0x05 */ U16 Reserved1; /* 0x06 */ } MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT, MPI2_POINTER PTR_MPI26_EVENT_DATA_ACTIVE_CABLE_EXCEPT, Mpi26EventDataActiveCableExcept_t, MPI2_POINTER pMpi26EventDataActiveCableExcept_t; /* defines for ReasonCode field */ -#define MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER (0x00) +#define MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER (0x00) +#define MPI26_EVENT_ACTIVE_CABLE_PRESENT (0x01) +#define MPI26_EVENT_ACTIVE_CABLE_DEGRADED (0x02) + /* Hard Reset Received Event data */ typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED { U8 Reserved1; /* 0x00 */ U8 Port; /* 0x01 */ U16 Reserved2; /* 0x02 */ } MPI2_EVENT_DATA_HARD_RESET_RECEIVED, MPI2_POINTER PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED, Mpi2EventDataHardResetReceived_t, MPI2_POINTER pMpi2EventDataHardResetReceived_t; /* Task Set Full Event data */ /* this event is obsolete */ typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL { U16 DevHandle; /* 0x00 */ U16 CurrentDepth; /* 0x02 */ } MPI2_EVENT_DATA_TASK_SET_FULL, MPI2_POINTER PTR_MPI2_EVENT_DATA_TASK_SET_FULL, Mpi2EventDataTaskSetFull_t, MPI2_POINTER pMpi2EventDataTaskSetFull_t; /* SAS Device Status Change Event data */ typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE { U16 TaskTag; /* 0x00 */ U8 ReasonCode; /* 0x02 */ U8 PhysicalPort; /* 0x03 */ U8 ASC; /* 0x04 */ U8 ASCQ; /* 0x05 */ U16 DevHandle; /* 0x06 */ U32 Reserved2; /* 0x08 */ U64 SASAddress; /* 0x0C */ U8 LUN[8]; /* 0x14 */ } MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, Mpi2EventDataSasDeviceStatusChange_t, MPI2_POINTER pMpi2EventDataSasDeviceStatusChange_t; /* SAS Device Status Change Event data ReasonCode values */ #define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) #define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) #define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08) #define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09) #define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A) #define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B) #define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C) #define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D) #define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E) #define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F) #define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE (0x10) #define MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY (0x11) #define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY (0x12) /* Integrated RAID Operation Status Event data */ typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS { U16 VolDevHandle; /* 0x00 */ U16 Reserved1; /* 0x02 */ U8 RAIDOperation; /* 0x04 */ U8 PercentComplete; /* 0x05 */ U16 Reserved2; /* 0x06 */ U32 ElapsedSeconds; /* 0x08 */ } MPI2_EVENT_DATA_IR_OPERATION_STATUS, MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS, Mpi2EventDataIrOperationStatus_t, MPI2_POINTER pMpi2EventDataIrOperationStatus_t; /* Integrated RAID Operation Status Event data RAIDOperation values */ #define MPI2_EVENT_IR_RAIDOP_RESYNC (0x00) #define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION (0x01) #define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK (0x02) #define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT (0x03) #define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT (0x04) /* Integrated RAID Volume Event data */ typedef struct _MPI2_EVENT_DATA_IR_VOLUME { U16 VolDevHandle; /* 0x00 */ U8 ReasonCode; /* 0x02 */ U8 Reserved1; /* 0x03 */ U32 NewValue; /* 0x04 */ U32 PreviousValue; /* 0x08 */ } MPI2_EVENT_DATA_IR_VOLUME, MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_VOLUME, Mpi2EventDataIrVolume_t, MPI2_POINTER pMpi2EventDataIrVolume_t; /* Integrated RAID Volume Event data ReasonCode values */ #define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED (0x01) #define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED (0x02) #define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED (0x03) /* Integrated RAID Physical Disk Event data */ typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK { U16 Reserved1; /* 0x00 */ U8 ReasonCode; /* 0x02 */ U8 PhysDiskNum; /* 0x03 */ U16 PhysDiskDevHandle; /* 0x04 */ U16 Reserved2; /* 0x06 */ U16 Slot; /* 0x08 */ U16 EnclosureHandle; /* 0x0A */ U32 NewValue; /* 0x0C */ U32 PreviousValue; /* 0x10 */ } MPI2_EVENT_DATA_IR_PHYSICAL_DISK, MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK, Mpi2EventDataIrPhysicalDisk_t, MPI2_POINTER pMpi2EventDataIrPhysicalDisk_t; /* Integrated RAID Physical Disk Event data ReasonCode values */ #define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED (0x01) #define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED (0x02) #define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED (0x03) /* Integrated RAID Configuration Change List Event data */ /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to * one and check NumElements at runtime. */ #ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT #define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT (1) #endif typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT { U16 ElementFlags; /* 0x00 */ U16 VolDevHandle; /* 0x02 */ U8 ReasonCode; /* 0x04 */ U8 PhysDiskNum; /* 0x05 */ U16 PhysDiskDevHandle; /* 0x06 */ } MPI2_EVENT_IR_CONFIG_ELEMENT, MPI2_POINTER PTR_MPI2_EVENT_IR_CONFIG_ELEMENT, Mpi2EventIrConfigElement_t, MPI2_POINTER pMpi2EventIrConfigElement_t; /* IR Configuration Change List Event data ElementFlags values */ #define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK (0x000F) #define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT (0x0000) #define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001) #define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT (0x0002) /* IR Configuration Change List Event data ReasonCode values */ #define MPI2_EVENT_IR_CHANGE_RC_ADDED (0x01) #define MPI2_EVENT_IR_CHANGE_RC_REMOVED (0x02) #define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE (0x03) #define MPI2_EVENT_IR_CHANGE_RC_HIDE (0x04) #define MPI2_EVENT_IR_CHANGE_RC_UNHIDE (0x05) #define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED (0x06) #define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED (0x07) #define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED (0x08) #define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED (0x09) typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST { U8 NumElements; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 Reserved2; /* 0x02 */ U8 ConfigNum; /* 0x03 */ U32 Flags; /* 0x04 */ MPI2_EVENT_IR_CONFIG_ELEMENT ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT]; /* 0x08 */ } MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST, MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST, Mpi2EventDataIrConfigChangeList_t, MPI2_POINTER pMpi2EventDataIrConfigChangeList_t; /* IR Configuration Change List Event data Flags values */ #define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG (0x00000001) /* SAS Discovery Event data */ typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY { U8 Flags; /* 0x00 */ U8 ReasonCode; /* 0x01 */ U8 PhysicalPort; /* 0x02 */ U8 Reserved1; /* 0x03 */ U32 DiscoveryStatus; /* 0x04 */ } MPI2_EVENT_DATA_SAS_DISCOVERY, MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DISCOVERY, Mpi2EventDataSasDiscovery_t, MPI2_POINTER pMpi2EventDataSasDiscovery_t; /* SAS Discovery Event data Flags values */ #define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE (0x02) #define MPI2_EVENT_SAS_DISC_IN_PROGRESS (0x01) /* SAS Discovery Event data ReasonCode values */ #define MPI2_EVENT_SAS_DISC_RC_STARTED (0x01) #define MPI2_EVENT_SAS_DISC_RC_COMPLETED (0x02) /* SAS Discovery Event data DiscoveryStatus values */ #define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED (0x80000000) #define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED (0x40000000) #define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED (0x20000000) #define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) #define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR (0x08000000) #define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) #define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) #define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN (0x00002000) #define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) #define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE (0x00000800) #define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK (0x00000400) #define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK (0x00000200) #define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR (0x00000100) #define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED (0x00000080) #define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST (0x00000040) #define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES (0x00000020) #define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT (0x00000010) #define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS (0x00000004) #define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE (0x00000002) #define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED (0x00000001) /* SAS Broadcast Primitive Event data */ typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE { U8 PhyNum; /* 0x00 */ U8 Port; /* 0x01 */ U8 PortWidth; /* 0x02 */ U8 Primitive; /* 0x03 */ } MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, Mpi2EventDataSasBroadcastPrimitive_t, MPI2_POINTER pMpi2EventDataSasBroadcastPrimitive_t; /* defines for the Primitive field */ #define MPI2_EVENT_PRIMITIVE_CHANGE (0x01) #define MPI2_EVENT_PRIMITIVE_SES (0x02) #define MPI2_EVENT_PRIMITIVE_EXPANDER (0x03) #define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04) #define MPI2_EVENT_PRIMITIVE_RESERVED3 (0x05) #define MPI2_EVENT_PRIMITIVE_RESERVED4 (0x06) #define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07) #define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08) /* SAS Notify Primitive Event data */ typedef struct _MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE { U8 PhyNum; /* 0x00 */ U8 Port; /* 0x01 */ U8 Reserved1; /* 0x02 */ U8 Primitive; /* 0x03 */ } MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, Mpi2EventDataSasNotifyPrimitive_t, MPI2_POINTER pMpi2EventDataSasNotifyPrimitive_t; /* defines for the Primitive field */ #define MPI2_EVENT_NOTIFY_ENABLE_SPINUP (0x01) #define MPI2_EVENT_NOTIFY_POWER_LOSS_EXPECTED (0x02) #define MPI2_EVENT_NOTIFY_RESERVED1 (0x03) #define MPI2_EVENT_NOTIFY_RESERVED2 (0x04) /* SAS Initiator Device Status Change Event data */ typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE { U8 ReasonCode; /* 0x00 */ U8 PhysicalPort; /* 0x01 */ U16 DevHandle; /* 0x02 */ U64 SASAddress; /* 0x04 */ } MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, Mpi2EventDataSasInitDevStatusChange_t, MPI2_POINTER pMpi2EventDataSasInitDevStatusChange_t; /* SAS Initiator Device Status Change event ReasonCode values */ #define MPI2_EVENT_SAS_INIT_RC_ADDED (0x01) #define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING (0x02) /* SAS Initiator Device Table Overflow Event data */ typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW { U16 MaxInit; /* 0x00 */ U16 CurrentInit; /* 0x02 */ U64 SASAddress; /* 0x04 */ } MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, Mpi2EventDataSasInitTableOverflow_t, MPI2_POINTER pMpi2EventDataSasInitTableOverflow_t; /* SAS Topology Change List Event data */ /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to * one and check NumEntries at runtime. */ #ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT #define MPI2_EVENT_SAS_TOPO_PHY_COUNT (1) #endif typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY { U16 AttachedDevHandle; /* 0x00 */ U8 LinkRate; /* 0x02 */ U8 PhyStatus; /* 0x03 */ } MPI2_EVENT_SAS_TOPO_PHY_ENTRY, MPI2_POINTER PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY, Mpi2EventSasTopoPhyEntry_t, MPI2_POINTER pMpi2EventSasTopoPhyEntry_t; typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST { U16 EnclosureHandle; /* 0x00 */ U16 ExpanderDevHandle; /* 0x02 */ U8 NumPhys; /* 0x04 */ U8 Reserved1; /* 0x05 */ U16 Reserved2; /* 0x06 */ U8 NumEntries; /* 0x08 */ U8 StartPhyNum; /* 0x09 */ U8 ExpStatus; /* 0x0A */ U8 PhysicalPort; /* 0x0B */ MPI2_EVENT_SAS_TOPO_PHY_ENTRY PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /* 0x0C*/ } MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, Mpi2EventDataSasTopologyChangeList_t, MPI2_POINTER pMpi2EventDataSasTopologyChangeList_t; /* values for the ExpStatus field */ #define MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER (0x00) #define MPI2_EVENT_SAS_TOPO_ES_ADDED (0x01) #define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02) #define MPI2_EVENT_SAS_TOPO_ES_RESPONDING (0x03) #define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04) /* defines for the LinkRate field */ #define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK (0xF0) #define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT (4) #define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK (0x0F) #define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT (0) #define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE (0x00) #define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED (0x01) #define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED (0x02) #define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03) #define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04) #define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05) #define MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY (0x06) #define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5 (0x08) #define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09) #define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A) #define MPI25_EVENT_SAS_TOPO_LR_RATE_12_0 (0x0B) /* values for the PhyStatus field */ #define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT (0x80) #define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE (0x10) /* values for the PhyStatus ReasonCode sub-field */ #define MPI2_EVENT_SAS_TOPO_RC_MASK (0x0F) #define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED (0x01) #define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING (0x02) #define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED (0x03) #define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE (0x04) #define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING (0x05) /* SAS Enclosure Device Status Change Event data */ typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE { U16 EnclosureHandle; /* 0x00 */ U8 ReasonCode; /* 0x02 */ U8 PhysicalPort; /* 0x03 */ U64 EnclosureLogicalID; /* 0x04 */ U16 NumSlots; /* 0x0C */ U16 StartSlot; /* 0x0E */ U32 PhyBits; /* 0x10 */ } MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE, MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE, Mpi2EventDataSasEnclDevStatusChange_t, MPI2_POINTER pMpi2EventDataSasEnclDevStatusChange_t; /* SAS Enclosure Device Status Change event ReasonCode values */ #define MPI2_EVENT_SAS_ENCL_RC_ADDED (0x01) #define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02) /* SAS PHY Counter Event data */ typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER { U64 TimeStamp; /* 0x00 */ U32 Reserved1; /* 0x08 */ U8 PhyEventCode; /* 0x0C */ U8 PhyNum; /* 0x0D */ U16 Reserved2; /* 0x0E */ U32 PhyEventInfo; /* 0x10 */ U8 CounterType; /* 0x14 */ U8 ThresholdWindow; /* 0x15 */ U8 TimeUnits; /* 0x16 */ U8 Reserved3; /* 0x17 */ U32 EventThreshold; /* 0x18 */ U16 ThresholdFlags; /* 0x1C */ U16 Reserved4; /* 0x1E */ } MPI2_EVENT_DATA_SAS_PHY_COUNTER, MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_PHY_COUNTER, Mpi2EventDataSasPhyCounter_t, MPI2_POINTER pMpi2EventDataSasPhyCounter_t; /* use MPI2_SASPHY3_EVENT_CODE_ values from mpi2_cnfg.h for the PhyEventCode field */ /* use MPI2_SASPHY3_COUNTER_TYPE_ values from mpi2_cnfg.h for the CounterType field */ /* use MPI2_SASPHY3_TIME_UNITS_ values from mpi2_cnfg.h for the TimeUnits field */ /* use MPI2_SASPHY3_TFLAGS_ values from mpi2_cnfg.h for the ThresholdFlags field */ /* SAS Quiesce Event data */ typedef struct _MPI2_EVENT_DATA_SAS_QUIESCE { U8 ReasonCode; /* 0x00 */ U8 Reserved1; /* 0x01 */ U16 Reserved2; /* 0x02 */ U32 Reserved3; /* 0x04 */ } MPI2_EVENT_DATA_SAS_QUIESCE, MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_QUIESCE, Mpi2EventDataSasQuiesce_t, MPI2_POINTER pMpi2EventDataSasQuiesce_t; /* SAS Quiesce Event data ReasonCode values */ #define MPI2_EVENT_SAS_QUIESCE_RC_STARTED (0x01) #define MPI2_EVENT_SAS_QUIESCE_RC_COMPLETED (0x02) /* Host Based Discovery Phy Event data */ typedef struct _MPI2_EVENT_HBD_PHY_SAS { U8 Flags; /* 0x00 */ U8 NegotiatedLinkRate; /* 0x01 */ U8 PhyNum; /* 0x02 */ U8 PhysicalPort; /* 0x03 */ U32 Reserved1; /* 0x04 */ U8 InitialFrame[28]; /* 0x08 */ } MPI2_EVENT_HBD_PHY_SAS, MPI2_POINTER PTR_MPI2_EVENT_HBD_PHY_SAS, Mpi2EventHbdPhySas_t, MPI2_POINTER pMpi2EventHbdPhySas_t; /* values for the Flags field */ #define MPI2_EVENT_HBD_SAS_FLAGS_FRAME_VALID (0x02) #define MPI2_EVENT_HBD_SAS_FLAGS_SATA_FRAME (0x01) /* use MPI2_SAS_NEG_LINK_RATE_ defines from mpi2_cnfg.h for the NegotiatedLinkRate field */ typedef union _MPI2_EVENT_HBD_DESCRIPTOR { MPI2_EVENT_HBD_PHY_SAS Sas; } MPI2_EVENT_HBD_DESCRIPTOR, MPI2_POINTER PTR_MPI2_EVENT_HBD_DESCRIPTOR, Mpi2EventHbdDescriptor_t, MPI2_POINTER pMpi2EventHbdDescriptor_t; typedef struct _MPI2_EVENT_DATA_HBD_PHY { U8 DescriptorType; /* 0x00 */ U8 Reserved1; /* 0x01 */ U16 Reserved2; /* 0x02 */ U32 Reserved3; /* 0x04 */ MPI2_EVENT_HBD_DESCRIPTOR Descriptor; /* 0x08 */ } MPI2_EVENT_DATA_HBD_PHY, MPI2_POINTER PTR_MPI2_EVENT_DATA_HBD_PHY, Mpi2EventDataHbdPhy_t, MPI2_POINTER pMpi2EventDataMpi2EventDataHbdPhy_t; /* values for the DescriptorType field */ #define MPI2_EVENT_HBD_DT_SAS (0x01) /**************************************************************************** * EventAck message ****************************************************************************/ /* EventAck Request message */ typedef struct _MPI2_EVENT_ACK_REQUEST { U16 Reserved1; /* 0x00 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U16 Event; /* 0x0C */ U16 Reserved5; /* 0x0E */ U32 EventContext; /* 0x10 */ } MPI2_EVENT_ACK_REQUEST, MPI2_POINTER PTR_MPI2_EVENT_ACK_REQUEST, Mpi2EventAckRequest_t, MPI2_POINTER pMpi2EventAckRequest_t; /* EventAck Reply message */ typedef struct _MPI2_EVENT_ACK_REPLY { U16 Reserved1; /* 0x00 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U16 Reserved5; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ } MPI2_EVENT_ACK_REPLY, MPI2_POINTER PTR_MPI2_EVENT_ACK_REPLY, Mpi2EventAckReply_t, MPI2_POINTER pMpi2EventAckReply_t; /**************************************************************************** * SendHostMessage message ****************************************************************************/ /* SendHostMessage Request message */ typedef struct _MPI2_SEND_HOST_MESSAGE_REQUEST { U16 HostDataLength; /* 0x00 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved1; /* 0x04 */ U8 Reserved2; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved3; /* 0x0A */ U8 Reserved4; /* 0x0C */ U8 DestVF_ID; /* 0x0D */ U16 Reserved5; /* 0x0E */ U32 Reserved6; /* 0x10 */ U32 Reserved7; /* 0x14 */ U32 Reserved8; /* 0x18 */ U32 Reserved9; /* 0x1C */ U32 Reserved10; /* 0x20 */ U32 HostData[1]; /* 0x24 */ } MPI2_SEND_HOST_MESSAGE_REQUEST, MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REQUEST, Mpi2SendHostMessageRequest_t, MPI2_POINTER pMpi2SendHostMessageRequest_t; /* SendHostMessage Reply message */ typedef struct _MPI2_SEND_HOST_MESSAGE_REPLY { U16 HostDataLength; /* 0x00 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved1; /* 0x04 */ U8 Reserved2; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved3; /* 0x0A */ U16 Reserved4; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ } MPI2_SEND_HOST_MESSAGE_REPLY, MPI2_POINTER PTR_MPI2_SEND_HOST_MESSAGE_REPLY, Mpi2SendHostMessageReply_t, MPI2_POINTER pMpi2SendHostMessageReply_t; /**************************************************************************** * FWDownload message ****************************************************************************/ /* MPI v2.0 FWDownload Request message */ typedef struct _MPI2_FW_DOWNLOAD_REQUEST { U8 ImageType; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U32 TotalImageSize; /* 0x0C */ U32 Reserved5; /* 0x10 */ MPI2_MPI_SGE_UNION SGL; /* 0x14 */ } MPI2_FW_DOWNLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REQUEST, Mpi2FWDownloadRequest, MPI2_POINTER pMpi2FWDownloadRequest; #define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01) #define MPI2_FW_DOWNLOAD_ITYPE_FW (0x01) #define MPI2_FW_DOWNLOAD_ITYPE_BIOS (0x02) #define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06) #define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07) #define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08) #define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09) #define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A) #define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) #define MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY (0x0C) /* MPI v2.5 and newer */ #define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0) /* MPI v2.0 FWDownload TransactionContext Element */ typedef struct _MPI2_FW_DOWNLOAD_TCSGE { U8 Reserved1; /* 0x00 */ U8 ContextSize; /* 0x01 */ U8 DetailsLength; /* 0x02 */ U8 Flags; /* 0x03 */ U32 Reserved2; /* 0x04 */ U32 ImageOffset; /* 0x08 */ U32 ImageSize; /* 0x0C */ } MPI2_FW_DOWNLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_TCSGE, Mpi2FWDownloadTCSGE_t, MPI2_POINTER pMpi2FWDownloadTCSGE_t; /* MPI v2.5 FWDownload Request message */ typedef struct _MPI25_FW_DOWNLOAD_REQUEST { U8 ImageType; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U32 TotalImageSize; /* 0x0C */ U32 Reserved5; /* 0x10 */ U32 Reserved6; /* 0x14 */ U32 ImageOffset; /* 0x18 */ U32 ImageSize; /* 0x1C */ MPI25_SGE_IO_UNION SGL; /* 0x20 */ } MPI25_FW_DOWNLOAD_REQUEST, MPI2_POINTER PTR_MPI25_FW_DOWNLOAD_REQUEST, Mpi25FWDownloadRequest, MPI2_POINTER pMpi25FWDownloadRequest; /* FWDownload Reply message */ typedef struct _MPI2_FW_DOWNLOAD_REPLY { U8 ImageType; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U16 Reserved5; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ } MPI2_FW_DOWNLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REPLY, Mpi2FWDownloadReply_t, MPI2_POINTER pMpi2FWDownloadReply_t; /**************************************************************************** * FWUpload message ****************************************************************************/ /* MPI v2.0 FWUpload Request message */ typedef struct _MPI2_FW_UPLOAD_REQUEST { U8 ImageType; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U32 Reserved5; /* 0x0C */ U32 Reserved6; /* 0x10 */ MPI2_MPI_SGE_UNION SGL; /* 0x14 */ } MPI2_FW_UPLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REQUEST, Mpi2FWUploadRequest_t, MPI2_POINTER pMpi2FWUploadRequest_t; #define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT (0x00) #define MPI2_FW_UPLOAD_ITYPE_FW_FLASH (0x01) #define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02) #define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP (0x05) #define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING (0x06) #define MPI2_FW_UPLOAD_ITYPE_CONFIG_1 (0x07) #define MPI2_FW_UPLOAD_ITYPE_CONFIG_2 (0x08) #define MPI2_FW_UPLOAD_ITYPE_MEGARAID (0x09) #define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A) #define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) #define MPI2_FW_UPLOAD_ITYPE_CBB_BACKUP (0x0D) /* MPI v2.0 FWUpload TransactionContext Element */ typedef struct _MPI2_FW_UPLOAD_TCSGE { U8 Reserved1; /* 0x00 */ U8 ContextSize; /* 0x01 */ U8 DetailsLength; /* 0x02 */ U8 Flags; /* 0x03 */ U32 Reserved2; /* 0x04 */ U32 ImageOffset; /* 0x08 */ U32 ImageSize; /* 0x0C */ } MPI2_FW_UPLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_UPLOAD_TCSGE, Mpi2FWUploadTCSGE_t, MPI2_POINTER pMpi2FWUploadTCSGE_t; /* MPI v2.5 FWUpload Request message */ typedef struct _MPI25_FW_UPLOAD_REQUEST { U8 ImageType; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U32 Reserved5; /* 0x0C */ U32 Reserved6; /* 0x10 */ U32 Reserved7; /* 0x14 */ U32 ImageOffset; /* 0x18 */ U32 ImageSize; /* 0x1C */ MPI25_SGE_IO_UNION SGL; /* 0x20 */ } MPI25_FW_UPLOAD_REQUEST, MPI2_POINTER PTR_MPI25_FW_UPLOAD_REQUEST, Mpi25FWUploadRequest_t, MPI2_POINTER pMpi25FWUploadRequest_t; /* FWUpload Reply message */ typedef struct _MPI2_FW_UPLOAD_REPLY { U8 ImageType; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U16 Reserved5; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ U32 ActualImageSize; /* 0x14 */ } MPI2_FW_UPLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REPLY, Mpi2FWUploadReply_t, MPI2_POINTER pMPi2FWUploadReply_t; /* FW Image Header */ typedef struct _MPI2_FW_IMAGE_HEADER { U32 Signature; /* 0x00 */ U32 Signature0; /* 0x04 */ U32 Signature1; /* 0x08 */ U32 Signature2; /* 0x0C */ MPI2_VERSION_UNION MPIVersion; /* 0x10 */ MPI2_VERSION_UNION FWVersion; /* 0x14 */ MPI2_VERSION_UNION NVDATAVersion; /* 0x18 */ MPI2_VERSION_UNION PackageVersion; /* 0x1C */ U16 VendorID; /* 0x20 */ U16 ProductID; /* 0x22 */ U16 ProtocolFlags; /* 0x24 */ U16 Reserved26; /* 0x26 */ U32 IOCCapabilities; /* 0x28 */ U32 ImageSize; /* 0x2C */ U32 NextImageHeaderOffset; /* 0x30 */ U32 Checksum; /* 0x34 */ U32 Reserved38; /* 0x38 */ U32 Reserved3C; /* 0x3C */ U32 Reserved40; /* 0x40 */ U32 Reserved44; /* 0x44 */ U32 Reserved48; /* 0x48 */ U32 Reserved4C; /* 0x4C */ U32 Reserved50; /* 0x50 */ U32 Reserved54; /* 0x54 */ U32 Reserved58; /* 0x58 */ U32 Reserved5C; /* 0x5C */ U32 BootFlags; /* 0x60 */ /* reserved in MPI v2.5 and earlier */ U32 FirmwareVersionNameWhat; /* 0x64 */ U8 FirmwareVersionName[32]; /* 0x68 */ U32 VendorNameWhat; /* 0x88 */ U8 VendorName[32]; /* 0x8C */ U32 PackageNameWhat; /* 0x88 */ U8 PackageName[32]; /* 0x8C */ U32 ReservedD0; /* 0xD0 */ U32 ReservedD4; /* 0xD4 */ U32 ReservedD8; /* 0xD8 */ U32 ReservedDC; /* 0xDC */ U32 ReservedE0; /* 0xE0 */ U32 ReservedE4; /* 0xE4 */ U32 ReservedE8; /* 0xE8 */ U32 ReservedEC; /* 0xEC */ U32 ReservedF0; /* 0xF0 */ U32 ReservedF4; /* 0xF4 */ U32 ReservedF8; /* 0xF8 */ U32 ReservedFC; /* 0xFC */ } MPI2_FW_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_FW_IMAGE_HEADER, Mpi2FWImageHeader_t, MPI2_POINTER pMpi2FWImageHeader_t; /* Signature field */ #define MPI2_FW_HEADER_SIGNATURE_OFFSET (0x00) #define MPI2_FW_HEADER_SIGNATURE_MASK (0xFF000000) #define MPI2_FW_HEADER_SIGNATURE (0xEA000000) #define MPI26_FW_HEADER_SIGNATURE (0xEB000000) /* Signature0 field */ #define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04) #define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A) #define MPI26_FW_HEADER_SIGNATURE0_BASE (0x5AEAA500) /* Last byte is defined by architecture */ #define MPI26_FW_HEADER_SIGNATURE0_ARC_0 (0x5A) #define MPI26_FW_HEADER_SIGNATURE0_ARC_1 (0x00) #define MPI26_FW_HEADER_SIGNATURE0_ARC_2 (0x01) #define MPI26_FW_HEADER_SIGNATURE0 (MPI26_FW_HEADER_SIGNATURE0_BASE+MPI26_FW_HEADER_SIGNATURE0_ARC_0) // legacy (0x5AEAA55A) #define MPI26_FW_HEADER_SIGNATURE0_3516 (MPI26_FW_HEADER_SIGNATURE0_BASE+MPI26_FW_HEADER_SIGNATURE0_ARC_1) /* Signature1 field */ #define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08) #define MPI2_FW_HEADER_SIGNATURE1 (0xA55AFAA5) #define MPI26_FW_HEADER_SIGNATURE1 (0xA55AEAA5) /* Signature2 field */ #define MPI2_FW_HEADER_SIGNATURE2_OFFSET (0x0C) #define MPI2_FW_HEADER_SIGNATURE2 (0x5AA55AFA) #define MPI26_FW_HEADER_SIGNATURE2 (0x5AA55AEA) /* defines for using the ProductID field */ #define MPI2_FW_HEADER_PID_TYPE_MASK (0xF000) #define MPI2_FW_HEADER_PID_TYPE_SAS (0x2000) #define MPI2_FW_HEADER_PID_PROD_MASK (0x0F00) #define MPI2_FW_HEADER_PID_PROD_A (0x0000) #define MPI2_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI (0x0200) #define MPI2_FW_HEADER_PID_PROD_IR_SCSI (0x0700) #define MPI2_FW_HEADER_PID_FAMILY_MASK (0x00FF) /* SAS ProductID Family bits */ #define MPI2_FW_HEADER_PID_FAMILY_2108_SAS (0x0013) #define MPI2_FW_HEADER_PID_FAMILY_2208_SAS (0x0014) #define MPI25_FW_HEADER_PID_FAMILY_3108_SAS (0x0021) #define MPI26_FW_HEADER_PID_FAMILY_3324_SAS (0x0028) #define MPI26_FW_HEADER_PID_FAMILY_3516_SAS (0x0031) /* use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */ /* use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */ #define MPI2_FW_HEADER_IMAGESIZE_OFFSET (0x2C) #define MPI2_FW_HEADER_NEXTIMAGE_OFFSET (0x30) #define MPI26_FW_HEADER_BOOTFLAGS_OFFSET (0x60) #define MPI2_FW_HEADER_VERNMHWAT_OFFSET (0x64) #define MPI2_FW_HEADER_WHAT_SIGNATURE (0x29232840) #define MPI2_FW_HEADER_SIZE (0x100) /* Extended Image Header */ typedef struct _MPI2_EXT_IMAGE_HEADER { U8 ImageType; /* 0x00 */ U8 Reserved1; /* 0x01 */ U16 Reserved2; /* 0x02 */ U32 Checksum; /* 0x04 */ U32 ImageSize; /* 0x08 */ U32 NextImageHeaderOffset; /* 0x0C */ U32 PackageVersion; /* 0x10 */ U32 Reserved3; /* 0x14 */ U32 Reserved4; /* 0x18 */ U32 Reserved5; /* 0x1C */ U8 IdentifyString[32]; /* 0x20 */ } MPI2_EXT_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_EXT_IMAGE_HEADER, Mpi2ExtImageHeader_t, MPI2_POINTER pMpi2ExtImageHeader_t; /* useful offsets */ #define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET (0x00) #define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET (0x08) #define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET (0x0C) #define MPI2_EXT_IMAGE_HEADER_SIZE (0x40) /* defines for the ImageType field */ #define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) #define MPI2_EXT_IMAGE_TYPE_FW (0x01) #define MPI2_EXT_IMAGE_TYPE_NVDATA (0x03) #define MPI2_EXT_IMAGE_TYPE_BOOTLOADER (0x04) #define MPI2_EXT_IMAGE_TYPE_INITIALIZATION (0x05) #define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT (0x06) #define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07) #define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08) #define MPI2_EXT_IMAGE_TYPE_ENCRYPTED_HASH (0x09) /* MPI v2.5 and newer */ #define MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC (0x80) #define MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC (0xFF) #define MPI2_EXT_IMAGE_TYPE_MAX (MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC) /* deprecated */ /* FLASH Layout Extended Image Data */ /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to * one and check RegionsPerLayout at runtime. */ #ifndef MPI2_FLASH_NUMBER_OF_REGIONS #define MPI2_FLASH_NUMBER_OF_REGIONS (1) #endif /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to * one and check NumberOfLayouts at runtime. */ #ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS #define MPI2_FLASH_NUMBER_OF_LAYOUTS (1) #endif typedef struct _MPI2_FLASH_REGION { U8 RegionType; /* 0x00 */ U8 Reserved1; /* 0x01 */ U16 Reserved2; /* 0x02 */ U32 RegionOffset; /* 0x04 */ U32 RegionSize; /* 0x08 */ U32 Reserved3; /* 0x0C */ } MPI2_FLASH_REGION, MPI2_POINTER PTR_MPI2_FLASH_REGION, Mpi2FlashRegion_t, MPI2_POINTER pMpi2FlashRegion_t; typedef struct _MPI2_FLASH_LAYOUT { U32 FlashSize; /* 0x00 */ U32 Reserved1; /* 0x04 */ U32 Reserved2; /* 0x08 */ U32 Reserved3; /* 0x0C */ MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS];/* 0x10 */ } MPI2_FLASH_LAYOUT, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT, Mpi2FlashLayout_t, MPI2_POINTER pMpi2FlashLayout_t; typedef struct _MPI2_FLASH_LAYOUT_DATA { U8 ImageRevision; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 SizeOfRegion; /* 0x02 */ U8 Reserved2; /* 0x03 */ U16 NumberOfLayouts; /* 0x04 */ U16 RegionsPerLayout; /* 0x06 */ U16 MinimumSectorAlignment; /* 0x08 */ U16 Reserved3; /* 0x0A */ U32 Reserved4; /* 0x0C */ MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS];/* 0x10 */ } MPI2_FLASH_LAYOUT_DATA, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT_DATA, Mpi2FlashLayoutData_t, MPI2_POINTER pMpi2FlashLayoutData_t; /* defines for the RegionType field */ #define MPI2_FLASH_REGION_UNUSED (0x00) #define MPI2_FLASH_REGION_FIRMWARE (0x01) #define MPI2_FLASH_REGION_BIOS (0x02) #define MPI2_FLASH_REGION_NVDATA (0x03) #define MPI2_FLASH_REGION_FIRMWARE_BACKUP (0x05) #define MPI2_FLASH_REGION_MFG_INFORMATION (0x06) #define MPI2_FLASH_REGION_CONFIG_1 (0x07) #define MPI2_FLASH_REGION_CONFIG_2 (0x08) #define MPI2_FLASH_REGION_MEGARAID (0x09) #define MPI2_FLASH_REGION_COMMON_BOOT_BLOCK (0x0A) #define MPI2_FLASH_REGION_INIT (MPI2_FLASH_REGION_COMMON_BOOT_BLOCK) /* older name */ #define MPI2_FLASH_REGION_CBB_BACKUP (0x0D) /* ImageRevision */ #define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00) /* Supported Devices Extended Image Data */ /* * Host code (drivers, BIOS, utilities, etc.) should leave this define set to * one and check NumberOfDevices at runtime. */ #ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES #define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES (1) #endif typedef struct _MPI2_SUPPORTED_DEVICE { U16 DeviceID; /* 0x00 */ U16 VendorID; /* 0x02 */ U16 DeviceIDMask; /* 0x04 */ U16 Reserved1; /* 0x06 */ U8 LowPCIRev; /* 0x08 */ U8 HighPCIRev; /* 0x09 */ U16 Reserved2; /* 0x0A */ U32 Reserved3; /* 0x0C */ } MPI2_SUPPORTED_DEVICE, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICE, Mpi2SupportedDevice_t, MPI2_POINTER pMpi2SupportedDevice_t; typedef struct _MPI2_SUPPORTED_DEVICES_DATA { U8 ImageRevision; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 NumberOfDevices; /* 0x02 */ U8 Reserved2; /* 0x03 */ U32 Reserved3; /* 0x04 */ MPI2_SUPPORTED_DEVICE SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES]; /* 0x08 */ } MPI2_SUPPORTED_DEVICES_DATA, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICES_DATA, Mpi2SupportedDevicesData_t, MPI2_POINTER pMpi2SupportedDevicesData_t; /* ImageRevision */ #define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION (0x00) /* Init Extended Image Data */ typedef struct _MPI2_INIT_IMAGE_FOOTER { U32 BootFlags; /* 0x00 */ U32 ImageSize; /* 0x04 */ U32 Signature0; /* 0x08 */ U32 Signature1; /* 0x0C */ U32 Signature2; /* 0x10 */ U32 ResetVector; /* 0x14 */ } MPI2_INIT_IMAGE_FOOTER, MPI2_POINTER PTR_MPI2_INIT_IMAGE_FOOTER, Mpi2InitImageFooter_t, MPI2_POINTER pMpi2InitImageFooter_t; /* defines for the BootFlags field */ #define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET (0x00) /* defines for the ImageSize field */ #define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET (0x04) /* defines for the Signature0 field */ #define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET (0x08) #define MPI2_INIT_IMAGE_SIGNATURE0 (0x5AA55AEA) /* defines for the Signature1 field */ #define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET (0x0C) #define MPI2_INIT_IMAGE_SIGNATURE1 (0xA55AEAA5) /* defines for the Signature2 field */ #define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET (0x10) #define MPI2_INIT_IMAGE_SIGNATURE2 (0x5AEAA55A) /* Signature fields as individual bytes */ #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0 (0xEA) #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1 (0x5A) #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2 (0xA5) #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3 (0x5A) #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4 (0xA5) #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5 (0xEA) #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6 (0x5A) #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7 (0xA5) #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8 (0x5A) #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9 (0xA5) #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A (0xEA) #define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B (0x5A) /* defines for the ResetVector field */ #define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET (0x14) /* Encrypted Hash Extended Image Data */ typedef struct _MPI25_ENCRYPTED_HASH_ENTRY { U8 HashImageType; /* 0x00 */ U8 HashAlgorithm; /* 0x01 */ U8 EncryptionAlgorithm; /* 0x02 */ U8 Reserved1; /* 0x03 */ U32 Reserved2; /* 0x04 */ U32 EncryptedHash[1]; /* 0x08 */ /* variable length */ } MPI25_ENCRYPTED_HASH_ENTRY, MPI2_POINTER PTR_MPI25_ENCRYPTED_HASH_ENTRY, Mpi25EncryptedHashEntry_t, MPI2_POINTER pMpi25EncryptedHashEntry_t; /* values for HashImageType */ #define MPI25_HASH_IMAGE_TYPE_UNUSED (0x00) #define MPI25_HASH_IMAGE_TYPE_FIRMWARE (0x01) #define MPI25_HASH_IMAGE_TYPE_BIOS (0x02) /* values for HashAlgorithm */ #define MPI25_HASH_ALGORITHM_UNUSED (0x00) #define MPI25_HASH_ALGORITHM_SHA256 (0x01) /* values for EncryptionAlgorithm */ #define MPI25_ENCRYPTION_ALG_UNUSED (0x00) #define MPI25_ENCRYPTION_ALG_RSA256 (0x01) typedef struct _MPI25_ENCRYPTED_HASH_DATA { U8 ImageVersion; /* 0x00 */ U8 NumHash; /* 0x01 */ U16 Reserved1; /* 0x02 */ U32 Reserved2; /* 0x04 */ MPI25_ENCRYPTED_HASH_ENTRY EncryptedHashEntry[1]; /* 0x08 */ /* variable number of entries */ } MPI25_ENCRYPTED_HASH_DATA, MPI2_POINTER PTR_MPI25_ENCRYPTED_HASH_DATA, Mpi25EncryptedHashData_t, MPI2_POINTER pMpi25EncryptedHashData_t; /**************************************************************************** * PowerManagementControl message ****************************************************************************/ /* PowerManagementControl Request message */ typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST { U8 Feature; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U8 Parameter1; /* 0x0C */ U8 Parameter2; /* 0x0D */ U8 Parameter3; /* 0x0E */ U8 Parameter4; /* 0x0F */ U32 Reserved5; /* 0x10 */ U32 Reserved6; /* 0x14 */ } MPI2_PWR_MGMT_CONTROL_REQUEST, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REQUEST, Mpi2PwrMgmtControlRequest_t, MPI2_POINTER pMpi2PwrMgmtControlRequest_t; /* defines for the Feature field */ #define MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND (0x01) #define MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION (0x02) #define MPI2_PM_CONTROL_FEATURE_PCIE_LINK (0x03) /* obsolete */ #define MPI2_PM_CONTROL_FEATURE_IOC_SPEED (0x04) #define MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE (0x05) /* reserved in MPI 2.0 */ #define MPI2_PM_CONTROL_FEATURE_MIN_PRODUCT_SPECIFIC (0x80) #define MPI2_PM_CONTROL_FEATURE_MAX_PRODUCT_SPECIFIC (0xFF) /* parameter usage for the MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND Feature */ /* Parameter1 contains a PHY number */ /* Parameter2 indicates power condition action using these defines */ #define MPI2_PM_CONTROL_PARAM2_PARTIAL (0x01) #define MPI2_PM_CONTROL_PARAM2_SLUMBER (0x02) #define MPI2_PM_CONTROL_PARAM2_EXIT_PWR_MGMT (0x03) /* Parameter3 and Parameter4 are reserved */ /* parameter usage for the MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION Feature */ /* Parameter1 contains SAS port width modulation group number */ /* Parameter2 indicates IOC action using these defines */ #define MPI2_PM_CONTROL_PARAM2_REQUEST_OWNERSHIP (0x01) #define MPI2_PM_CONTROL_PARAM2_CHANGE_MODULATION (0x02) #define MPI2_PM_CONTROL_PARAM2_RELINQUISH_OWNERSHIP (0x03) /* Parameter3 indicates desired modulation level using these defines */ #define MPI2_PM_CONTROL_PARAM3_25_PERCENT (0x00) #define MPI2_PM_CONTROL_PARAM3_50_PERCENT (0x01) #define MPI2_PM_CONTROL_PARAM3_75_PERCENT (0x02) #define MPI2_PM_CONTROL_PARAM3_100_PERCENT (0x03) /* Parameter4 is reserved */ /* this next set (_PCIE_LINK) is obsolete */ /* parameter usage for the MPI2_PM_CONTROL_FEATURE_PCIE_LINK Feature */ /* Parameter1 indicates desired PCIe link speed using these defines */ #define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS (0x00) /* obsolete */ #define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS (0x01) /* obsolete */ #define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS (0x02) /* obsolete */ /* Parameter2 indicates desired PCIe link width using these defines */ #define MPI2_PM_CONTROL_PARAM2_WIDTH_X1 (0x01) /* obsolete */ #define MPI2_PM_CONTROL_PARAM2_WIDTH_X2 (0x02) /* obsolete */ #define MPI2_PM_CONTROL_PARAM2_WIDTH_X4 (0x04) /* obsolete */ #define MPI2_PM_CONTROL_PARAM2_WIDTH_X8 (0x08) /* obsolete */ /* Parameter3 and Parameter4 are reserved */ /* parameter usage for the MPI2_PM_CONTROL_FEATURE_IOC_SPEED Feature */ /* Parameter1 indicates desired IOC hardware clock speed using these defines */ #define MPI2_PM_CONTROL_PARAM1_FULL_IOC_SPEED (0x01) #define MPI2_PM_CONTROL_PARAM1_HALF_IOC_SPEED (0x02) #define MPI2_PM_CONTROL_PARAM1_QUARTER_IOC_SPEED (0x04) #define MPI2_PM_CONTROL_PARAM1_EIGHTH_IOC_SPEED (0x08) /* Parameter2, Parameter3, and Parameter4 are reserved */ /* parameter usage for the MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE Feature */ /* Parameter1 indicates host action regarding global power management mode */ #define MPI2_PM_CONTROL_PARAM1_TAKE_CONTROL (0x01) #define MPI2_PM_CONTROL_PARAM1_CHANGE_GLOBAL_MODE (0x02) #define MPI2_PM_CONTROL_PARAM1_RELEASE_CONTROL (0x03) /* Parameter2 indicates the requested global power management mode */ #define MPI2_PM_CONTROL_PARAM2_FULL_PWR_PERF (0x01) #define MPI2_PM_CONTROL_PARAM2_REDUCED_PWR_PERF (0x08) #define MPI2_PM_CONTROL_PARAM2_STANDBY (0x40) /* Parameter3 and Parameter4 are reserved */ /* PowerManagementControl Reply message */ typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY { U8 Feature; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U16 Reserved2; /* 0x04 */ U8 Reserved3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved4; /* 0x0A */ U16 Reserved5; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ } MPI2_PWR_MGMT_CONTROL_REPLY, MPI2_POINTER PTR_MPI2_PWR_MGMT_CONTROL_REPLY, Mpi2PwrMgmtControlReply_t, MPI2_POINTER pMpi2PwrMgmtControlReply_t; /**************************************************************************** * IO Unit Control messages (MPI v2.6 and later only.) ****************************************************************************/ /* IO Unit Control Request Message */ typedef struct _MPI26_IOUNIT_CONTROL_REQUEST { U8 Operation; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U16 DevHandle; /* 0x04 */ U8 IOCParameter; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved3; /* 0x0A */ U16 Reserved4; /* 0x0C */ U8 PhyNum; /* 0x0E */ U8 PrimFlags; /* 0x0F */ U32 Primitive; /* 0x10 */ U8 LookupMethod; /* 0x14 */ U8 Reserved5; /* 0x15 */ U16 SlotNumber; /* 0x16 */ U64 LookupAddress; /* 0x18 */ U32 IOCParameterValue; /* 0x20 */ U32 Reserved7; /* 0x24 */ U32 Reserved8; /* 0x28 */ } MPI26_IOUNIT_CONTROL_REQUEST, MPI2_POINTER PTR_MPI26_IOUNIT_CONTROL_REQUEST, Mpi26IoUnitControlRequest_t, MPI2_POINTER pMpi26IoUnitControlRequest_t; /* values for the Operation field */ #define MPI26_CTRL_OP_CLEAR_ALL_PERSISTENT (0x02) #define MPI26_CTRL_OP_SAS_PHY_LINK_RESET (0x06) #define MPI26_CTRL_OP_SAS_PHY_HARD_RESET (0x07) #define MPI26_CTRL_OP_PHY_CLEAR_ERROR_LOG (0x08) #define MPI26_CTRL_OP_LINK_CLEAR_ERROR_LOG (0x09) #define MPI26_CTRL_OP_SAS_SEND_PRIMITIVE (0x0A) #define MPI26_CTRL_OP_FORCE_FULL_DISCOVERY (0x0B) #define MPI26_CTRL_OP_REMOVE_DEVICE (0x0D) #define MPI26_CTRL_OP_LOOKUP_MAPPING (0x0E) #define MPI26_CTRL_OP_SET_IOC_PARAMETER (0x0F) #define MPI26_CTRL_OP_ENABLE_FP_DEVICE (0x10) #define MPI26_CTRL_OP_DISABLE_FP_DEVICE (0x11) #define MPI26_CTRL_OP_ENABLE_FP_ALL (0x12) #define MPI26_CTRL_OP_DISABLE_FP_ALL (0x13) #define MPI26_CTRL_OP_DEV_ENABLE_NCQ (0x14) #define MPI26_CTRL_OP_DEV_DISABLE_NCQ (0x15) #define MPI26_CTRL_OP_SHUTDOWN (0x16) #define MPI26_CTRL_OP_DEV_ENABLE_PERSIST_CONNECTION (0x17) #define MPI26_CTRL_OP_DEV_DISABLE_PERSIST_CONNECTION (0x18) #define MPI26_CTRL_OP_DEV_CLOSE_PERSIST_CONNECTION (0x19) #define MPI26_CTRL_OP_PRODUCT_SPECIFIC_MIN (0x80) /* values for the PrimFlags field */ #define MPI26_CTRL_PRIMFLAGS_SINGLE (0x08) #define MPI26_CTRL_PRIMFLAGS_TRIPLE (0x02) #define MPI26_CTRL_PRIMFLAGS_REDUNDANT (0x01) /* values for the LookupMethod field */ #define MPI26_CTRL_LOOKUP_METHOD_WWID_ADDRESS (0x01) #define MPI26_CTRL_LOOKUP_METHOD_ENCLOSURE_SLOT (0x02) #define MPI26_CTRL_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03) /* IO Unit Control Reply Message */ typedef struct _MPI26_IOUNIT_CONTROL_REPLY { U8 Operation; /* 0x00 */ U8 Reserved1; /* 0x01 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U16 DevHandle; /* 0x04 */ U8 IOCParameter; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved3; /* 0x0A */ U16 Reserved4; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ } MPI26_IOUNIT_CONTROL_REPLY, MPI2_POINTER PTR_MPI26_IOUNIT_CONTROL_REPLY, Mpi26IoUnitControlReply_t, MPI2_POINTER pMpi26IoUnitControlReply_t; #endif Index: stable/11/sys/dev/mpr/mpr_sas_lsi.c =================================================================== --- stable/11/sys/dev/mpr/mpr_sas_lsi.c (revision 315187) +++ stable/11/sys/dev/mpr/mpr_sas_lsi.c (revision 315188) @@ -1,1411 +1,1423 @@ /*- * Copyright (c) 2011-2015 LSI Corp. * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ #include __FBSDID("$FreeBSD$"); /* Communications core for Avago Technologies (LSI) MPT3 */ /* TODO Move headers to mprvar */ #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 #include #include #include #include #include #include #include #include #include /* For Hashed SAS Address creation for SATA Drives */ #define MPT2SAS_SN_LEN 20 #define MPT2SAS_MN_LEN 40 struct mpr_fw_event_work { u16 event; void *event_data; TAILQ_ENTRY(mpr_fw_event_work) ev_link; }; union _sata_sas_address { u8 wwid[8]; struct { u32 high; u32 low; } word; }; /* * define the IDENTIFY DEVICE structure */ struct _ata_identify_device_data { u16 reserved1[10]; /* 0-9 */ u16 serial_number[10]; /* 10-19 */ u16 reserved2[7]; /* 20-26 */ u16 model_number[20]; /* 27-46*/ u16 reserved3[170]; /* 47-216 */ u16 rotational_speed; /* 217 */ u16 reserved4[38]; /* 218-255 */ }; static u32 event_count; static void mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event); static void mprsas_fw_event_free(struct mpr_softc *, struct mpr_fw_event_work *); static int mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate); static int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo); static void mprsas_ata_id_timeout(void *data); int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD); static int mprsas_volume_add(struct mpr_softc *sc, u16 handle); static void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc); static void mprsas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb); void mprsas_evt_handler(struct mpr_softc *sc, uintptr_t data, MPI2_EVENT_NOTIFICATION_REPLY *event) { struct mpr_fw_event_work *fw_event; u16 sz; mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); mpr_print_evt_sas(sc, event); mprsas_record_event(sc, event); fw_event = malloc(sizeof(struct mpr_fw_event_work), M_MPR, M_ZERO|M_NOWAIT); if (!fw_event) { printf("%s: allocate failed for fw_event\n", __func__); return; } sz = le16toh(event->EventDataLength) * 4; fw_event->event_data = malloc(sz, M_MPR, M_ZERO|M_NOWAIT); if (!fw_event->event_data) { printf("%s: allocate failed for event_data\n", __func__); free(fw_event, M_MPR); return; } bcopy(event->EventData, fw_event->event_data, sz); fw_event->event = event->Event; if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || event->Event == MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE || event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) && sc->track_mapping_events) sc->pending_map_events++; /* * When wait_for_port_enable flag is set, make sure that all the events * are processed. Increment the startup_refcount and decrement it after * events are processed. */ if ((event->Event == MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || event->Event == MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST) && sc->wait_for_port_enable) mprsas_startup_increment(sc->sassc); TAILQ_INSERT_TAIL(&sc->sassc->ev_queue, fw_event, ev_link); taskqueue_enqueue(sc->sassc->ev_tq, &sc->sassc->ev_task); } static void mprsas_fw_event_free(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) { free(fw_event->event_data, M_MPR); free(fw_event, M_MPR); } /** * _mpr_fw_work - delayed task for processing firmware events * @sc: per adapter object * @fw_event: The fw_event_work object * Context: user. * * Return nothing. */ static void mprsas_fw_work(struct mpr_softc *sc, struct mpr_fw_event_work *fw_event) { struct mprsas_softc *sassc; sassc = sc->sassc; mpr_dprint(sc, MPR_EVENT, "(%d)->(%s) Working on Event: [%x]\n", event_count++, __func__, fw_event->event); switch (fw_event->event) { case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: { MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data; MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy; int i; data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *) fw_event->event_data; mpr_mapping_topology_change_event(sc, fw_event->event_data); for (i = 0; i < data->NumEntries; i++) { phy = &data->PHY[i]; switch (phy->PhyStatus & MPI2_EVENT_SAS_TOPO_RC_MASK) { case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: if (mprsas_add_device(sc, le16toh(phy->AttachedDevHandle), phy->LinkRate)) { printf("%s: failed to add device with " "handle 0x%x\n", __func__, le16toh(phy->AttachedDevHandle)); mprsas_prepare_remove(sassc, le16toh( phy->AttachedDevHandle)); } break; case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: mprsas_prepare_remove(sassc, le16toh( phy->AttachedDevHandle)); break; case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE: case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING: default: break; } } /* * refcount was incremented for this event in * mprsas_evt_handler. Decrement it here because the event has * been processed. */ mprsas_startup_decrement(sassc); break; } case MPI2_EVENT_SAS_DISCOVERY: { MPI2_EVENT_DATA_SAS_DISCOVERY *data; data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)fw_event->event_data; if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_STARTED) mpr_dprint(sc, MPR_TRACE,"SAS discovery start event\n"); if (data->ReasonCode & MPI2_EVENT_SAS_DISC_RC_COMPLETED) { mpr_dprint(sc, MPR_TRACE,"SAS discovery stop event\n"); sassc->flags &= ~MPRSAS_IN_DISCOVERY; mprsas_discovery_end(sassc); } break; } case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: { Mpi2EventDataSasEnclDevStatusChange_t *data; data = (Mpi2EventDataSasEnclDevStatusChange_t *) fw_event->event_data; mpr_mapping_enclosure_dev_status_change_event(sc, fw_event->event_data); break; } case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: { Mpi2EventIrConfigElement_t *element; int i; u8 foreign_config, reason; u16 elementType; Mpi2EventDataIrConfigChangeList_t *event_data; struct mprsas_target *targ; unsigned int id; event_data = fw_event->event_data; foreign_config = (le32toh(event_data->Flags) & MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; id = mpr_mapping_get_raid_id_from_handle(sc, element->VolDevHandle); mpr_mapping_ir_config_change_event(sc, event_data); for (i = 0; i < event_data->NumElements; i++, element++) { reason = element->ReasonCode; elementType = le16toh(element->ElementFlags) & MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK; /* * check for element type of Phys Disk or Hot Spare */ if ((elementType != MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT) && (elementType != MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT)) // do next element goto skip_fp_send; /* * check for reason of Hide, Unhide, PD Created, or PD * Deleted */ if ((reason != MPI2_EVENT_IR_CHANGE_RC_HIDE) && (reason != MPI2_EVENT_IR_CHANGE_RC_UNHIDE) && (reason != MPI2_EVENT_IR_CHANGE_RC_PD_CREATED) && (reason != MPI2_EVENT_IR_CHANGE_RC_PD_DELETED)) goto skip_fp_send; // check for a reason of Hide or PD Created if ((reason == MPI2_EVENT_IR_CHANGE_RC_HIDE) || (reason == MPI2_EVENT_IR_CHANGE_RC_PD_CREATED)) { // build RAID Action message Mpi2RaidActionRequest_t *action; Mpi2RaidActionReply_t *reply; struct mpr_command *cm; int error = 0; if ((cm = mpr_alloc_command(sc)) == NULL) { printf("%s: command alloc failed\n", __func__); return; } mpr_dprint(sc, MPR_EVENT, "Sending FP action " "from " "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST " ":\n"); action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req; action->Function = MPI2_FUNCTION_RAID_ACTION; action->Action = MPI2_RAID_ACTION_PHYSDISK_HIDDEN; action->PhysDiskNum = element->PhysDiskNum; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; error = mpr_request_polled(sc, cm); reply = (Mpi2RaidActionReply_t *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* * If the poll returns error then we * need to do diag reset */ printf("%s: poll for page completed " "with error %d", __func__, error); } if (reply && (le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) { mpr_dprint(sc, MPR_ERROR, "%s: error " "sending RaidActionPage; " "iocstatus = 0x%x\n", __func__, le16toh(reply->IOCStatus)); } if (cm) mpr_free_command(sc, cm); } skip_fp_send: mpr_dprint(sc, MPR_EVENT, "Received " "MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST Reason " "code %x:\n", element->ReasonCode); switch (element->ReasonCode) { case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: case MPI2_EVENT_IR_CHANGE_RC_ADDED: if (!foreign_config) { if (mprsas_volume_add(sc, le16toh(element->VolDevHandle))) { printf("%s: failed to add RAID " "volume with handle 0x%x\n", __func__, le16toh(element-> VolDevHandle)); } } break; case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: case MPI2_EVENT_IR_CHANGE_RC_REMOVED: /* * Rescan after volume is deleted or removed. */ if (!foreign_config) { if (id == MPR_MAP_BAD_ID) { printf("%s: could not get ID " "for volume with handle " "0x%04x\n", __func__, le16toh(element-> VolDevHandle)); break; } targ = &sassc->targets[id]; targ->handle = 0x0; targ->encl_slot = 0x0; targ->encl_handle = 0x0; targ->encl_level_valid = 0x0; targ->encl_level = 0x0; targ->connector_name[0] = ' '; targ->connector_name[1] = ' '; targ->connector_name[2] = ' '; targ->connector_name[3] = ' '; targ->exp_dev_handle = 0x0; targ->phy_num = 0x0; targ->linkrate = 0x0; mprsas_rescan_target(sc, targ); printf("RAID target id 0x%x removed\n", targ->tid); } break; case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: case MPI2_EVENT_IR_CHANGE_RC_HIDE: /* * Phys Disk of a volume has been created. Hide * it from the OS. */ targ = mprsas_find_target_by_handle(sassc, 0, element->PhysDiskDevHandle); if (targ == NULL) break; targ->flags |= MPR_TARGET_FLAGS_RAID_COMPONENT; mprsas_rescan_target(sc, targ); break; case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: /* * Phys Disk of a volume has been deleted. * Expose it to the OS. */ if (mprsas_add_device(sc, le16toh(element->PhysDiskDevHandle), 0)) { printf("%s: failed to add device with " "handle 0x%x\n", __func__, le16toh(element-> PhysDiskDevHandle)); mprsas_prepare_remove(sassc, le16toh(element-> PhysDiskDevHandle)); } break; } } /* * refcount was incremented for this event in * mprsas_evt_handler. Decrement it here because the event has * been processed. */ mprsas_startup_decrement(sassc); break; } case MPI2_EVENT_IR_VOLUME: { Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; /* * Informational only. */ mpr_dprint(sc, MPR_EVENT, "Received IR Volume event:\n"); switch (event_data->ReasonCode) { case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED: mpr_dprint(sc, MPR_EVENT, " Volume Settings " "changed from 0x%x to 0x%x for Volome with " "handle 0x%x", le32toh(event_data->PreviousValue), le32toh(event_data->NewValue), le16toh(event_data->VolDevHandle)); break; case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED: mpr_dprint(sc, MPR_EVENT, " Volume Status " "changed from 0x%x to 0x%x for Volome with " "handle 0x%x", le32toh(event_data->PreviousValue), le32toh(event_data->NewValue), le16toh(event_data->VolDevHandle)); break; case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED: mpr_dprint(sc, MPR_EVENT, " Volume State " "changed from 0x%x to 0x%x for Volome with " "handle 0x%x", le32toh(event_data->PreviousValue), le32toh(event_data->NewValue), le16toh(event_data->VolDevHandle)); u32 state; struct mprsas_target *targ; state = le32toh(event_data->NewValue); switch (state) { case MPI2_RAID_VOL_STATE_MISSING: case MPI2_RAID_VOL_STATE_FAILED: mprsas_prepare_volume_remove(sassc, event_data->VolDevHandle); break; case MPI2_RAID_VOL_STATE_ONLINE: case MPI2_RAID_VOL_STATE_DEGRADED: case MPI2_RAID_VOL_STATE_OPTIMAL: targ = mprsas_find_target_by_handle(sassc, 0, event_data->VolDevHandle); if (targ) { printf("%s %d: Volume handle " "0x%x is already added \n", __func__, __LINE__, event_data->VolDevHandle); break; } if (mprsas_volume_add(sc, le16toh(event_data-> VolDevHandle))) { printf("%s: failed to add RAID " "volume with handle 0x%x\n", __func__, le16toh( event_data->VolDevHandle)); } break; default: break; } break; default: break; } break; } case MPI2_EVENT_IR_PHYSICAL_DISK: { Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; struct mprsas_target *targ; /* * Informational only. */ mpr_dprint(sc, MPR_EVENT, "Received IR Phys Disk event:\n"); switch (event_data->ReasonCode) { case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED: mpr_dprint(sc, MPR_EVENT, " Phys Disk Settings " "changed from 0x%x to 0x%x for Phys Disk Number " "%d and handle 0x%x at Enclosure handle 0x%x, Slot " "%d", le32toh(event_data->PreviousValue), le32toh(event_data->NewValue), event_data->PhysDiskNum, le16toh(event_data->PhysDiskDevHandle), le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot)); break; case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED: mpr_dprint(sc, MPR_EVENT, " Phys Disk Status changed " "from 0x%x to 0x%x for Phys Disk Number %d and " "handle 0x%x at Enclosure handle 0x%x, Slot %d", le32toh(event_data->PreviousValue), le32toh(event_data->NewValue), event_data->PhysDiskNum, le16toh(event_data->PhysDiskDevHandle), le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot)); break; case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED: mpr_dprint(sc, MPR_EVENT, " Phys Disk State changed " "from 0x%x to 0x%x for Phys Disk Number %d and " "handle 0x%x at Enclosure handle 0x%x, Slot %d", le32toh(event_data->PreviousValue), le32toh(event_data->NewValue), event_data->PhysDiskNum, le16toh(event_data->PhysDiskDevHandle), le16toh(event_data->EnclosureHandle), le16toh(event_data->Slot)); switch (event_data->NewValue) { case MPI2_RAID_PD_STATE_ONLINE: case MPI2_RAID_PD_STATE_DEGRADED: case MPI2_RAID_PD_STATE_REBUILDING: case MPI2_RAID_PD_STATE_OPTIMAL: case MPI2_RAID_PD_STATE_HOT_SPARE: targ = mprsas_find_target_by_handle( sassc, 0, event_data->PhysDiskDevHandle); if (targ) { targ->flags |= MPR_TARGET_FLAGS_RAID_COMPONENT; printf("%s %d: Found Target " "for handle 0x%x.\n", __func__, __LINE__ , event_data-> PhysDiskDevHandle); } break; case MPI2_RAID_PD_STATE_OFFLINE: case MPI2_RAID_PD_STATE_NOT_CONFIGURED: case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: default: targ = mprsas_find_target_by_handle( sassc, 0, event_data->PhysDiskDevHandle); if (targ) { targ->flags |= ~MPR_TARGET_FLAGS_RAID_COMPONENT; printf("%s %d: Found Target " "for handle 0x%x. \n", __func__, __LINE__ , event_data-> PhysDiskDevHandle); } break; } default: break; } break; } case MPI2_EVENT_IR_OPERATION_STATUS: { Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data; /* * Informational only. */ mpr_dprint(sc, MPR_EVENT, "Received IR Op Status event:\n"); mpr_dprint(sc, MPR_EVENT, " RAID Operation of %d is %d " "percent complete for Volume with handle 0x%x", event_data->RAIDOperation, event_data->PercentComplete, le16toh(event_data->VolDevHandle)); break; } case MPI2_EVENT_TEMP_THRESHOLD: { pMpi2EventDataTemperature_t temp_event; temp_event = (pMpi2EventDataTemperature_t)fw_event->event_data; /* * The Temp Sensor Count must be greater than the event's Sensor * Num to be valid. If valid, print the temp thresholds that * have been exceeded. */ if (sc->iounit_pg8.NumSensors > temp_event->SensorNum) { mpr_dprint(sc, MPR_FAULT, "Temperature Threshold flags " "%s %s %s %s exceeded for Sensor: %d !!!\n", ((temp_event->Status & 0x01) == 1) ? "0 " : " ", ((temp_event->Status & 0x02) == 2) ? "1 " : " ", ((temp_event->Status & 0x04) == 4) ? "2 " : " ", ((temp_event->Status & 0x08) == 8) ? "3 " : " ", temp_event->SensorNum); mpr_dprint(sc, MPR_FAULT, "Current Temp in Celsius: " "%d\n", temp_event->CurrentTemperature); } break; } case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION: { pMpi26EventDataActiveCableExcept_t ace_event_data; ace_event_data = (pMpi26EventDataActiveCableExcept_t)fw_event->event_data; - if (ace_event_data->ReasonCode == - MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER) { - mpr_printf(sc, "Currently an active cable with " + switch(ace_event_data->ReasonCode) { + case MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER: + { + mpr_printf(sc, "Currently a cable with " "ReceptacleID %d cannot be powered and device " "connected to this active cable will not be seen. " "This active cable requires %d mW of power.\n", ace_event_data->ReceptacleID, ace_event_data->ActiveCablePowerRequirement); + break; + } + case MPI26_EVENT_ACTIVE_CABLE_DEGRADED: + { + mpr_printf(sc, "Currently a cable with " + "ReceptacleID %d is not running at optimal speed " + "(12 Gb/s rate)\n", ace_event_data->ReceptacleID); + break; + } + default: + break; } break; } case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: default: mpr_dprint(sc, MPR_TRACE,"Unhandled event 0x%0X\n", fw_event->event); break; } mpr_dprint(sc, MPR_EVENT, "(%d)->(%s) Event Free: [%x]\n", event_count, __func__, fw_event->event); mprsas_fw_event_free(sc, fw_event); } void mprsas_firmware_event_work(void *arg, int pending) { struct mpr_fw_event_work *fw_event; struct mpr_softc *sc; sc = (struct mpr_softc *)arg; mpr_lock(sc); while ((fw_event = TAILQ_FIRST(&sc->sassc->ev_queue)) != NULL) { TAILQ_REMOVE(&sc->sassc->ev_queue, fw_event, ev_link); mprsas_fw_work(sc, fw_event); } mpr_unlock(sc); } static int mprsas_add_device(struct mpr_softc *sc, u16 handle, u8 linkrate){ char devstring[80]; struct mprsas_softc *sassc; struct mprsas_target *targ; Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t config_page; uint64_t sas_address, parent_sas_address = 0; u32 device_info, parent_devinfo = 0; unsigned int id; int ret = 1, error = 0, i; struct mprsas_lun *lun; u8 is_SATA_SSD = 0; struct mpr_command *cm; sassc = sc->sassc; mprsas_startup_increment(sassc); if ((mpr_config_get_sas_device_pg0(sc, &mpi_reply, &config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { printf("%s: error reading SAS device page0\n", __func__); error = ENXIO; goto out; } device_info = le32toh(config_page.DeviceInfo); if (((device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) && (le16toh(config_page.ParentDevHandle) != 0)) { Mpi2ConfigReply_t tmp_mpi_reply; Mpi2SasDevicePage0_t parent_config_page; if ((mpr_config_get_sas_device_pg0(sc, &tmp_mpi_reply, &parent_config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, le16toh(config_page.ParentDevHandle)))) { printf("%s: error reading SAS device %#x page0\n", __func__, le16toh(config_page.ParentDevHandle)); } else { parent_sas_address = parent_config_page.SASAddress.High; parent_sas_address = (parent_sas_address << 32) | parent_config_page.SASAddress.Low; parent_devinfo = le32toh(parent_config_page.DeviceInfo); } } /* TODO Check proper endianness */ sas_address = config_page.SASAddress.High; sas_address = (sas_address << 32) | config_page.SASAddress.Low; mpr_dprint(sc, MPR_INFO, "SAS Address from SAS device page0 = %jx\n", sas_address); /* * Always get SATA Identify information because this is used to * determine if Start/Stop Unit should be sent to the drive when the * system is shutdown. */ if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { ret = mprsas_get_sas_address_for_sata_disk(sc, &sas_address, handle, device_info, &is_SATA_SSD); if (ret) { mpr_dprint(sc, MPR_ERROR, "%s: failed to get disk type " "(SSD or HDD) for SATA device with handle 0x%04x\n", __func__, handle); } else { mpr_dprint(sc, MPR_INFO, "SAS Address from SATA " "device = %jx\n", sas_address); } } id = mpr_mapping_get_sas_id(sc, sas_address, handle); if (id == MPR_MAP_BAD_ID) { printf("failure at %s:%d/%s()! Could not get ID for device " "with handle 0x%04x\n", __FILE__, __LINE__, __func__, handle); error = ENXIO; goto out; } if (mprsas_check_id(sassc, id) != 0) { device_printf(sc->mpr_dev, "Excluding target id %d\n", id); error = ENXIO; goto out; } mpr_dprint(sc, MPR_MAPPING, "SAS Address from SAS device page0 = %jx\n", sas_address); targ = &sassc->targets[id]; targ->devinfo = device_info; targ->devname = le32toh(config_page.DeviceName.High); targ->devname = (targ->devname << 32) | le32toh(config_page.DeviceName.Low); targ->encl_handle = le16toh(config_page.EnclosureHandle); targ->encl_slot = le16toh(config_page.Slot); targ->encl_level = config_page.EnclosureLevel; targ->connector_name[0] = config_page.ConnectorName[0]; targ->connector_name[1] = config_page.ConnectorName[1]; targ->connector_name[2] = config_page.ConnectorName[2]; targ->connector_name[3] = config_page.ConnectorName[3]; targ->handle = handle; targ->parent_handle = le16toh(config_page.ParentDevHandle); targ->sasaddr = mpr_to_u64(&config_page.SASAddress); targ->parent_sasaddr = le64toh(parent_sas_address); targ->parent_devinfo = parent_devinfo; targ->tid = id; targ->linkrate = (linkrate>>4); targ->flags = 0; if (is_SATA_SSD) { targ->flags = MPR_TARGET_IS_SATA_SSD; } if (le16toh(config_page.Flags) & MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) { targ->scsi_req_desc_type = MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO; } if (le16toh(config_page.Flags) & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { targ->encl_level_valid = TRUE; } TAILQ_INIT(&targ->commands); TAILQ_INIT(&targ->timedout_commands); while (!SLIST_EMPTY(&targ->luns)) { lun = SLIST_FIRST(&targ->luns); SLIST_REMOVE_HEAD(&targ->luns, lun_link); free(lun, M_MPR); } SLIST_INIT(&targ->luns); mpr_describe_devinfo(targ->devinfo, devstring, 80); mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "Found device <%s> <%s> " "handle<0x%04x> enclosureHandle<0x%04x> slot %d\n", devstring, mpr_describe_table(mpr_linkrate_names, targ->linkrate), targ->handle, targ->encl_handle, targ->encl_slot); if (targ->encl_level_valid) { mpr_dprint(sc, (MPR_INFO|MPR_MAPPING), "At enclosure level %d " "and connector name (%4s)\n", targ->encl_level, targ->connector_name); } #if ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000039)) || \ (__FreeBSD_version < 902502) if ((sassc->flags & MPRSAS_IN_STARTUP) == 0) #endif mprsas_rescan_target(sc, targ); mpr_dprint(sc, MPR_MAPPING, "Target id 0x%x added\n", targ->tid); /* * Check all commands to see if the SATA_ID_TIMEOUT flag has been set. * If so, send a Target Reset TM to the target that was just created. * An Abort Task TM should be used instead of a Target Reset, but that * would be much more difficult because targets have not been fully * discovered yet, and LUN's haven't been setup. So, just reset the * target instead of the LUN. */ for (i = 1; i < sc->num_reqs; i++) { cm = &sc->commands[i]; if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { targ->timeouts++; cm->cm_state = MPR_CM_STATE_TIMEDOUT; if ((targ->tm = mprsas_alloc_tm(sc)) != NULL) { mpr_dprint(sc, MPR_INFO, "%s: sending Target " "Reset for stuck SATA identify command " "(cm = %p)\n", __func__, cm); targ->tm->cm_targ = targ; mprsas_send_reset(sc, targ->tm, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); } else { mpr_dprint(sc, MPR_ERROR, "Failed to allocate " "tm for Target Reset after SATA ID command " "timed out (cm %p)\n", cm); } /* * No need to check for more since the target is * already being reset. */ break; } } out: /* * Free the commands that may not have been freed from the SATA ID call */ for (i = 1; i < sc->num_reqs; i++) { cm = &sc->commands[i]; if (cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) { mpr_free_command(sc, cm); } } mprsas_startup_decrement(sassc); return (error); } int mprsas_get_sas_address_for_sata_disk(struct mpr_softc *sc, u64 *sas_address, u16 handle, u32 device_info, u8 *is_SATA_SSD) { Mpi2SataPassthroughReply_t mpi_reply; int i, rc, try_count; u32 *bufferptr; union _sata_sas_address hash_address; struct _ata_identify_device_data ata_identify; u8 buffer[MPT2SAS_MN_LEN + MPT2SAS_SN_LEN]; u32 ioc_status; u8 sas_status; memset(&ata_identify, 0, sizeof(ata_identify)); memset(&mpi_reply, 0, sizeof(mpi_reply)); try_count = 0; do { rc = mprsas_get_sata_identify(sc, handle, &mpi_reply, (char *)&ata_identify, sizeof(ata_identify), device_info); try_count++; ioc_status = le16toh(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; sas_status = mpi_reply.SASStatus; switch (ioc_status) { case MPI2_IOCSTATUS_SUCCESS: break; case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: /* No sense sleeping. this error won't get better */ break; default: if (sc->spinup_wait_time > 0) { mpr_dprint(sc, MPR_INFO, "Sleeping %d seconds " "after SATA ID error to wait for spinup\n", sc->spinup_wait_time); msleep(&sc->msleep_fake_chan, &sc->mpr_mtx, 0, "mprid", sc->spinup_wait_time * hz); } } } while (((rc && (rc != EWOULDBLOCK)) || (ioc_status && (ioc_status != MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR)) || sas_status) && (try_count < 5)); if (rc == 0 && !ioc_status && !sas_status) { mpr_dprint(sc, MPR_MAPPING, "%s: got SATA identify " "successfully for handle = 0x%x with try_count = %d\n", __func__, handle, try_count); } else { mpr_dprint(sc, MPR_MAPPING, "%s: handle = 0x%x failed\n", __func__, handle); return -1; } /* Copy & byteswap the 40 byte model number to a buffer */ for (i = 0; i < MPT2SAS_MN_LEN; i += 2) { buffer[i] = ((u8 *)ata_identify.model_number)[i + 1]; buffer[i + 1] = ((u8 *)ata_identify.model_number)[i]; } /* Copy & byteswap the 20 byte serial number to a buffer */ for (i = 0; i < MPT2SAS_SN_LEN; i += 2) { buffer[MPT2SAS_MN_LEN + i] = ((u8 *)ata_identify.serial_number)[i + 1]; buffer[MPT2SAS_MN_LEN + i + 1] = ((u8 *)ata_identify.serial_number)[i]; } bufferptr = (u32 *)buffer; /* There are 60 bytes to hash down to 8. 60 isn't divisible by 8, * so loop through the first 56 bytes (7*8), * and then add in the last dword. */ hash_address.word.low = 0; hash_address.word.high = 0; for (i = 0; (i < ((MPT2SAS_MN_LEN+MPT2SAS_SN_LEN)/8)); i++) { hash_address.word.low += *bufferptr; bufferptr++; hash_address.word.high += *bufferptr; bufferptr++; } /* Add the last dword */ hash_address.word.low += *bufferptr; /* Make sure the hash doesn't start with 5, because it could clash * with a SAS address. Change 5 to a D. */ if ((hash_address.word.high & 0x000000F0) == (0x00000050)) hash_address.word.high |= 0x00000080; *sas_address = (u64)hash_address.wwid[0] << 56 | (u64)hash_address.wwid[1] << 48 | (u64)hash_address.wwid[2] << 40 | (u64)hash_address.wwid[3] << 32 | (u64)hash_address.wwid[4] << 24 | (u64)hash_address.wwid[5] << 16 | (u64)hash_address.wwid[6] << 8 | (u64)hash_address.wwid[7]; if (ata_identify.rotational_speed == 1) { *is_SATA_SSD = 1; } return 0; } static int mprsas_get_sata_identify(struct mpr_softc *sc, u16 handle, Mpi2SataPassthroughReply_t *mpi_reply, char *id_buffer, int sz, u32 devinfo) { Mpi2SataPassthroughRequest_t *mpi_request; Mpi2SataPassthroughReply_t *reply; struct mpr_command *cm; char *buffer; int error = 0; buffer = malloc( sz, M_MPR, M_NOWAIT | M_ZERO); if (!buffer) return ENOMEM; if ((cm = mpr_alloc_command(sc)) == NULL) { free(buffer, M_MPR); return (EBUSY); } mpi_request = (MPI2_SATA_PASSTHROUGH_REQUEST *)cm->cm_req; bzero(mpi_request,sizeof(MPI2_SATA_PASSTHROUGH_REQUEST)); mpi_request->Function = MPI2_FUNCTION_SATA_PASSTHROUGH; mpi_request->VF_ID = 0; mpi_request->DevHandle = htole16(handle); mpi_request->PassthroughFlags = (MPI2_SATA_PT_REQ_PT_FLAGS_PIO | MPI2_SATA_PT_REQ_PT_FLAGS_READ); mpi_request->DataLength = htole32(sz); mpi_request->CommandFIS[0] = 0x27; mpi_request->CommandFIS[1] = 0x80; mpi_request->CommandFIS[2] = (devinfo & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? 0xA1 : 0xEC; cm->cm_sge = &mpi_request->SGL; cm->cm_sglsize = sizeof(MPI2_SGE_IO_UNION); cm->cm_flags = MPR_CM_FLAGS_DATAIN; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; cm->cm_data = buffer; cm->cm_length = htole32(sz); /* * Start a timeout counter specifically for the SATA ID command. This * is used to fix a problem where the FW does not send a reply sometimes * when a bad disk is in the topology. So, this is used to timeout the * command so that processing can continue normally. */ mpr_dprint(sc, MPR_XINFO, "%s start timeout counter for SATA ID " "command\n", __func__); callout_reset(&cm->cm_callout, MPR_ATA_ID_TIMEOUT * hz, mprsas_ata_id_timeout, cm); error = mpr_wait_command(sc, cm, 60, CAN_SLEEP); mpr_dprint(sc, MPR_XINFO, "%s stop timeout counter for SATA ID " "command\n", __func__); callout_stop(&cm->cm_callout); reply = (Mpi2SataPassthroughReply_t *)cm->cm_reply; if (error || (reply == NULL)) { /* FIXME */ /* * If the request returns an error then we need to do a diag * reset */ printf("%s: request for page completed with error %d", __func__, error); error = ENXIO; goto out; } bcopy(buffer, id_buffer, sz); bcopy(reply, mpi_reply, sizeof(Mpi2SataPassthroughReply_t)); if ((le16toh(reply->IOCStatus) & MPI2_IOCSTATUS_MASK) != MPI2_IOCSTATUS_SUCCESS) { printf("%s: error reading SATA PASSTHRU; iocstatus = 0x%x\n", __func__, reply->IOCStatus); error = ENXIO; goto out; } out: /* * If the SATA_ID_TIMEOUT flag has been set for this command, don't free * it. The command will be freed after sending a target reset TM. If * the command did timeout, use EWOULDBLOCK. */ if ((cm->cm_flags & MPR_CM_FLAGS_SATA_ID_TIMEOUT) == 0) mpr_free_command(sc, cm); else if (error == 0) error = EWOULDBLOCK; cm->cm_data = NULL; free(buffer, M_MPR); return (error); } static void mprsas_ata_id_timeout(void *data) { struct mpr_softc *sc; struct mpr_command *cm; cm = (struct mpr_command *)data; sc = cm->cm_sc; mtx_assert(&sc->mpr_mtx, MA_OWNED); mpr_dprint(sc, MPR_INFO, "%s checking ATA ID command %p sc %p\n", __func__, cm, sc); if ((callout_pending(&cm->cm_callout)) || (!callout_active(&cm->cm_callout))) { mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed out\n", __func__); return; } callout_deactivate(&cm->cm_callout); /* * Run the interrupt handler to make sure it's not pending. This * isn't perfect because the command could have already completed * and been re-used, though this is unlikely. */ mpr_intr_locked(sc); if (cm->cm_state == MPR_CM_STATE_FREE) { mpr_dprint(sc, MPR_INFO, "%s ATA ID command almost timed out\n", __func__); return; } mpr_dprint(sc, MPR_INFO, "ATA ID command timeout cm %p\n", cm); /* * Send wakeup() to the sleeping thread that issued this ATA ID command. * wakeup() will cause msleep to return a 0 (not EWOULDBLOCK), and this * will keep reinit() from being called. This way, an Abort Task TM can * be issued so that the timed out command can be cleared. The Abort * Task cannot be sent from here because the driver has not completed * setting up targets. Instead, the command is flagged so that special * handling will be used to send the abort. */ cm->cm_flags |= MPR_CM_FLAGS_SATA_ID_TIMEOUT; wakeup(cm); } static int mprsas_volume_add(struct mpr_softc *sc, u16 handle) { struct mprsas_softc *sassc; struct mprsas_target *targ; u64 wwid; unsigned int id; int error = 0; struct mprsas_lun *lun; sassc = sc->sassc; mprsas_startup_increment(sassc); /* wwid is endian safe */ mpr_config_get_volume_wwid(sc, handle, &wwid); if (!wwid) { printf("%s: invalid WWID; cannot add volume to mapping table\n", __func__); error = ENXIO; goto out; } id = mpr_mapping_get_raid_id(sc, wwid, handle); if (id == MPR_MAP_BAD_ID) { printf("%s: could not get ID for volume with handle 0x%04x and " "WWID 0x%016llx\n", __func__, handle, (unsigned long long)wwid); error = ENXIO; goto out; } targ = &sassc->targets[id]; targ->tid = id; targ->handle = handle; targ->devname = wwid; TAILQ_INIT(&targ->commands); TAILQ_INIT(&targ->timedout_commands); while (!SLIST_EMPTY(&targ->luns)) { lun = SLIST_FIRST(&targ->luns); SLIST_REMOVE_HEAD(&targ->luns, lun_link); free(lun, M_MPR); } SLIST_INIT(&targ->luns); #if ((__FreeBSD_version >= 1000000) && (__FreeBSD_version < 1000039)) || \ (__FreeBSD_version < 902502) if ((sassc->flags & MPRSAS_IN_STARTUP) == 0) #endif mprsas_rescan_target(sc, targ); mpr_dprint(sc, MPR_MAPPING, "RAID target id %d added (WWID = 0x%jx)\n", targ->tid, wwid); out: mprsas_startup_decrement(sassc); return (error); } /** * mprsas_SSU_to_SATA_devices * @sc: per adapter object * * Looks through the target list and issues a StartStopUnit SCSI command to each * SATA direct-access device. This helps to ensure that data corruption is * avoided when the system is being shut down. This must be called after the IR * System Shutdown RAID Action is sent if in IR mode. * * Return nothing. */ static void mprsas_SSU_to_SATA_devices(struct mpr_softc *sc) { struct mprsas_softc *sassc = sc->sassc; union ccb *ccb; path_id_t pathid = cam_sim_path(sassc->sim); target_id_t targetid; struct mprsas_target *target; char path_str[64]; struct timeval cur_time, start_time; mpr_lock(sc); /* * For each target, issue a StartStopUnit command to stop the device. */ sc->SSU_started = TRUE; sc->SSU_refcount = 0; for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) { target = &sassc->targets[targetid]; if (target->handle == 0x0) { continue; } /* * The stop_at_shutdown flag will be set if this device is * a SATA direct-access end device. */ if (target->stop_at_shutdown) { ccb = xpt_alloc_ccb_nowait(); if (ccb == NULL) { mpr_dprint(sc, MPR_FAULT, "Unable to alloc CCB to stop " "unit.\n"); return; } if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, pathid, targetid, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { mpr_dprint(sc, MPR_ERROR, "Unable to create " "path to stop unit.\n"); xpt_free_ccb(ccb); return; } xpt_path_string(ccb->ccb_h.path, path_str, sizeof(path_str)); mpr_dprint(sc, MPR_INFO, "Sending StopUnit: path %s " "handle %d\n", path_str, target->handle); /* * Issue a START STOP UNIT command for the target. * Increment the SSU counter to be used to count the * number of required replies. */ mpr_dprint(sc, MPR_INFO, "Incrementing SSU count\n"); sc->SSU_refcount++; ccb->ccb_h.target_id = xpt_path_target_id(ccb->ccb_h.path); ccb->ccb_h.ppriv_ptr1 = sassc; scsi_start_stop(&ccb->csio, /*retries*/0, mprsas_stop_unit_done, MSG_SIMPLE_Q_TAG, /*start*/FALSE, /*load/eject*/0, /*immediate*/FALSE, MPR_SENSE_LEN, /*timeout*/10000); xpt_action(ccb); } } mpr_unlock(sc); /* * Wait until all of the SSU commands have completed or time has * expired (60 seconds). Pause for 100ms each time through. If any * command times out, the target will be reset in the SCSI command * timeout routine. */ getmicrotime(&start_time); while (sc->SSU_refcount) { pause("mprwait", hz/10); getmicrotime(&cur_time); if ((cur_time.tv_sec - start_time.tv_sec) > 60) { mpr_dprint(sc, MPR_ERROR, "Time has expired waiting " "for SSU commands to complete.\n"); break; } } } static void mprsas_stop_unit_done(struct cam_periph *periph, union ccb *done_ccb) { struct mprsas_softc *sassc; char path_str[64]; if (done_ccb == NULL) return; sassc = (struct mprsas_softc *)done_ccb->ccb_h.ppriv_ptr1; xpt_path_string(done_ccb->ccb_h.path, path_str, sizeof(path_str)); mpr_dprint(sassc->sc, MPR_INFO, "Completing stop unit for %s\n", path_str); /* * Nothing more to do except free the CCB and path. If the command * timed out, an abort reset, then target reset will be issued during * the SCSI Command process. */ xpt_free_path(done_ccb->ccb_h.path); xpt_free_ccb(done_ccb); } /** * mprsas_ir_shutdown - IR shutdown notification * @sc: per adapter object * * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that * the host system is shutting down. * * Return nothing. */ void mprsas_ir_shutdown(struct mpr_softc *sc) { u16 volume_mapping_flags; u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); struct dev_mapping_table *mt_entry; u32 start_idx, end_idx; unsigned int id, found_volume = 0; struct mpr_command *cm; Mpi2RaidActionRequest_t *action; target_id_t targetid; struct mprsas_target *target; mpr_dprint(sc, MPR_TRACE, "%s\n", __func__); /* is IR firmware build loaded? */ if (!sc->ir_firmware) goto out; /* are there any volumes? Look at IR target IDs. */ // TODO-later, this should be looked up in the RAID config structure // when it is implemented. volume_mapping_flags = le16toh(sc->ioc_pg8.IRVolumeMappingFlags) & MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; if (volume_mapping_flags == MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) { start_idx = 0; if (ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0) start_idx = 1; } else start_idx = sc->max_devices - sc->max_volumes; end_idx = start_idx + sc->max_volumes - 1; for (id = start_idx; id < end_idx; id++) { mt_entry = &sc->mapping_table[id]; if ((mt_entry->physical_id != 0) && (mt_entry->missing_count == 0)) { found_volume = 1; break; } } if (!found_volume) goto out; if ((cm = mpr_alloc_command(sc)) == NULL) { printf("%s: command alloc failed\n", __func__); goto out; } action = (MPI2_RAID_ACTION_REQUEST *)cm->cm_req; action->Function = MPI2_FUNCTION_RAID_ACTION; action->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; cm->cm_desc.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; mpr_lock(sc); mpr_wait_command(sc, cm, 5, CAN_SLEEP); mpr_unlock(sc); /* * Don't check for reply, just leave. */ if (cm) mpr_free_command(sc, cm); out: /* * All of the targets must have the correct value set for * 'stop_at_shutdown' for the current 'enable_ssu' sysctl variable. * * The possible values for the 'enable_ssu' variable are: * 0: disable to SSD and HDD * 1: disable only to HDD (default) * 2: disable only to SSD * 3: enable to SSD and HDD * anything else will default to 1. */ for (targetid = 0; targetid < sc->facts->MaxTargets; targetid++) { target = &sc->sassc->targets[targetid]; if (target->handle == 0x0) { continue; } if (target->supports_SSU) { switch (sc->enable_ssu) { case MPR_SSU_DISABLE_SSD_DISABLE_HDD: target->stop_at_shutdown = FALSE; break; case MPR_SSU_DISABLE_SSD_ENABLE_HDD: target->stop_at_shutdown = TRUE; if (target->flags & MPR_TARGET_IS_SATA_SSD) { target->stop_at_shutdown = FALSE; } break; case MPR_SSU_ENABLE_SSD_ENABLE_HDD: target->stop_at_shutdown = TRUE; break; case MPR_SSU_ENABLE_SSD_DISABLE_HDD: default: target->stop_at_shutdown = TRUE; if ((target->flags & MPR_TARGET_IS_SATA_SSD) == 0) { target->stop_at_shutdown = FALSE; } break; } } } mprsas_SSU_to_SATA_devices(sc); } Index: stable/11/sys/dev/mpr/mpr_table.c =================================================================== --- stable/11/sys/dev/mpr/mpr_table.c (revision 315187) +++ stable/11/sys/dev/mpr/mpr_table.c (revision 315188) @@ -1,516 +1,522 @@ /*- * Copyright (c) 2009 Yahoo! Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* Debugging tables for MPT2 */ /* TODO Move headers to mprvar */ #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 char * mpr_describe_table(struct mpr_table_lookup *table, u_int code) { int i; for (i = 0; table[i].string != NULL; i++) { if (table[i].code == code) return(table[i].string); } return(table[i+1].string); } struct mpr_table_lookup mpr_event_names[] = { {"LogData", 0x01}, {"StateChange", 0x02}, {"HardResetReceived", 0x05}, {"EventChange", 0x0a}, {"TaskSetFull", 0x0e}, {"SasDeviceStatusChange", 0x0f}, {"IrOperationStatus", 0x14}, {"SasDiscovery", 0x16}, {"SasBroadcastPrimitive", 0x17}, {"SasInitDeviceStatusChange", 0x18}, {"SasInitTableOverflow", 0x19}, {"SasTopologyChangeList", 0x1c}, {"SasEnclDeviceStatusChange", 0x1d}, {"IrVolume", 0x1e}, {"IrPhysicalDisk", 0x1f}, {"IrConfigurationChangeList", 0x20}, {"LogEntryAdded", 0x21}, {"SasPhyCounter", 0x22}, {"GpioInterrupt", 0x23}, {"HbdPhyEvent", 0x24}, + {"SasQuiesce", 0x25}, + {"SasNotifyPrimitive", 0x26}, + {"TempThreshold", 0x27}, + {"HostMessage", 0x28}, + {"PowerPerformanceChange", 0x29}, + {"CableEvent", 0x34}, {NULL, 0}, {"Unknown Event", 0} }; struct mpr_table_lookup mpr_phystatus_names[] = { {"NewTargetAdded", 0x01}, {"TargetGone", 0x02}, {"PHYLinkStatusChange", 0x03}, {"PHYLinkStatusUnchanged", 0x04}, {"TargetMissing", 0x05}, {NULL, 0}, {"Unknown Status", 0} }; struct mpr_table_lookup mpr_linkrate_names[] = { {"PHY disabled", 0x01}, {"Speed Negotiation Failed", 0x02}, {"SATA OOB Complete", 0x03}, {"SATA Port Selector", 0x04}, {"SMP Reset in Progress", 0x05}, {"1.5Gbps", 0x08}, {"3.0Gbps", 0x09}, {"6.0Gbps", 0x0a}, {"12.0Gbps", 0x0b}, {NULL, 0}, {"LinkRate Unknown", 0x00} }; struct mpr_table_lookup mpr_sasdev0_devtype[] = { {"End Device", 0x01}, {"Edge Expander", 0x02}, {"Fanout Expander", 0x03}, {NULL, 0}, {"No Device", 0x00} }; struct mpr_table_lookup mpr_phyinfo_reason_names[] = { {"Power On", 0x01}, {"Hard Reset", 0x02}, {"SMP Phy Control Link Reset", 0x03}, {"Loss DWORD Sync", 0x04}, {"Multiplex Sequence", 0x05}, {"I-T Nexus Loss Timer", 0x06}, {"Break Timeout Timer", 0x07}, {"PHY Test Function", 0x08}, {NULL, 0}, {"Unknown Reason", 0x00} }; struct mpr_table_lookup mpr_whoinit_names[] = { {"System BIOS", 0x01}, {"ROM BIOS", 0x02}, {"PCI Peer", 0x03}, {"Host Driver", 0x04}, {"Manufacturing", 0x05}, {NULL, 0}, {"Not Initialized", 0x00} }; struct mpr_table_lookup mpr_sasdisc_reason[] = { {"Discovery Started", 0x01}, {"Discovery Complete", 0x02}, {NULL, 0}, {"Unknown", 0x00} }; struct mpr_table_lookup mpr_sastopo_exp[] = { {"Added", 0x01}, {"Not Responding", 0x02}, {"Responding", 0x03}, {"Delay Not Responding", 0x04}, {NULL, 0}, {"Unknown", 0x00} }; struct mpr_table_lookup mpr_sasdev_reason[] = { {"SMART Data", 0x05}, {"Unsupported", 0x07}, {"Internal Device Reset", 0x08}, {"Task Abort Internal", 0x09}, {"Abort Task Set Internal", 0x0a}, {"Clear Task Set Internal", 0x0b}, {"Query Task Internal", 0x0c}, {"Async Notification", 0x0d}, {"Cmp Internal Device Reset", 0x0e}, {"Cmp Task Abort Internal", 0x0f}, {"Sata Init Failure", 0x10}, {NULL, 0}, {"Unknown", 0x00} }; void mpr_describe_devinfo(uint32_t devinfo, char *string, int len) { snprintf(string, len, "%b,%s", devinfo, "\20" "\4SataHost" "\5SmpInit" "\6StpInit" "\7SspInit" "\10SataDev" "\11SmpTarg" "\12StpTarg" "\13SspTarg" "\14Direct" "\15LsiDev" "\16AtapiDev" "\17SepDev", mpr_describe_table(mpr_sasdev0_devtype, devinfo & 0x03)); } void mpr_print_iocfacts(struct mpr_softc *sc, MPI2_IOC_FACTS_REPLY *facts) { MPR_PRINTFIELD_START(sc, "IOCFacts"); MPR_PRINTFIELD(sc, facts, MsgVersion, 0x%x); MPR_PRINTFIELD(sc, facts, HeaderVersion, 0x%x); MPR_PRINTFIELD(sc, facts, IOCNumber, %d); MPR_PRINTFIELD(sc, facts, IOCExceptions, 0x%x); MPR_PRINTFIELD(sc, facts, MaxChainDepth, %d); mpr_dprint_field(sc, MPR_XINFO, "WhoInit: %s\n", mpr_describe_table(mpr_whoinit_names, facts->WhoInit)); MPR_PRINTFIELD(sc, facts, NumberOfPorts, %d); MPR_PRINTFIELD(sc, facts, RequestCredit, %d); MPR_PRINTFIELD(sc, facts, ProductID, 0x%x); mpr_dprint_field(sc, MPR_XINFO, "IOCCapabilities: %b\n", facts->IOCCapabilities, "\20" "\3ScsiTaskFull" "\4DiagTrace" "\5SnapBuf" "\6ExtBuf" "\7EEDP" "\10BiDirTarg" "\11Multicast" "\14TransRetry" "\15IR" "\16EventReplay" "\17RaidAccel" "\20MSIXIndex" "\21HostDisc"); mpr_dprint_field(sc, MPR_XINFO, "FWVersion= %d-%d-%d-%d\n", facts->FWVersion.Struct.Major, facts->FWVersion.Struct.Minor, facts->FWVersion.Struct.Unit, facts->FWVersion.Struct.Dev); MPR_PRINTFIELD(sc, facts, IOCRequestFrameSize, %d); MPR_PRINTFIELD(sc, facts, MaxInitiators, %d); MPR_PRINTFIELD(sc, facts, MaxTargets, %d); MPR_PRINTFIELD(sc, facts, MaxSasExpanders, %d); MPR_PRINTFIELD(sc, facts, MaxEnclosures, %d); mpr_dprint_field(sc, MPR_XINFO, "ProtocolFlags: %b\n", facts->ProtocolFlags, "\20" "\1ScsiTarg" "\2ScsiInit"); MPR_PRINTFIELD(sc, facts, HighPriorityCredit, %d); MPR_PRINTFIELD(sc, facts, MaxReplyDescriptorPostQueueDepth, %d); MPR_PRINTFIELD(sc, facts, ReplyFrameSize, %d); MPR_PRINTFIELD(sc, facts, MaxVolumes, %d); MPR_PRINTFIELD(sc, facts, MaxDevHandle, %d); MPR_PRINTFIELD(sc, facts, MaxPersistentEntries, %d); } void mpr_print_portfacts(struct mpr_softc *sc, MPI2_PORT_FACTS_REPLY *facts) { MPR_PRINTFIELD_START(sc, "PortFacts"); MPR_PRINTFIELD(sc, facts, PortNumber, %d); MPR_PRINTFIELD(sc, facts, PortType, 0x%x); MPR_PRINTFIELD(sc, facts, MaxPostedCmdBuffers, %d); } void mpr_print_event(struct mpr_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event) { MPR_EVENTFIELD_START(sc, "EventReply"); MPR_EVENTFIELD(sc, event, EventDataLength, %d); MPR_EVENTFIELD(sc, event, AckRequired, %d); mpr_dprint_field(sc, MPR_EVENT, "Event: %s (0x%x)\n", mpr_describe_table(mpr_event_names, event->Event), event->Event); MPR_EVENTFIELD(sc, event, EventContext, 0x%x); } void mpr_print_sasdev0(struct mpr_softc *sc, MPI2_CONFIG_PAGE_SAS_DEV_0 *buf) { MPR_PRINTFIELD_START(sc, "SAS Device Page 0"); MPR_PRINTFIELD(sc, buf, Slot, %d); MPR_PRINTFIELD(sc, buf, EnclosureHandle, 0x%x); mpr_dprint_field(sc, MPR_XINFO, "SASAddress: 0x%jx\n", mpr_to_u64(&buf->SASAddress)); MPR_PRINTFIELD(sc, buf, ParentDevHandle, 0x%x); MPR_PRINTFIELD(sc, buf, PhyNum, %d); MPR_PRINTFIELD(sc, buf, AccessStatus, 0x%x); MPR_PRINTFIELD(sc, buf, DevHandle, 0x%x); MPR_PRINTFIELD(sc, buf, AttachedPhyIdentifier, 0x%x); MPR_PRINTFIELD(sc, buf, ZoneGroup, %d); mpr_dprint_field(sc, MPR_XINFO, "DeviceInfo: %b,%s\n", buf->DeviceInfo, "\20" "\4SataHost" "\5SmpInit" "\6StpInit" "\7SspInit" "\10SataDev" "\11SmpTarg" "\12StpTarg" "\13SspTarg" "\14Direct" "\15LsiDev" "\16AtapiDev" "\17SepDev", mpr_describe_table(mpr_sasdev0_devtype, buf->DeviceInfo & 0x03)); MPR_PRINTFIELD(sc, buf, Flags, 0x%x); MPR_PRINTFIELD(sc, buf, PhysicalPort, %d); MPR_PRINTFIELD(sc, buf, MaxPortConnections, %d); mpr_dprint_field(sc, MPR_XINFO, "DeviceName: 0x%jx\n", mpr_to_u64(&buf->DeviceName)); MPR_PRINTFIELD(sc, buf, PortGroups, %d); MPR_PRINTFIELD(sc, buf, DmaGroup, %d); MPR_PRINTFIELD(sc, buf, ControlGroup, %d); } void mpr_print_evt_sas(struct mpr_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event) { mpr_print_event(sc, event); switch(event->Event) { case MPI2_EVENT_SAS_DISCOVERY: { MPI2_EVENT_DATA_SAS_DISCOVERY *data; data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)&event->EventData; mpr_dprint_field(sc, MPR_EVENT, "Flags: %b\n", data->Flags, "\20" "\1InProgress" "\2DeviceChange"); mpr_dprint_field(sc, MPR_EVENT, "ReasonCode: %s\n", mpr_describe_table(mpr_sasdisc_reason, data->ReasonCode)); MPR_EVENTFIELD(sc, data, PhysicalPort, %d); mpr_dprint_field(sc, MPR_EVENT, "DiscoveryStatus: %b\n", data->DiscoveryStatus, "\20" "\1Loop" "\2UnaddressableDev" "\3DupSasAddr" "\5SmpTimeout" "\6ExpRouteFull" "\7RouteIndexError" "\10SmpFailed" "\11SmpCrcError" "\12SubSubLink" "\13TableTableLink" "\14UnsupDevice" "\15TableSubLink" "\16MultiDomain" "\17MultiSub" "\20MultiSubSub" "\34DownstreamInit" "\35MaxPhys" "\36MaxTargs" "\37MaxExpanders" "\40MaxEnclosures"); break; } case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: { MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data; MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy; int i, phynum; data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *) &event->EventData; MPR_EVENTFIELD(sc, data, EnclosureHandle, 0x%x); MPR_EVENTFIELD(sc, data, ExpanderDevHandle, 0x%x); MPR_EVENTFIELD(sc, data, NumPhys, %d); MPR_EVENTFIELD(sc, data, NumEntries, %d); MPR_EVENTFIELD(sc, data, StartPhyNum, %d); mpr_dprint_field(sc, MPR_EVENT, "ExpStatus: %s (0x%x)\n", mpr_describe_table(mpr_sastopo_exp, data->ExpStatus), data->ExpStatus); MPR_EVENTFIELD(sc, data, PhysicalPort, %d); for (i = 0; i < data->NumEntries; i++) { phy = &data->PHY[i]; phynum = data->StartPhyNum + i; mpr_dprint_field(sc, MPR_EVENT, "PHY[%d].AttachedDevHandle: 0x%04x\n", phynum, phy->AttachedDevHandle); mpr_dprint_field(sc, MPR_EVENT, "PHY[%d].LinkRate: %s (0x%x)\n", phynum, mpr_describe_table(mpr_linkrate_names, (phy->LinkRate >> 4) & 0xf), phy->LinkRate); mpr_dprint_field(sc,MPR_EVENT,"PHY[%d].PhyStatus: %s\n", phynum, mpr_describe_table(mpr_phystatus_names, phy->PhyStatus)); } break; } case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: { MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE *data; data = (MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE *) &event->EventData; MPR_EVENTFIELD(sc, data, EnclosureHandle, 0x%x); mpr_dprint_field(sc, MPR_EVENT, "ReasonCode: %s\n", mpr_describe_table(mpr_sastopo_exp, data->ReasonCode)); MPR_EVENTFIELD(sc, data, PhysicalPort, %d); MPR_EVENTFIELD(sc, data, NumSlots, %d); MPR_EVENTFIELD(sc, data, StartSlot, %d); MPR_EVENTFIELD(sc, data, PhyBits, 0x%x); break; } case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: { MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *data; data = (MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *) &event->EventData; MPR_EVENTFIELD(sc, data, TaskTag, 0x%x); mpr_dprint_field(sc, MPR_EVENT, "ReasonCode: %s\n", mpr_describe_table(mpr_sasdev_reason, data->ReasonCode)); MPR_EVENTFIELD(sc, data, ASC, 0x%x); MPR_EVENTFIELD(sc, data, ASCQ, 0x%x); MPR_EVENTFIELD(sc, data, DevHandle, 0x%x); mpr_dprint_field(sc, MPR_EVENT, "SASAddress: 0x%jx\n", mpr_to_u64(&data->SASAddress)); } default: break; } } void mpr_print_expander1(struct mpr_softc *sc, MPI2_CONFIG_PAGE_EXPANDER_1 *buf) { MPR_PRINTFIELD_START(sc, "SAS Expander Page 1 #%d", buf->Phy); MPR_PRINTFIELD(sc, buf, PhysicalPort, %d); MPR_PRINTFIELD(sc, buf, NumPhys, %d); MPR_PRINTFIELD(sc, buf, Phy, %d); MPR_PRINTFIELD(sc, buf, NumTableEntriesProgrammed, %d); mpr_dprint_field(sc, MPR_XINFO, "ProgrammedLinkRate: %s (0x%x)\n", mpr_describe_table(mpr_linkrate_names, (buf->ProgrammedLinkRate >> 4) & 0xf), buf->ProgrammedLinkRate); mpr_dprint_field(sc, MPR_XINFO, "HwLinkRate: %s (0x%x)\n", mpr_describe_table(mpr_linkrate_names, (buf->HwLinkRate >> 4) & 0xf), buf->HwLinkRate); MPR_PRINTFIELD(sc, buf, AttachedDevHandle, 0x%04x); mpr_dprint_field(sc, MPR_XINFO, "PhyInfo Reason: %s (0x%x)\n", mpr_describe_table(mpr_phyinfo_reason_names, (buf->PhyInfo >> 16) & 0xf), buf->PhyInfo); mpr_dprint_field(sc, MPR_XINFO, "AttachedDeviceInfo: %b,%s\n", buf->AttachedDeviceInfo, "\20" "\4SATAhost" "\5SMPinit" "\6STPinit" "\7SSPinit" "\10SATAdev" "\11SMPtarg" "\12STPtarg" "\13SSPtarg" "\14Direct" "\15LSIdev" "\16ATAPIdev" "\17SEPdev", mpr_describe_table(mpr_sasdev0_devtype, buf->AttachedDeviceInfo & 0x03)); MPR_PRINTFIELD(sc, buf, ExpanderDevHandle, 0x%04x); MPR_PRINTFIELD(sc, buf, ChangeCount, %d); mpr_dprint_field(sc, MPR_XINFO, "NegotiatedLinkRate: %s (0x%x)\n", mpr_describe_table(mpr_linkrate_names, buf->NegotiatedLinkRate & 0xf), buf->NegotiatedLinkRate); MPR_PRINTFIELD(sc, buf, PhyIdentifier, %d); MPR_PRINTFIELD(sc, buf, AttachedPhyIdentifier, %d); MPR_PRINTFIELD(sc, buf, DiscoveryInfo, 0x%x); MPR_PRINTFIELD(sc, buf, AttachedPhyInfo, 0x%x); mpr_dprint_field(sc, MPR_XINFO, "AttachedPhyInfo Reason: %s (0x%x)\n", mpr_describe_table(mpr_phyinfo_reason_names, buf->AttachedPhyInfo & 0xf), buf->AttachedPhyInfo); MPR_PRINTFIELD(sc, buf, ZoneGroup, %d); MPR_PRINTFIELD(sc, buf, SelfConfigStatus, 0x%x); } void mpr_print_sasphy0(struct mpr_softc *sc, MPI2_CONFIG_PAGE_SAS_PHY_0 *buf) { MPR_PRINTFIELD_START(sc, "SAS PHY Page 0"); MPR_PRINTFIELD(sc, buf, OwnerDevHandle, 0x%04x); MPR_PRINTFIELD(sc, buf, AttachedDevHandle, 0x%04x); MPR_PRINTFIELD(sc, buf, AttachedPhyIdentifier, %d); mpr_dprint_field(sc, MPR_XINFO, "AttachedPhyInfo Reason: %s (0x%x)\n", mpr_describe_table(mpr_phyinfo_reason_names, buf->AttachedPhyInfo & 0xf), buf->AttachedPhyInfo); mpr_dprint_field(sc, MPR_XINFO, "ProgrammedLinkRate: %s (0x%x)\n", mpr_describe_table(mpr_linkrate_names, (buf->ProgrammedLinkRate >> 4) & 0xf), buf->ProgrammedLinkRate); mpr_dprint_field(sc, MPR_XINFO, "HwLinkRate: %s (0x%x)\n", mpr_describe_table(mpr_linkrate_names, (buf->HwLinkRate >> 4) & 0xf), buf->HwLinkRate); MPR_PRINTFIELD(sc, buf, ChangeCount, %d); MPR_PRINTFIELD(sc, buf, Flags, 0x%x); mpr_dprint_field(sc, MPR_XINFO, "PhyInfo Reason: %s (0x%x)\n", mpr_describe_table(mpr_phyinfo_reason_names, (buf->PhyInfo >> 16) & 0xf), buf->PhyInfo); mpr_dprint_field(sc, MPR_XINFO, "NegotiatedLinkRate: %s (0x%x)\n", mpr_describe_table(mpr_linkrate_names, buf->NegotiatedLinkRate & 0xf), buf->NegotiatedLinkRate); } void mpr_print_sgl(struct mpr_softc *sc, struct mpr_command *cm, int offset) { MPI2_IEEE_SGE_SIMPLE64 *ieee_sge; MPI25_IEEE_SGE_CHAIN64 *ieee_sgc; MPI2_SGE_SIMPLE64 *sge; MPI2_REQUEST_HEADER *req; struct mpr_chain *chain = NULL; char *frame; u_int i = 0, flags, length; req = (MPI2_REQUEST_HEADER *)cm->cm_req; frame = (char *)cm->cm_req; ieee_sge = (MPI2_IEEE_SGE_SIMPLE64 *)&frame[offset * 4]; sge = (MPI2_SGE_SIMPLE64 *)&frame[offset * 4]; printf("SGL for command %p\n", cm); hexdump(frame, 128, NULL, 0); while ((frame != NULL) && (!(cm->cm_flags & MPR_CM_FLAGS_SGE_SIMPLE))) { flags = ieee_sge->Flags; length = le32toh(ieee_sge->Length); printf("IEEE seg%d flags=0x%02x len=0x%08x addr=0x%016jx\n", i, flags, length, mpr_to_u64(&ieee_sge->Address)); if (flags & MPI25_IEEE_SGE_FLAGS_END_OF_LIST) break; ieee_sge++; i++; if (flags & MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT) { ieee_sgc = (MPI25_IEEE_SGE_CHAIN64 *)ieee_sge; printf("IEEE chain flags=0x%x len=0x%x Offset=0x%x " "Address=0x%016jx\n", ieee_sgc->Flags, le32toh(ieee_sgc->Length), ieee_sgc->NextChainOffset, mpr_to_u64(&ieee_sgc->Address)); if (chain == NULL) chain = TAILQ_FIRST(&cm->cm_chain_list); else chain = TAILQ_NEXT(chain, chain_link); frame = (char *)chain->chain; ieee_sge = (MPI2_IEEE_SGE_SIMPLE64 *)frame; hexdump(frame, 128, NULL, 0); } } while ((frame != NULL) && (cm->cm_flags & MPR_CM_FLAGS_SGE_SIMPLE)) { flags = le32toh(sge->FlagsLength) >> MPI2_SGE_FLAGS_SHIFT; printf("seg%d flags=0x%02x len=0x%06x addr=0x%016jx\n", i, flags, le32toh(sge->FlagsLength) & 0xffffff, mpr_to_u64(&sge->Address)); if (flags & (MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_END_OF_BUFFER)) break; sge++; i++; } } void mpr_print_scsiio_cmd(struct mpr_softc *sc, struct mpr_command *cm) { MPI2_SCSI_IO_REQUEST *req; req = (MPI2_SCSI_IO_REQUEST *)cm->cm_req; mpr_print_sgl(sc, cm, req->SGLOffset0); } Index: stable/11/sys/dev/mpr/mprvar.h =================================================================== --- stable/11/sys/dev/mpr/mprvar.h (revision 315187) +++ stable/11/sys/dev/mpr/mprvar.h (revision 315188) @@ -1,781 +1,781 @@ /*- * Copyright (c) 2009 Yahoo! Inc. * Copyright (c) 2011-2015 LSI Corp. * Copyright (c) 2013-2016 Avago Technologies * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD * * $FreeBSD$ */ #ifndef _MPRVAR_H #define _MPRVAR_H -#define MPR_DRIVER_VERSION "13.01.00.00-fbsd" +#define MPR_DRIVER_VERSION "15.01.00.00-fbsd" #define MPR_DB_MAX_WAIT 2500 #define MPR_REQ_FRAMES 1024 #define MPR_EVT_REPLY_FRAMES 32 #define MPR_REPLY_FRAMES MPR_REQ_FRAMES #define MPR_CHAIN_FRAMES 2048 #define MPR_MAXIO_PAGES (-1) #define MPR_SENSE_LEN SSD_FULL_SIZE #define MPR_MSI_COUNT 1 #define MPR_SGE64_SIZE 12 #define MPR_SGE32_SIZE 8 #define MPR_SGC_SIZE 8 #define MPR_DEFAULT_CHAIN_SEG_SIZE 8 #define MPR_MAX_CHAIN_ELEMENT_SIZE 16 #define MPR_FUNCTRACE(sc) \ mpr_dprint((sc), MPR_TRACE, "%s\n", __func__) #define CAN_SLEEP 1 #define NO_SLEEP 0 #define MPR_PERIODIC_DELAY 1 /* 1 second heartbeat/watchdog check */ #define MPR_ATA_ID_TIMEOUT 5 /* 5 second timeout for SATA ID cmd */ #define IFAULT_IOP_OVER_TEMP_THRESHOLD_EXCEEDED 0x2810 #define MPR_SCSI_RI_INVALID_FRAME (0x00000002) #define MPR_STRING_LENGTH 64 #define DEFAULT_SPINUP_WAIT 3 /* seconds to wait for spinup */ #include /* * host mapping related macro definitions */ #define MPR_MAPTABLE_BAD_IDX 0xFFFFFFFF #define MPR_DPM_BAD_IDX 0xFFFF #define MPR_ENCTABLE_BAD_IDX 0xFF #define MPR_MAX_MISSING_COUNT 0x0F #define MPR_DEV_RESERVED 0x20000000 #define MPR_MAP_IN_USE 0x10000000 #define MPR_RAID_CHANNEL 1 #define MPR_MAP_BAD_ID 0xFFFFFFFF typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; /** * struct dev_mapping_table - device mapping information * @physical_id: SAS address for drives or WWID for RAID volumes * @device_info: bitfield provides detailed info about the device * @phy_bits: bitfields indicating controller phys * @dpm_entry_num: index of this device in device persistent map table * @dev_handle: device handle for the device pointed by this entry * @channel: target channel * @id: target id * @missing_count: number of times the device not detected by driver * @hide_flag: Hide this physical disk/not (foreign configuration) * @init_complete: Whether the start of the day checks completed or not * @TLR_bits: Turn TLR support on or off */ struct dev_mapping_table { u64 physical_id; u32 device_info; u32 phy_bits; u16 dpm_entry_num; u16 dev_handle; u8 reserved1; u8 channel; u16 id; u8 missing_count; u8 init_complete; u8 TLR_bits; u8 reserved2; }; /** * struct enc_mapping_table - mapping information about an enclosure * @enclosure_id: Logical ID of this enclosure * @start_index: index to the entry in dev_mapping_table * @phy_bits: bitfields indicating controller phys * @dpm_entry_num: index of this enclosure in device persistent map table * @enc_handle: device handle for the enclosure pointed by this entry * @num_slots: number of slots in the enclosure * @start_slot: Starting slot id * @missing_count: number of times the device not detected by driver * @removal_flag: used to mark the device for removal * @skip_search: used as a flag to include/exclude enclosure for search * @init_complete: Whether the start of the day checks completed or not */ struct enc_mapping_table { u64 enclosure_id; u32 start_index; u32 phy_bits; u16 dpm_entry_num; u16 enc_handle; u16 num_slots; u16 start_slot; u8 missing_count; u8 removal_flag; u8 skip_search; u8 init_complete; }; /** * struct map_removal_table - entries to be removed from mapping table * @dpm_entry_num: index of this device in device persistent map table * @dev_handle: device handle for the device pointed by this entry */ struct map_removal_table{ u16 dpm_entry_num; u16 dev_handle; }; typedef struct mpr_fw_diagnostic_buffer { size_t size; uint8_t extended_type; uint8_t buffer_type; uint8_t force_release; uint32_t product_specific[23]; uint8_t immediate; uint8_t enabled; uint8_t valid_data; uint8_t owned_by_firmware; uint32_t unique_id; } mpr_fw_diagnostic_buffer_t; struct mpr_softc; struct mpr_command; struct mprsas_softc; union ccb; struct mprsas_target; struct mpr_column_map; MALLOC_DECLARE(M_MPR); typedef void mpr_evt_callback_t(struct mpr_softc *, uintptr_t, MPI2_EVENT_NOTIFICATION_REPLY *reply); typedef void mpr_command_callback_t(struct mpr_softc *, struct mpr_command *cm); struct mpr_chain { TAILQ_ENTRY(mpr_chain) chain_link; void *chain; uint64_t chain_busaddr; }; /* * This needs to be at least 2 to support SMP passthrough. */ #define MPR_IOVEC_COUNT 2 struct mpr_command { TAILQ_ENTRY(mpr_command) cm_link; TAILQ_ENTRY(mpr_command) cm_recovery; struct mpr_softc *cm_sc; union ccb *cm_ccb; void *cm_data; u_int cm_length; u_int cm_out_len; struct uio cm_uio; struct iovec cm_iovec[MPR_IOVEC_COUNT]; u_int cm_max_segs; u_int cm_sglsize; void *cm_sge; uint8_t *cm_req; uint8_t *cm_reply; uint32_t cm_reply_data; mpr_command_callback_t *cm_complete; void *cm_complete_data; struct mprsas_target *cm_targ; MPI2_REQUEST_DESCRIPTOR_UNION cm_desc; u_int cm_lun; u_int cm_flags; #define MPR_CM_FLAGS_POLLED (1 << 0) #define MPR_CM_FLAGS_COMPLETE (1 << 1) #define MPR_CM_FLAGS_SGE_SIMPLE (1 << 2) #define MPR_CM_FLAGS_DATAOUT (1 << 3) #define MPR_CM_FLAGS_DATAIN (1 << 4) #define MPR_CM_FLAGS_WAKEUP (1 << 5) #define MPR_CM_FLAGS_USE_UIO (1 << 6) #define MPR_CM_FLAGS_SMP_PASS (1 << 7) #define MPR_CM_FLAGS_CHAIN_FAILED (1 << 8) #define MPR_CM_FLAGS_ERROR_MASK MPR_CM_FLAGS_CHAIN_FAILED #define MPR_CM_FLAGS_USE_CCB (1 << 9) #define MPR_CM_FLAGS_SATA_ID_TIMEOUT (1 << 10) u_int cm_state; #define MPR_CM_STATE_FREE 0 #define MPR_CM_STATE_BUSY 1 #define MPR_CM_STATE_TIMEDOUT 2 bus_dmamap_t cm_dmamap; struct scsi_sense_data *cm_sense; TAILQ_HEAD(, mpr_chain) cm_chain_list; uint32_t cm_req_busaddr; uint32_t cm_sense_busaddr; struct callout cm_callout; }; struct mpr_column_map { uint16_t dev_handle; uint8_t phys_disk_num; }; struct mpr_event_handle { TAILQ_ENTRY(mpr_event_handle) eh_list; mpr_evt_callback_t *callback; void *data; uint8_t mask[16]; }; struct mpr_softc { device_t mpr_dev; struct cdev *mpr_cdev; u_int mpr_flags; #define MPR_FLAGS_INTX (1 << 0) #define MPR_FLAGS_MSI (1 << 1) #define MPR_FLAGS_BUSY (1 << 2) #define MPR_FLAGS_SHUTDOWN (1 << 3) #define MPR_FLAGS_DIAGRESET (1 << 4) #define MPR_FLAGS_ATTACH_DONE (1 << 5) u_int mpr_debug; u_int disable_msix; u_int disable_msi; int tm_cmds_active; int io_cmds_active; int io_cmds_highwater; int chain_free; int max_chains; int max_io_pages; int chain_free_lowwater; uint32_t chain_frame_size; uint16_t chain_seg_size; u_int enable_ssu; int spinup_wait_time; uint64_t chain_alloc_fail; struct sysctl_ctx_list sysctl_ctx; struct sysctl_oid *sysctl_tree; char fw_version[16]; struct mpr_command *commands; struct mpr_chain *chains; struct callout periodic; struct mprsas_softc *sassc; char tmp_string[MPR_STRING_LENGTH]; TAILQ_HEAD(, mpr_command) req_list; TAILQ_HEAD(, mpr_command) high_priority_req_list; TAILQ_HEAD(, mpr_chain) chain_list; TAILQ_HEAD(, mpr_command) tm_list; int replypostindex; int replyfreeindex; struct resource *mpr_regs_resource; bus_space_handle_t mpr_bhandle; bus_space_tag_t mpr_btag; int mpr_regs_rid; bus_dma_tag_t mpr_parent_dmat; bus_dma_tag_t buffer_dmat; MPI2_IOC_FACTS_REPLY *facts; int num_reqs; int num_replies; int fqdepth; /* Free queue */ int pqdepth; /* Post queue */ uint8_t event_mask[16]; TAILQ_HEAD(, mpr_event_handle) event_list; struct mpr_event_handle *mpr_log_eh; struct mtx mpr_mtx; struct intr_config_hook mpr_ich; struct resource *mpr_irq[MPR_MSI_COUNT]; void *mpr_intrhand[MPR_MSI_COUNT]; int mpr_irq_rid[MPR_MSI_COUNT]; uint8_t *req_frames; bus_addr_t req_busaddr; bus_dma_tag_t req_dmat; bus_dmamap_t req_map; uint8_t *reply_frames; bus_addr_t reply_busaddr; bus_dma_tag_t reply_dmat; bus_dmamap_t reply_map; struct scsi_sense_data *sense_frames; bus_addr_t sense_busaddr; bus_dma_tag_t sense_dmat; bus_dmamap_t sense_map; uint8_t *chain_frames; bus_addr_t chain_busaddr; bus_dma_tag_t chain_dmat; bus_dmamap_t chain_map; MPI2_REPLY_DESCRIPTORS_UNION *post_queue; bus_addr_t post_busaddr; uint32_t *free_queue; bus_addr_t free_busaddr; bus_dma_tag_t queues_dmat; bus_dmamap_t queues_map; uint8_t *fw_diag_buffer; bus_addr_t fw_diag_busaddr; bus_dma_tag_t fw_diag_dmat; bus_dmamap_t fw_diag_map; uint8_t ir_firmware; /* static config pages */ Mpi2IOCPage8_t ioc_pg8; Mpi2IOUnitPage8_t iounit_pg8; /* host mapping support */ struct dev_mapping_table *mapping_table; struct enc_mapping_table *enclosure_table; struct map_removal_table *removal_table; uint8_t *dpm_entry_used; uint8_t *dpm_flush_entry; Mpi2DriverMappingPage0_t *dpm_pg0; uint16_t max_devices; uint16_t max_enclosures; uint16_t max_expanders; uint8_t max_volumes; uint8_t num_enc_table_entries; uint8_t num_rsvd_entries; uint8_t num_channels; uint16_t max_dpm_entries; uint8_t is_dpm_enable; uint8_t track_mapping_events; uint32_t pending_map_events; uint8_t mt_full_retry; uint8_t mt_add_device_failed; /* FW diag Buffer List */ mpr_fw_diagnostic_buffer_t fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_COUNT]; /* Event Recording IOCTL support */ uint32_t events_to_record[4]; mpr_event_entry_t recorded_events[MPR_EVENT_QUEUE_SIZE]; uint8_t event_index; uint32_t event_number; /* EEDP and TLR support */ uint8_t eedp_enabled; uint8_t control_TLR; /* Shutdown Event Handler */ eventhandler_tag shutdown_eh; /* To track topo events during reset */ #define MPR_DIAG_RESET_TIMEOUT 300000 uint8_t wait_for_port_enable; uint8_t port_enable_complete; uint8_t msleep_fake_chan; /* StartStopUnit command handling at shutdown */ uint32_t SSU_refcount; uint8_t SSU_started; char exclude_ids[80]; struct timeval lastfail; }; struct mpr_config_params { MPI2_CONFIG_EXT_PAGE_HEADER_UNION hdr; u_int action; u_int page_address; /* Attributes, not a phys address */ u_int status; void *buffer; u_int length; int timeout; void (*callback)(struct mpr_softc *, struct mpr_config_params *); void *cbdata; }; struct scsi_read_capacity_eedp { uint8_t addr[8]; uint8_t length[4]; uint8_t protect; }; static __inline uint32_t mpr_regread(struct mpr_softc *sc, uint32_t offset) { return (bus_space_read_4(sc->mpr_btag, sc->mpr_bhandle, offset)); } static __inline void mpr_regwrite(struct mpr_softc *sc, uint32_t offset, uint32_t val) { bus_space_write_4(sc->mpr_btag, sc->mpr_bhandle, offset, val); } /* free_queue must have Little Endian address * TODO- cm_reply_data is unwanted. We can remove it. * */ static __inline void mpr_free_reply(struct mpr_softc *sc, uint32_t busaddr) { if (++sc->replyfreeindex >= sc->fqdepth) sc->replyfreeindex = 0; sc->free_queue[sc->replyfreeindex] = htole32(busaddr); mpr_regwrite(sc, MPI2_REPLY_FREE_HOST_INDEX_OFFSET, sc->replyfreeindex); } static __inline struct mpr_chain * mpr_alloc_chain(struct mpr_softc *sc) { struct mpr_chain *chain; if ((chain = TAILQ_FIRST(&sc->chain_list)) != NULL) { TAILQ_REMOVE(&sc->chain_list, chain, chain_link); sc->chain_free--; if (sc->chain_free < sc->chain_free_lowwater) sc->chain_free_lowwater = sc->chain_free; } else sc->chain_alloc_fail++; return (chain); } static __inline void mpr_free_chain(struct mpr_softc *sc, struct mpr_chain *chain) { #if 0 bzero(chain->chain, 128); #endif sc->chain_free++; TAILQ_INSERT_TAIL(&sc->chain_list, chain, chain_link); } static __inline void mpr_free_command(struct mpr_softc *sc, struct mpr_command *cm) { struct mpr_chain *chain, *chain_temp; if (cm->cm_reply != NULL) mpr_free_reply(sc, cm->cm_reply_data); cm->cm_reply = NULL; cm->cm_flags = 0; cm->cm_complete = NULL; cm->cm_complete_data = NULL; cm->cm_ccb = NULL; cm->cm_targ = NULL; cm->cm_max_segs = 0; cm->cm_lun = 0; cm->cm_state = MPR_CM_STATE_FREE; cm->cm_data = NULL; cm->cm_length = 0; cm->cm_out_len = 0; cm->cm_sglsize = 0; cm->cm_sge = NULL; TAILQ_FOREACH_SAFE(chain, &cm->cm_chain_list, chain_link, chain_temp) { TAILQ_REMOVE(&cm->cm_chain_list, chain, chain_link); mpr_free_chain(sc, chain); } TAILQ_INSERT_TAIL(&sc->req_list, cm, cm_link); } static __inline struct mpr_command * mpr_alloc_command(struct mpr_softc *sc) { struct mpr_command *cm; cm = TAILQ_FIRST(&sc->req_list); if (cm == NULL) return (NULL); TAILQ_REMOVE(&sc->req_list, cm, cm_link); KASSERT(cm->cm_state == MPR_CM_STATE_FREE, ("mpr: Allocating busy command\n")); cm->cm_state = MPR_CM_STATE_BUSY; return (cm); } static __inline void mpr_free_high_priority_command(struct mpr_softc *sc, struct mpr_command *cm) { struct mpr_chain *chain, *chain_temp; if (cm->cm_reply != NULL) mpr_free_reply(sc, cm->cm_reply_data); cm->cm_reply = NULL; cm->cm_flags = 0; cm->cm_complete = NULL; cm->cm_complete_data = NULL; cm->cm_ccb = NULL; cm->cm_targ = NULL; cm->cm_lun = 0; cm->cm_state = MPR_CM_STATE_FREE; TAILQ_FOREACH_SAFE(chain, &cm->cm_chain_list, chain_link, chain_temp) { TAILQ_REMOVE(&cm->cm_chain_list, chain, chain_link); mpr_free_chain(sc, chain); } TAILQ_INSERT_TAIL(&sc->high_priority_req_list, cm, cm_link); } static __inline struct mpr_command * mpr_alloc_high_priority_command(struct mpr_softc *sc) { struct mpr_command *cm; cm = TAILQ_FIRST(&sc->high_priority_req_list); if (cm == NULL) return (NULL); TAILQ_REMOVE(&sc->high_priority_req_list, cm, cm_link); KASSERT(cm->cm_state == MPR_CM_STATE_FREE, ("mpr: Allocating busy command\n")); cm->cm_state = MPR_CM_STATE_BUSY; return (cm); } static __inline void mpr_lock(struct mpr_softc *sc) { mtx_lock(&sc->mpr_mtx); } static __inline void mpr_unlock(struct mpr_softc *sc) { mtx_unlock(&sc->mpr_mtx); } #define MPR_INFO (1 << 0) /* Basic info */ #define MPR_FAULT (1 << 1) /* Hardware faults */ #define MPR_EVENT (1 << 2) /* Event data from the controller */ #define MPR_LOG (1 << 3) /* Log data from the controller */ #define MPR_RECOVERY (1 << 4) /* Command error recovery tracing */ #define MPR_ERROR (1 << 5) /* Parameter errors, programming bugs */ #define MPR_INIT (1 << 6) /* Things related to system init */ #define MPR_XINFO (1 << 7) /* More detailed/noisy info */ #define MPR_USER (1 << 8) /* Trace user-generated commands */ #define MPR_MAPPING (1 << 9) /* Trace device mappings */ #define MPR_TRACE (1 << 10) /* Function-by-function trace */ #define MPR_SSU_DISABLE_SSD_DISABLE_HDD 0 #define MPR_SSU_ENABLE_SSD_DISABLE_HDD 1 #define MPR_SSU_DISABLE_SSD_ENABLE_HDD 2 #define MPR_SSU_ENABLE_SSD_ENABLE_HDD 3 #define mpr_printf(sc, args...) \ device_printf((sc)->mpr_dev, ##args) #define mpr_vprintf(sc, args...) \ do { \ if (bootverbose) \ mpr_printf(sc, ##args); \ } while (0) #define mpr_dprint(sc, level, msg, args...) \ do { \ if ((sc)->mpr_debug & (level)) \ device_printf((sc)->mpr_dev, msg, ##args); \ } while (0) #define mpr_dprint_field(sc, level, msg, args...) \ do { \ if ((sc)->mpr_debug & (level)) \ printf("\t" msg, ##args); \ } while (0) #define MPR_PRINTFIELD_START(sc, tag...) \ mpr_dprint((sc), MPR_INFO, ##tag); \ mpr_dprint_field((sc), MPR_INFO, ":\n") #define MPR_PRINTFIELD_END(sc, tag) \ mpr_dprint((sc), MPR_INFO, tag "\n") #define MPR_PRINTFIELD(sc, facts, attr, fmt) \ mpr_dprint_field((sc), MPR_INFO, #attr ": " #fmt "\n", (facts)->attr) #define MPR_EVENTFIELD_START(sc, tag...) \ mpr_dprint((sc), MPR_EVENT, ##tag); \ mpr_dprint_field((sc), MPR_EVENT, ":\n") #define MPR_EVENTFIELD(sc, facts, attr, fmt) \ mpr_dprint_field((sc), MPR_EVENT, #attr ": " #fmt "\n", (facts)->attr) static __inline void mpr_from_u64(uint64_t data, U64 *mpr) { (mpr)->High = htole32((uint32_t)((data) >> 32)); (mpr)->Low = htole32((uint32_t)((data) & 0xffffffff)); } static __inline uint64_t mpr_to_u64(U64 *data) { return (((uint64_t)le32toh(data->High) << 32) | le32toh(data->Low)); } static __inline void mpr_mask_intr(struct mpr_softc *sc) { uint32_t mask; mask = mpr_regread(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET); mask |= MPI2_HIM_REPLY_INT_MASK; mpr_regwrite(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET, mask); } static __inline void mpr_unmask_intr(struct mpr_softc *sc) { uint32_t mask; mask = mpr_regread(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET); mask &= ~MPI2_HIM_REPLY_INT_MASK; mpr_regwrite(sc, MPI2_HOST_INTERRUPT_MASK_OFFSET, mask); } int mpr_pci_setup_interrupts(struct mpr_softc *sc); int mpr_pci_restore(struct mpr_softc *sc); int mpr_attach(struct mpr_softc *sc); int mpr_free(struct mpr_softc *sc); void mpr_intr(void *); void mpr_intr_msi(void *); void mpr_intr_locked(void *); int mpr_register_events(struct mpr_softc *, uint8_t *, mpr_evt_callback_t *, void *, struct mpr_event_handle **); int mpr_restart(struct mpr_softc *); int mpr_update_events(struct mpr_softc *, struct mpr_event_handle *, uint8_t *); int mpr_deregister_events(struct mpr_softc *, struct mpr_event_handle *); int mpr_push_sge(struct mpr_command *, MPI2_SGE_SIMPLE64 *, size_t, int); int mpr_push_ieee_sge(struct mpr_command *, void *, int); int mpr_add_dmaseg(struct mpr_command *, vm_paddr_t, size_t, u_int, int); int mpr_attach_sas(struct mpr_softc *sc); int mpr_detach_sas(struct mpr_softc *sc); int mpr_read_config_page(struct mpr_softc *, struct mpr_config_params *); int mpr_write_config_page(struct mpr_softc *, struct mpr_config_params *); void mpr_memaddr_cb(void *, bus_dma_segment_t *, int , int ); void mpr_init_sge(struct mpr_command *cm, void *req, void *sge); int mpr_attach_user(struct mpr_softc *); void mpr_detach_user(struct mpr_softc *); void mprsas_record_event(struct mpr_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event_reply); int mpr_map_command(struct mpr_softc *sc, struct mpr_command *cm); int mpr_wait_command(struct mpr_softc *sc, struct mpr_command *cm, int timeout, int sleep_flag); int mpr_request_polled(struct mpr_softc *sc, struct mpr_command *cm); int mpr_config_get_bios_pg3(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage3_t *config_page); int mpr_config_get_raid_volume_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 page_address); int mpr_config_get_ioc_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *, Mpi2IOCPage8_t *); int mpr_config_get_iounit_pg8(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page); int mpr_config_get_sas_device_pg0(struct mpr_softc *, Mpi2ConfigReply_t *, Mpi2SasDevicePage0_t *, u32 , u16 ); int mpr_config_get_dpm_pg0(struct mpr_softc *, Mpi2ConfigReply_t *, Mpi2DriverMappingPage0_t *, u16 ); int mpr_config_get_raid_volume_pg1(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u16 handle); int mpr_config_get_volume_wwid(struct mpr_softc *sc, u16 volume_handle, u64 *wwid); int mpr_config_get_raid_pd_pg0(struct mpr_softc *sc, Mpi2ConfigReply_t *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 page_address); void mprsas_ir_shutdown(struct mpr_softc *sc); int mpr_reinit(struct mpr_softc *sc); void mprsas_handle_reinit(struct mpr_softc *sc); void mpr_base_static_config_pages(struct mpr_softc *sc); int mpr_mapping_initialize(struct mpr_softc *); void mpr_mapping_topology_change_event(struct mpr_softc *, Mpi2EventDataSasTopologyChangeList_t *); int mpr_mapping_is_reinit_required(struct mpr_softc *); void mpr_mapping_free_memory(struct mpr_softc *sc); int mpr_config_set_dpm_pg0(struct mpr_softc *, Mpi2ConfigReply_t *, Mpi2DriverMappingPage0_t *, u16 ); void mpr_mapping_exit(struct mpr_softc *); void mpr_mapping_check_devices(struct mpr_softc *, int); int mpr_mapping_allocate_memory(struct mpr_softc *sc); unsigned int mpr_mapping_get_sas_id(struct mpr_softc *, uint64_t , u16); unsigned int mpr_mapping_get_sas_id_from_handle(struct mpr_softc *sc, u16 handle); unsigned int mpr_mapping_get_raid_id(struct mpr_softc *sc, u64 wwid, u16 handle); unsigned int mpr_mapping_get_raid_id_from_handle(struct mpr_softc *sc, u16 volHandle); void mpr_mapping_enclosure_dev_status_change_event(struct mpr_softc *, Mpi2EventDataSasEnclDevStatusChange_t *event_data); void mpr_mapping_ir_config_change_event(struct mpr_softc *sc, Mpi2EventDataIrConfigChangeList_t *event_data); void mprsas_evt_handler(struct mpr_softc *sc, uintptr_t data, MPI2_EVENT_NOTIFICATION_REPLY *event); void mprsas_prepare_remove(struct mprsas_softc *sassc, uint16_t handle); void mprsas_prepare_volume_remove(struct mprsas_softc *sassc, uint16_t handle); int mprsas_startup(struct mpr_softc *sc); struct mprsas_target * mprsas_find_target_by_handle(struct mprsas_softc *, int, uint16_t); void mprsas_realloc_targets(struct mpr_softc *sc, int maxtargets); struct mpr_command * mprsas_alloc_tm(struct mpr_softc *sc); void mprsas_free_tm(struct mpr_softc *sc, struct mpr_command *tm); void mprsas_release_simq_reinit(struct mprsas_softc *sassc); int mprsas_send_reset(struct mpr_softc *sc, struct mpr_command *tm, uint8_t type); SYSCTL_DECL(_hw_mpr); /* Compatibility shims for different OS versions */ #if __FreeBSD_version >= 800001 #define mpr_kproc_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \ kproc_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) #define mpr_kproc_exit(arg) kproc_exit(arg) #else #define mpr_kproc_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \ kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) #define mpr_kproc_exit(arg) kthread_exit(arg) #endif #if defined(CAM_PRIORITY_XPT) #define MPR_PRIORITY_XPT CAM_PRIORITY_XPT #else #define MPR_PRIORITY_XPT 5 #endif #if __FreeBSD_version < 800107 // Prior to FreeBSD-8.0 scp3_flags was not defined. #define spc3_flags reserved #define SPC3_SID_PROTECT 0x01 #define SPC3_SID_3PC 0x08 #define SPC3_SID_TPGS_MASK 0x30 #define SPC3_SID_TPGS_IMPLICIT 0x10 #define SPC3_SID_TPGS_EXPLICIT 0x20 #define SPC3_SID_ACC 0x40 #define SPC3_SID_SCCS 0x80 #define CAM_PRIORITY_NORMAL CAM_PRIORITY_NONE #endif #endif Index: stable/11 =================================================================== --- stable/11 (revision 315187) +++ stable/11 (revision 315188) Property changes on: stable/11 ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r314786