#!/usr/sbin/dtrace -Cs /* Copyright (c) 2016 Jens Elkner. All rights reserved. License: CDDL 1.0 Usage example: # optional (5 is max.): setenv _LIBDEVINFO_DEBUG 5 setenv CTRL_IDX 0 setenv SAS2IRCU /net/software/export/install/dos/flashutils.dsk/lsi/P18/sas2ircu + ~/sas2ircu.d -c "${SAS2IRCU} ${CTRL_IDX} LOCATE 1:3 ON" + ~/sas2ircu.d -c "${SAS2IRCU} ${CTRL_IDX} LOCATE 1:3 OFF" # to show all mpt_sas calls, add '-DVERBOSE=1' above # grep for CmndLocate in the output to find the interesting stuff faster # If in doubt, get info about HBAs: setenv LSIUTIL /net/software/export/install/dos/flashutils.dsk/lsi/lsiutil + ${LSIUTIL} -p ${CTRL_IDX}+1 16 #pragma D option aggsize=128m #pragma D option destructive */ /* flush dtrace buffers ASAP to align the output with the util output */ #pragma D option switchrate=1 #pragma D option quiet #pragma D option defaultargs #ifndef VERBOSE #define VERBOSE 0 #endif /* mptsas_ioctl.h */ #define MPTIOCTL ('I' << 8) #define MPTIOCTL_GET_ADAPTER_DATA (MPTIOCTL | 1) #define MPTIOCTL_UPDATE_FLASH (MPTIOCTL | 2) #define MPTIOCTL_RESET_ADAPTER (MPTIOCTL | 3) #define MPTIOCTL_PASS_THRU (MPTIOCTL | 4) #define MPTIOCTL_EVENT_QUERY (MPTIOCTL | 5) #define MPTIOCTL_EVENT_ENABLE (MPTIOCTL | 6) #define MPTIOCTL_EVENT_REPORT (MPTIOCTL | 7) #define MPTIOCTL_GET_PCI_INFO (MPTIOCTL | 8) #define MPTIOCTL_DIAG_ACTION (MPTIOCTL | 9) #define MPTIOCTL_REG_ACCESS (MPTIOCTL | 10) #define MPTIOCTL_GET_DISK_INFO (MPTIOCTL | 11) #define MPTIOCTL_LED_CONTROL (MPTIOCTL | 12) #define CMD2STR(s, x) \ s=((x) < (MPTIOCTL+1) || (x) > (MPTIOCTL+12)) ? "UNKNOWN" : CMD[(x) & 0xFF] string CMD[13]; /* DIRECTION => DataSize DataOutSize */ #define MPTSAS_PASS_THRU_DIRECTION_NONE 0 /* == 0 == 0 */ #define MPTSAS_PASS_THRU_DIRECTION_READ 1 /* != 0 */ #define MPTSAS_PASS_THRU_DIRECTION_WRITE 2 /* != 0 */ #define MPTSAS_PASS_THRU_DIRECTION_BOTH 3 /* != 0 != 0 */ #define MPTSAS_PASS_THRU_DIRECTION_MAX 4 #define DIR2STR(s, x) \ s = (x) >= MPTSAS_PASS_THRU_DIRECTION_MAX ? "UNKNOWN" : DIR[(x)] string DIR[MPTSAS_PASS_THRU_DIRECTION_MAX]; typedef struct mptsas_pass_thru { uint64_t PtrRequest; /* uint8_t *request */ uint64_t PtrReply; /* uint8_t *reply */ uint64_t PtrData; /* uint8_t *data */ uint32_t RequestSize; /* request_size */ uint32_t ReplySize; /* reply_size */ uint32_t DataSize; /* data_size */ uint32_t DataDirection; /* direction */ uint64_t PtrDataOut; /* uint8_t *dataout */ uint32_t DataOutSize; /* dataout_size */ uint32_t Timeout; /* command timeout: if 0 use default (60s) */ } mptsas_pass_thru_t; /* mpi2.h */ #define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) #define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01) #define MPI2_FUNCTION_IOC_INIT (0x02) #define MPI2_FUNCTION_IOC_FACTS (0x03) #define MPI2_FUNCTION_CONFIG (0x04) #define MPI2_FUNCTION_PORT_FACTS (0x05) #define MPI2_FUNCTION_PORT_ENABLE (0x06) #define MPI2_FUNCTION_EVENT_NOTIFICATION (0x07) #define MPI2_FUNCTION_EVENT_ACK (0x08) #define MPI2_FUNCTION_FW_DOWNLOAD (0x09) #define MPI2_FUNCTION_TARGET_ASSIST (0x0B) #define MPI2_FUNCTION_TARGET_STATUS_SEND (0x0C) #define MPI2_FUNCTION_TARGET_MODE_ABORT (0x0D) #define MPI2_FUNCTION_FW_UPLOAD (0x12) #define MPI2_FUNCTION_RAID_ACTION (0x15) #define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH (0x16) #define MPI2_FUNCTION_TOOLBOX (0x17) #define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) #define MPI2_FUNCTION_SMP_PASSTHROUGH (0x1A) #define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) #define MPI2_FUNCTION_SATA_PASSTHROUGH (0x1C) #define MPI2_FUNCTION_DIAG_BUFFER_POST (0x1D) #define MPI2_FUNCTION_DIAG_RELEASE (0x1E) #define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) #define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) #define MPI2_FUNCTION_RAID_ACCELERATOR (0x2C) #define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION (0x2F) #define MPI2_FUNCTION_PWR_MGMT_CONTROL (0x30) #define MPI2_FUNCTION_SEND_HOST_MESSAGE (0x31) #define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0) #define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF) #define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40) #define MPI2_FUNCTION_HANDSHAKE (0x42) #define FN2STR(s, x) \ s = ((x) >= 0xF0) \ ? "PRODUCT_SPECIFIC" \ : (x) > 0x42 \ ? "UNKNOWN" \ : (x) >= 0x40 \ ? FN2[(x)-0x40] \ : FN1[(x)] string FN1[0x32]; string FN2[0x3]; /* IOC Status Values */ #define MPI2_IOCSTATUS_MASK (0x7FFF) #define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000) #define MPI2_IOCSTATUS_SUCCESS (0x0000) #define MPI2_IOCSTATUS_INVALID_FUNCTION (0x0001) #define MPI2_IOCSTATUS_BUSY (0x0002) #define MPI2_IOCSTATUS_INVALID_SGL (0x0003) #define MPI2_IOCSTATUS_INTERNAL_ERROR (0x0004) #define MPI2_IOCSTATUS_INVALID_VPID (0x0005) #define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006) #define MPI2_IOCSTATUS_INVALID_FIELD (0x0007) #define MPI2_IOCSTATUS_INVALID_STATE (0x0008) #define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009) #define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) #define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) #define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) #define MPI2_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) #define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) #define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) #define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040) #define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE (0x0042) #define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043) #define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044) #define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045) #define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046) #define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) #define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) #define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) #define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) #define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) #define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) #define MPI2_IOCSTATUS_EEDP_GUARD_ERROR (0x004D) #define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E) #define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F) #define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062) #define MPI2_IOCSTATUS_TARGET_ABORTED (0x0063) #define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064) #define MPI2_IOCSTATUS_TARGET_NO_CONNECTION (0x0065) #define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A) #define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) #define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) #define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) #define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070) #define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071) #define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) #define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091) #define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) #define MPI2_IOCSTATUS_RAID_ACCEL_ERROR (0x00B0) #define IOCSTATUS2STR(s, v) \ this->i = ((v) & MPI2_IOCSTATUS_MASK); \ s = this->i > 0x00B0 \ ? "UNKNOWN" \ : (this->i == 0x00B0) \ ? "RAID_ACCEL_ERROR" \ : (this->i > 80) \ ? IOCSTATUS3[this->i - 0x80] \ : (this->i > 40) \ ? IOCSTATUS2[this->i - 0x40] \ : IOCSTATUS1[this->i] string IOCSTATUS1[0x26]; string IOCSTATUS2[0x32]; string IOCSTATUS3[0x31]; /* IOCLogInfo Types */ #define MPI2_IOCLOGINFO_TYPE_MASK (0xF0000000) #define MPI2_IOCLOGINFO_TYPE_SHIFT (28) #define MPI2_IOCLOGINFO_TYPE_NONE (0x0) #define MPI2_IOCLOGINFO_TYPE_SCSI (0x1) #define MPI2_IOCLOGINFO_TYPE_FC (0x2) #define MPI2_IOCLOGINFO_TYPE_SAS (0x3) #define MPI2_IOCLOGINFO_TYPE_ISCSI (0x4) #define MPI2_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF) #define LOGINFO2STR(s, t) \ this->l = ((t) & MPI2_IOCLOGINFO_TYPE_MASK) >> MPI2_IOCLOGINFO_TYPE_SHIFT;\ s = (this->l > 0x4) ? "UNKNOWN" : LOGINFOT[this->l] string LOGINFOT[5]; /* mpi2_init.h */ #define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS (0x00) #define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01) #define RFLAG2STR(x) \ (((x) < 0 || (x) > 0x1) ? "UNKNOWN" : RFLAG[(x)]) string RFLAG[2]; #define MPI2_SEP_REQ_ACTION_WRITE_STATUS (0x00) #define MPI2_SEP_REQ_ACTION_READ_STATUS (0x01) #define ACTION2STR(x) \ (((x) < 0 || (x) > 0x1) ? "UNKNOWN" : ACTION[(x)]) string ACTION[2]; #define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000) #define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) #define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200) #define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100) #define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080) #define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040) #define MPI2_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) #define MPI2_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) #define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004) #define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002) #define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001) #define I2S(s, mask, name, val) \ s = (val & mask) ? strjoin(s, name) : (s) #define SLOTSTATUS2STR(s, x) \ s = ""; \ s = I2S((s), MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE, "|REQUEST_REMOVE", (x));\ s = I2S((s), MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST, "|IDENTIFY_REQUEST", (x)); \ s = I2S((s), MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED, "|REBUILD_STOPPED", (x)); \ s = I2S((s), MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE, "|HOT_SPARE", (x)); \ s = I2S((s), MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED, "|UNCONFIGURED", (x)); \ s = I2S((s), MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT, "|PREDICTED_FAULT", (x)); \ s = I2S((s), MPI2_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY, "|IN_CRITICAL_ARRAY", (x)); \ s = I2S((s), MPI2_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY, "|IN_FAILED_ARRAY", (x)); \ s = I2S((s), MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING, "|DEV_REBUILDING", (x)); \ s = I2S((s), MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY, "|DEV_FAULTY", (x)); \ s = I2S((s), MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR, "|NO_ERROR", (x)) typedef struct _MPI2_SEP_REQUEST { U16 DevHandle; /* 0x00 */ U8 ChainOffset; /* 0x02 */ U8 Function; /* 0x03 */ U8 Action; /* 0x04 */ U8 Flags; /* 0x05 */ U8 Reserved1; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved2; /* 0x0A */ U32 SlotStatus; /* 0x0C */ U32 Reserved3; /* 0x10 */ U32 Reserved4; /* 0x14 */ U32 Reserved5; /* 0x18 */ U16 Slot; /* 0x1C */ U16 EnclosureHandle; /* 0x1E */ } MPI2_SEP_REQUEST, *PTR_MPI2_SEP_REQUEST, Mpi2SepRequest_t, *pMpi2SepRequest_t; typedef struct _MPI2_SEP_REPLY { U16 DevHandle; /* 0x00 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U8 Action; /* 0x04 */ U8 Flags; /* 0x05 */ U8 Reserved1; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved2; /* 0x0A */ U16 Reserved3; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ U32 SlotStatus; /* 0x14 */ U32 Reserved4; /* 0x18 */ U16 Slot; /* 0x1C */ U16 EnclosureHandle; /* 0x1E */ } MPI2_SEP_REPLY, *PTR_MPI2_SEP_REPLY, Mpi2SepReply_t, *pMpi2SepReply_t; typedef struct _MPI2_DEFAULT_REPLY { U16 FunctionDependent1; /* 0x00 */ U8 MsgLength; /* 0x02 */ U8 Function; /* 0x03 */ U16 FunctionDependent2; /* 0x04 */ U8 FunctionDependent3; /* 0x06 */ U8 MsgFlags; /* 0x07 */ U8 VP_ID; /* 0x08 */ U8 VF_ID; /* 0x09 */ U16 Reserved1; /* 0x0A */ U16 FunctionDependent5; /* 0x0C */ U16 IOCStatus; /* 0x0E */ U32 IOCLogInfo; /* 0x10 */ } MPI2_DEFAULT_REPLY, *PTR_MPI2_DEFAULT_REPLY, MPI2DefaultReply_t, *pMPI2DefaultReply_t; dtrace:::BEGIN { /* grep '^#define MPI2_SEP_REQ_FLAGS_' ~/sas2ircu.d | \ sed -e 's,.*FLAGS_,,' -e 's,_ADDRESS,,' | \ nawk '{ print "\tRFLAG[MPI2_SEP_REQ_FLAGS_" $1 "_ADDRESS]=\"" $1 "\";"}' */ RFLAG[MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS]="DEVHANDLE"; RFLAG[MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS]="ENCLOSURE_SLOT"; /* grep '^#define MPI2_SEP_REQ_ACTION_' ~/sas2ircu.d | \ sed -e 's,.*ACTION_,,' | \ nawk '{ print "\tACTION[MPI2_SEP_REQ_ACTION_" $1 "]=\"" $1 "\";" }' */ ACTION[MPI2_SEP_REQ_ACTION_WRITE_STATUS]="WRITE_STATUS"; ACTION[MPI2_SEP_REQ_ACTION_READ_STATUS]="READ_STATUS"; /* grep '^#define MPTSAS_PASS_THRU_DIRECTION_' ~/sas2ircu.d | \ sed -e 's,.*DIRECTION_,,' | \ nawk '/MAX/ { next; } { print "\tDIR[MPTSAS_PASS_THRU_DIRECTION_" $1 "]=\"" $1 "\";" }' */ DIR[MPTSAS_PASS_THRU_DIRECTION_NONE]="NONE"; DIR[MPTSAS_PASS_THRU_DIRECTION_READ]="READ"; DIR[MPTSAS_PASS_THRU_DIRECTION_WRITE]="WRITE"; DIR[MPTSAS_PASS_THRU_DIRECTION_BOTH]="BOTH"; /* grep '^#define MPTIOCTL_' ~/sas2ircu.d | \ sed -e 's,.*MPTIOCTL_,,' -e 's,[\)],,' | \ nawk '{ print "\tCMD[" $4 "]=\"" $1 "\";" }' */ CMD[1]="GET_ADAPTER_DATA"; CMD[2]="UPDATE_FLASH"; CMD[3]="RESET_ADAPTER"; CMD[4]="PASS_THRU"; CMD[5]="EVENT_QUERY"; CMD[6]="EVENT_ENABLE"; CMD[7]="EVENT_REPORT"; CMD[8]="GET_PCI_INFO"; CMD[9]="DIAG_ACTION"; CMD[10]="REG_ACCESS"; CMD[11]="GET_DISK_INFO"; CMD[12]="LED_CONTROL"; /* grep '^#define MPI2_IOCLOGINFO_TYPE_.*0x[0-9])' ~/sas2ircu.d | \ sed -e 's,.*TYPE_,,' | \ nawk '{ print "LOGINFOT[MPI2_IOCLOGINFO_TYPE_" $1 "]=\"" $1 "\";" }' */ LOGINFOT[MPI2_IOCLOGINFO_TYPE_NONE]="NONE"; LOGINFOT[MPI2_IOCLOGINFO_TYPE_SCSI]="SCSI"; LOGINFOT[MPI2_IOCLOGINFO_TYPE_FC]="FC"; LOGINFOT[MPI2_IOCLOGINFO_TYPE_SAS]="SAS"; LOGINFOT[MPI2_IOCLOGINFO_TYPE_ISCSI]="ISCSI"; /* grep '^#define MPI2_IOCSTATUS_' ~/sas2ircu.d | \ sed -e 's,.*IOCSTATUS_,,' -e 's,[\(\)],,g' | \ ksh -c 'integer B; while read A B; do (( B >= 0x00B0 )) && continue; X=1; O=0; (( B >= 0x80 )) && { X=3; O=0x80; } || { (( B >= 0x40 )) && X=2 && O=0x40; } ; print "\tIOCSTATUS$X[MPI2_IOCSTATUS_${A}-$O]=\"$A\";" ; done' */ IOCSTATUS1[MPI2_IOCSTATUS_SUCCESS-0]="SUCCESS"; IOCSTATUS1[MPI2_IOCSTATUS_INVALID_FUNCTION-0]="INVALID_FUNCTION"; IOCSTATUS1[MPI2_IOCSTATUS_BUSY-0]="BUSY"; IOCSTATUS1[MPI2_IOCSTATUS_INVALID_SGL-0]="INVALID_SGL"; IOCSTATUS1[MPI2_IOCSTATUS_INTERNAL_ERROR-0]="INTERNAL_ERROR"; IOCSTATUS1[MPI2_IOCSTATUS_INVALID_VPID-0]="INVALID_VPID"; IOCSTATUS1[MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES-0]="INSUFFICIENT_RESOURCES"; IOCSTATUS1[MPI2_IOCSTATUS_INVALID_FIELD-0]="INVALID_FIELD"; IOCSTATUS1[MPI2_IOCSTATUS_INVALID_STATE-0]="INVALID_STATE"; IOCSTATUS1[MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED-0]="OP_STATE_NOT_SUPPORTED"; IOCSTATUS1[MPI2_IOCSTATUS_CONFIG_INVALID_ACTION-0]="CONFIG_INVALID_ACTION"; IOCSTATUS1[MPI2_IOCSTATUS_CONFIG_INVALID_TYPE-0]="CONFIG_INVALID_TYPE"; IOCSTATUS1[MPI2_IOCSTATUS_CONFIG_INVALID_PAGE-0]="CONFIG_INVALID_PAGE"; IOCSTATUS1[MPI2_IOCSTATUS_CONFIG_INVALID_DATA-0]="CONFIG_INVALID_DATA"; IOCSTATUS1[MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS-0]="CONFIG_NO_DEFAULTS"; IOCSTATUS1[MPI2_IOCSTATUS_CONFIG_CANT_COMMIT-0]="CONFIG_CANT_COMMIT"; IOCSTATUS2[MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR-0x40]="SCSI_RECOVERED_ERROR"; IOCSTATUS2[MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE-0x40]="SCSI_INVALID_DEVHANDLE"; IOCSTATUS2[MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE-0x40]="SCSI_DEVICE_NOT_THERE"; IOCSTATUS2[MPI2_IOCSTATUS_SCSI_DATA_OVERRUN-0x40]="SCSI_DATA_OVERRUN"; IOCSTATUS2[MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN-0x40]="SCSI_DATA_UNDERRUN"; IOCSTATUS2[MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR-0x40]="SCSI_IO_DATA_ERROR"; IOCSTATUS2[MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR-0x40]="SCSI_PROTOCOL_ERROR"; IOCSTATUS2[MPI2_IOCSTATUS_SCSI_TASK_TERMINATED-0x40]="SCSI_TASK_TERMINATED"; IOCSTATUS2[MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH-0x40]="SCSI_RESIDUAL_MISMATCH"; IOCSTATUS2[MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED-0x40]="SCSI_TASK_MGMT_FAILED"; IOCSTATUS2[MPI2_IOCSTATUS_SCSI_IOC_TERMINATED-0x40]="SCSI_IOC_TERMINATED"; IOCSTATUS2[MPI2_IOCSTATUS_SCSI_EXT_TERMINATED-0x40]="SCSI_EXT_TERMINATED"; IOCSTATUS2[MPI2_IOCSTATUS_EEDP_GUARD_ERROR-0x40]="EEDP_GUARD_ERROR"; IOCSTATUS2[MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR-0x40]="EEDP_REF_TAG_ERROR"; IOCSTATUS2[MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR-0x40]="EEDP_APP_TAG_ERROR"; IOCSTATUS2[MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX-0x40]="TARGET_INVALID_IO_INDEX"; IOCSTATUS2[MPI2_IOCSTATUS_TARGET_ABORTED-0x40]="TARGET_ABORTED"; IOCSTATUS2[MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE-0x40]="TARGET_NO_CONN_RETRYABLE"; IOCSTATUS2[MPI2_IOCSTATUS_TARGET_NO_CONNECTION-0x40]="TARGET_NO_CONNECTION"; IOCSTATUS2[MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH-0x40]="TARGET_XFER_COUNT_MISMATCH"; IOCSTATUS2[MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR-0x40]="TARGET_DATA_OFFSET_ERROR"; IOCSTATUS2[MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA-0x40]="TARGET_TOO_MUCH_WRITE_DATA"; IOCSTATUS2[MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT-0x40]="TARGET_IU_TOO_SHORT"; IOCSTATUS2[MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT-0x40]="TARGET_ACK_NAK_TIMEOUT"; IOCSTATUS2[MPI2_IOCSTATUS_TARGET_NAK_RECEIVED-0x40]="TARGET_NAK_RECEIVED"; IOCSTATUS3[MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED-0x80]="SAS_SMP_REQUEST_FAILED"; IOCSTATUS3[MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN-0x80]="SAS_SMP_DATA_OVERRUN"; IOCSTATUS3[MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED-0x80]="DIAGNOSTIC_RELEASED"; /* grep '^#define MPI2_FUNCTION_' ~/sas2ircu.d | \ sed -e 's,.*FUNCTION_,,' -e 's,[\(\)],,g' | \ ksh -c 'integer B; while read A B; do (( B >= 0x80 )) && continue; X=1; O=0; (( B >= 0x40 )) && X=2 && O=0x40 ; print "\tFN$X[MPI2_FUNCTION_${A}-$O]=\"$A\";" ; done' */ FN1[MPI2_FUNCTION_SCSI_IO_REQUEST-0]="SCSI_IO_REQUEST"; FN1[MPI2_FUNCTION_SCSI_TASK_MGMT-0]="SCSI_TASK_MGMT"; FN1[MPI2_FUNCTION_IOC_INIT-0]="IOC_INIT"; FN1[MPI2_FUNCTION_IOC_FACTS-0]="IOC_FACTS"; FN1[MPI2_FUNCTION_CONFIG-0]="CONFIG"; FN1[MPI2_FUNCTION_PORT_FACTS-0]="PORT_FACTS"; FN1[MPI2_FUNCTION_PORT_ENABLE-0]="PORT_ENABLE"; FN1[MPI2_FUNCTION_EVENT_NOTIFICATION-0]="EVENT_NOTIFICATION"; FN1[MPI2_FUNCTION_EVENT_ACK-0]="EVENT_ACK"; FN1[MPI2_FUNCTION_FW_DOWNLOAD-0]="FW_DOWNLOAD"; FN1[MPI2_FUNCTION_TARGET_ASSIST-0]="TARGET_ASSIST"; FN1[MPI2_FUNCTION_TARGET_STATUS_SEND-0]="TARGET_STATUS_SEND"; FN1[MPI2_FUNCTION_TARGET_MODE_ABORT-0]="TARGET_MODE_ABORT"; FN1[MPI2_FUNCTION_FW_UPLOAD-0]="FW_UPLOAD"; FN1[MPI2_FUNCTION_RAID_ACTION-0]="RAID_ACTION"; FN1[MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH-0]="RAID_SCSI_IO_PASSTHROUGH"; FN1[MPI2_FUNCTION_TOOLBOX-0]="TOOLBOX"; FN1[MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR-0]="SCSI_ENCLOSURE_PROCESSOR"; FN1[MPI2_FUNCTION_SMP_PASSTHROUGH-0]="SMP_PASSTHROUGH"; FN1[MPI2_FUNCTION_SAS_IO_UNIT_CONTROL-0]="SAS_IO_UNIT_CONTROL"; FN1[MPI2_FUNCTION_SATA_PASSTHROUGH-0]="SATA_PASSTHROUGH"; FN1[MPI2_FUNCTION_DIAG_BUFFER_POST-0]="DIAG_BUFFER_POST"; FN1[MPI2_FUNCTION_DIAG_RELEASE-0]="DIAG_RELEASE"; FN1[MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST-0]="TARGET_CMD_BUF_BASE_POST"; FN1[MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST-0]="TARGET_CMD_BUF_LIST_POST"; FN1[MPI2_FUNCTION_RAID_ACCELERATOR-0]="RAID_ACCELERATOR"; FN1[MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION-0]="HOST_BASED_DISCOVERY_ACTION"; FN1[MPI2_FUNCTION_PWR_MGMT_CONTROL-0]="PWR_MGMT_CONTROL"; FN1[MPI2_FUNCTION_SEND_HOST_MESSAGE-0]="SEND_HOST_MESSAGE"; FN2[MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET-0x40]="IOC_MESSAGE_UNIT_RESET"; FN2[MPI2_FUNCTION_HANDSHAKE-0x40]="HANDSHAKE"; } pid$target:libc.so.1:getenv:entry { self->vname = arg0 ? copyinstr(arg0) : ""; self->e = 1; /* record the pid early to be able to filter fbt/syscalls later */ self->pid = pid; } pid$target:libc.so.1:getenv:return / self->e / { this->val = arg1 ? copyinstr(arg1) : "NULL"; printf("getenv: %s = '%s'\n", self->vname, this->val); self->e = 0; } /* Track fd assignments to avoid destructive probes for showing fd associated path in ioctl(). The lazy destructive alternative would be: system("ls -l /proc/%d/path/%d", pid, fdes); */ fbt:genunix:setf:entry / self->pid == pid / { self->fd[arg0] = arg1 ? (args[1])->f_vnode->v_path : NULL; } pid$target:libc.so.1:ioctl:entry / arg1 == MPTIOCTL_PASS_THRU / { /* sas2ircu seems to use MPTIOCTL_PASS_THRU, only. Also tracking only this avoids the clutter from "real" IO. However, one may loosen it with / (arg1 & MPTIOCTL) == MPTIOCTL / */ CMD2STR(this->cmd, arg1); /* usually like /devices/pci@0,0/pci8086,e08@3/pci1000,3020@0:devctl */ this->fname = self->fd[arg0] ? stringof(self->fd[arg0]) : "???"; printf("-> ioctl(fdes=%d=='%s', cmd=MPTIOCTL_%s==0x%04X, arg=0x%p)\n", arg0, this->fname, this->cmd, arg1, arg2); ustack(); printf("\n"); self->trace = 1; } fbt:mpt_sas:mptsas_ioctl:entry / self->trace / { printf("-> mptsas_ioctl(dev=0x%X, cmd=0x%X, data=0x%p, mode=0x%X, credp=0x%p, rval=0x%p)\n", args[0], args[1], args[2], args[3], args[4], args[5] ); self->seen = 1; } /* mptsas_pass_thru(mptsas_t *mpt, mptsas_pass_thru_t *data, int mode) */ /* common entry stuff prolog */ fbt:mpt_sas:mptsas_pass_thru:entry / self->trace / { self->data = (mptsas_pass_thru_t *) args[1]; this->PtrRequest = (uintptr_t)self->data->PtrRequest; this->PtrReply = (uintptr_t)self->data->PtrReply; this->PtrData = (uintptr_t)self->data->PtrData; this->PtrDataOut = (uintptr_t)self->data->PtrDataOut; DIR2STR(this->dir, self->data->DataDirection); printf("\n -> mptsas_passthru(mpt=0x%p, mode=0x%08X, Timeout=%d, RequestSize=%d, ReplySize=%d, DataSize=%d, DataDirection=MPTSAS_PASS_THRU_DIRECTION_%s, DataOutSize=%d, PtrRequest=0x%p, PtrReply=0x%p, PtrData=0x%p, PtrDataOut=0x%p):\n", arg0, arg2, self->data->Timeout, self->data->RequestSize, self->data->ReplySize, self->data->DataSize, this->dir, self->data->DataOutSize, this->PtrRequest, this->PtrReply, this->PtrData, this->PtrDataOut ); self->repSz = self->data->ReplySize; self->reqSz = self->data->RequestSize; this->req2 = self->reqSz ? (uint8_t *) copyin(this->PtrRequest, self->reqSz) : NULL; self->fn = this->req2[3]; /* same for _all_ requests */ FN2STR(self->fnName, self->fn); /* without this we get strange errors below */ this->req = (pMpi2SepRequest_t) (this->req2); } /* non-ENCLOSURE_PROCESSOR entry stuff */ fbt:mpt_sas:mptsas_pass_thru:entry / self->reqSz > 0 && self->fn != MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR / { /* since copyin() buffers get destroyed when a probe has finished ... */ this->req2 = (uint8_t *) copyin(self->data->PtrRequest, self->reqSz); printf(" Function=MPI2_FUNCTION_%s (RequestDump):\n", self->fnName); tracemem(this->req2, 64, self->reqSz); printf("%s", self->reqSz > 64 ? " ...\n\n" : "\n"); } /* ENCLOSURE_PROCESSOR entry stuff */ fbt:mpt_sas:mptsas_pass_thru:entry / self->reqSz > 0 && self->fn == MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR / { /* since copyin() buffers get destroyed when a probe has finished ... */ this->req2 = (uint8_t *) copyin(self->data->PtrRequest, self->reqSz); this->req = (pMpi2SepRequest_t) (this->req2); SLOTSTATUS2STR(this->status, this->req->SlotStatus); printf(" Function=MPI2_FUNCTION_%s DevHandle=0x%04x ChainOffset=0x%02x Action=MPI2_SEP_REQ_ACTION_%s Flags=MPI2_SEP_REQ_FLAGS_%s_ADDRESS MsgFlags=0x%02X VP_ID=0x%02X VF_ID=0x%02X SlotStatus=%s Slot=0x%04X EnclosureHandle=0x%04X Reserved1=0x%02X Reserved2=0x%04X Reserved3=0x%08X Reserved4=0x%08X Reserved5=0x%08X\n\n", self->fnName, this->req->DevHandle, this->req->ChainOffset, ACTION2STR(this->req->Action), RFLAG2STR(this->req->Flags), this->req->MsgFlags, this->req->VP_ID, this->req->VF_ID, this->status, this->req->Slot, this->req->EnclosureHandle, this->req->Reserved1, this->req->Reserved2, this->req->Reserved3, this->req->Reserved4, this->req->Reserved5 ); } /* common entry stuff epilog as well as stack traces for other mptsas_pass_thru calls. Add '/ self->trace /' below throw away nt so interesting stuff. */ fbt:mpt_sas:mptsas_pass_thru:entry { /* stack(); */ self->seen = 1; /* don't show this call in the next clause */ } fbt:mpt_sas::entry / self->seen != 1 && VERBOSE / { printf("-> %s@%s@%s@%s\n", probeprov, probemod, probefunc, probename); } /* non-ENCLOSURE_PROCESSOR return prolog */ fbt:mpt_sas:mptsas_pass_thru:return / self->repSz > 0 && self->fn != MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR / { this->rep2 = (uint8_t *) copyin(self->data->PtrReply, self->repSz); this->rep3 = (pMPI2DefaultReply_t) this->rep2; IOCSTATUS2STR(this->istatus, this->rep3->IOCStatus); LOGINFO2STR(this->logInfoType, this->rep3->IOCLogInfo); printf(" REPLY: MsgLength=%d MsgFlags=0x%02X IOCStatus=MPI2_IOCSTATUS_%s==0x%04X IOCLogInfo[MPI2_IOCLOGINFO_TYPE_%s]=0x%07X\n Dump:\n", this->rep3->MsgLength, this->rep3->MsgFlags, this->istatus, this->rep3->IOCStatus, this->logInfoType, this->rep3->IOCLogInfo & MPI2_IOCLOGINFO_LOG_DATA_MASK ); tracemem(this->rep2, 64, self->repSz); printf("%s", self->reqSz > 64 ? " ...\n\n" : "\n"); } /* ENCLOSURE_PROCESSOR return prolog */ fbt:mpt_sas:mptsas_pass_thru:return / self->repSz > 0 && self->fn == MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR / { this->rep2 = (uint8_t *) copyin(self->data->PtrReply, self->repSz); this->rep = (pMpi2SepReply_t) this->rep2; IOCSTATUS2STR(this->istatus, this->rep->IOCStatus); LOGINFO2STR(this->logInfoType, this->rep->IOCLogInfo); /* Usually the RequestMsg gets reused, i.e. the ReplyMsg is the RequestMsg * with the reply related fields overwritten. So no need to repeat. */ printf(" REPLY: MsgLength=%d MsgFlags=0x%02X IOCStatus=MPI2_IOCSTATUS_%s==0x%04X IOCLogInfo[MPI2_IOCLOGINFO_TYPE_%s]=0x%07X SlotStatus=%04X\n", this->rep->MsgLength, this->rep->MsgFlags, this->istatus, this->rep->IOCStatus, this->logInfoType, this->rep->IOCLogInfo & MPI2_IOCLOGINFO_LOG_DATA_MASK, this->rep->SlotStatus ); } /* common return stuff epilog */ fbt:mpt_sas:mptsas_pass_thru:return / self->trace / { /* dtrace doesn't seem to get it right - skip to avoid misleading printf("\t\tRESULT = %d\n", arg0); */ self->data = NULL; self->request = NULL; self->fnName = NULL; self->repSz = self->reqSz = self->fn = self->seen = 0; printf("\n\n"); } pid$target:libc.so.1:ioctl:return / self->trace / { self->trace = 0; }