Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/mpsutil/mps_cmd.c
Show All 35 Lines | |||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__RCSID("$FreeBSD$"); | __RCSID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/errno.h> | #include <sys/errno.h> | ||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/uio.h> | #include <sys/uio.h> | ||||
#include <sys/endian.h> | |||||
#include <err.h> | #include <err.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | |||||
struct mprs_btdh_mapping { | struct mprs_btdh_mapping { | ||||
uint16_t TargetID; | uint16_t TargetID; | ||||
uint16_t Bus; | uint16_t Bus; | ||||
uint16_t DevHandle; | uint16_t DevHandle; | ||||
uint16_t Reserved; | uint16_t Reserved; | ||||
}; | }; | ||||
static void adjust_iocfacts_endianness(MPI2_IOC_FACTS_REPLY *facts); | |||||
const char * | const char * | ||||
mps_ioc_status(U16 IOCStatus) | mps_ioc_status(U16 IOCStatus) | ||||
{ | { | ||||
static char buffer[16]; | static char buffer[16]; | ||||
IOCStatus &= MPI2_IOCSTATUS_MASK; | IOCStatus &= MPI2_IOCSTATUS_MASK; | ||||
if (IOCStatus < sizeof(mps_ioc_status_codes) / sizeof(char *) && | if (IOCStatus < sizeof(mps_ioc_status_codes) / sizeof(char *) && | ||||
mps_ioc_status_codes[IOCStatus] != NULL) | mps_ioc_status_codes[IOCStatus] != NULL) | ||||
Show All 39 Lines | mps_set_slot_status(int fd, U16 handle, U16 slot, U32 status) | ||||
req.EnclosureHandle = handle; | req.EnclosureHandle = handle; | ||||
req.Slot = slot; | req.Slot = slot; | ||||
req.SlotStatus = status; | req.SlotStatus = status; | ||||
if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), | if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), | ||||
NULL, 0, NULL, 0, 30) != 0) | NULL, 0, NULL, 0, 30) != 0) | ||||
return (errno); | return (errno); | ||||
if (!IOC_STATUS_SUCCESS(reply.IOCStatus)) | if (!IOC_STATUS_SUCCESS(le16toh(reply.IOCStatus))) | ||||
return (EIO); | return (EIO); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
mps_read_config_page_header(int fd, U8 PageType, U8 PageNumber, U32 PageAddress, | mps_read_config_page_header(int fd, U8 PageType, U8 PageNumber, U32 PageAddress, | ||||
MPI2_CONFIG_PAGE_HEADER *header, U16 *IOCStatus) | MPI2_CONFIG_PAGE_HEADER *header, U16 *IOCStatus) | ||||
{ | { | ||||
MPI2_CONFIG_REQUEST req; | MPI2_CONFIG_REQUEST req; | ||||
MPI2_CONFIG_REPLY reply; | MPI2_CONFIG_REPLY reply; | ||||
bzero(&req, sizeof(req)); | bzero(&req, sizeof(req)); | ||||
req.Function = MPI2_FUNCTION_CONFIG; | req.Function = MPI2_FUNCTION_CONFIG; | ||||
req.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | req.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||||
req.Header.PageType = PageType; | req.Header.PageType = PageType; | ||||
req.Header.PageNumber = PageNumber; | req.Header.PageNumber = PageNumber; | ||||
req.PageAddress = PageAddress; | req.PageAddress = PageAddress; | ||||
if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), | if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), | ||||
NULL, 0, NULL, 0, 30)) | NULL, 0, NULL, 0, 30)) | ||||
return (errno); | return (errno); | ||||
if (!IOC_STATUS_SUCCESS(reply.IOCStatus)) { | if (!IOC_STATUS_SUCCESS(le16toh(reply.IOCStatus))) { | ||||
if (IOCStatus != NULL) | if (IOCStatus != NULL) | ||||
*IOCStatus = reply.IOCStatus; | *IOCStatus = reply.IOCStatus; | ||||
return (EIO); | return (EIO); | ||||
} | } | ||||
if (header == NULL) | if (header == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
*header = reply.Header; | *header = reply.Header; | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
mps_read_ext_config_page_header(int fd, U8 ExtPageType, U8 PageNumber, U32 PageAddress, MPI2_CONFIG_PAGE_HEADER *header, U16 *ExtPageLength, U16 *IOCStatus) | mps_read_ext_config_page_header(int fd, U8 ExtPageType, U8 PageNumber, U32 PageAddress, MPI2_CONFIG_PAGE_HEADER *header, U16 *ExtPageLength, U16 *IOCStatus) | ||||
{ | { | ||||
MPI2_CONFIG_REQUEST req; | MPI2_CONFIG_REQUEST req; | ||||
MPI2_CONFIG_REPLY reply; | MPI2_CONFIG_REPLY reply; | ||||
bzero(&req, sizeof(req)); | bzero(&req, sizeof(req)); | ||||
req.Function = MPI2_FUNCTION_CONFIG; | req.Function = MPI2_FUNCTION_CONFIG; | ||||
req.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | req.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; | ||||
req.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | req.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; | ||||
req.ExtPageType = ExtPageType; | req.ExtPageType = ExtPageType; | ||||
req.Header.PageNumber = PageNumber; | req.Header.PageNumber = PageNumber; | ||||
req.PageAddress = PageAddress; | req.PageAddress = htole32(PageAddress); | ||||
if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), | if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), | ||||
NULL, 0, NULL, 0, 30)) | NULL, 0, NULL, 0, 30)) | ||||
return (errno); | return (errno); | ||||
if (!IOC_STATUS_SUCCESS(reply.IOCStatus)) { | if (!IOC_STATUS_SUCCESS(le16toh(reply.IOCStatus))) { | ||||
if (IOCStatus != NULL) | if (IOCStatus != NULL) | ||||
*IOCStatus = reply.IOCStatus; | *IOCStatus = le16toh(reply.IOCStatus); | ||||
return (EIO); | return (EIO); | ||||
} | } | ||||
if ((header == NULL) || (ExtPageLength == NULL)) | if ((header == NULL) || (ExtPageLength == NULL)) | ||||
return (EINVAL); | return (EINVAL); | ||||
*header = reply.Header; | *header = reply.Header; | ||||
*ExtPageLength = reply.ExtPageLength; | *ExtPageLength = reply.ExtPageLength; | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 14 Lines | mps_read_config_page(int fd, U8 PageType, U8 PageNumber, U32 PageAddress, | ||||
if (error) { | if (error) { | ||||
errno = error; | errno = error; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
bzero(&req, sizeof(req)); | bzero(&req, sizeof(req)); | ||||
req.Function = MPI2_FUNCTION_CONFIG; | req.Function = MPI2_FUNCTION_CONFIG; | ||||
req.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | req.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||||
req.PageAddress = PageAddress; | req.PageAddress = htole32(PageAddress); | ||||
req.Header = header; | req.Header = header; | ||||
if (req.Header.PageLength == 0) | if (req.Header.PageLength == 0) | ||||
req.Header.PageLength = 4; | req.Header.PageLength = 4; | ||||
len = req.Header.PageLength * 4; | len = req.Header.PageLength * 4; | ||||
buf = malloc(len); | buf = malloc(len); | ||||
if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), | if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), | ||||
buf, len, NULL, 0, 30)) { | buf, len, NULL, 0, 30)) { | ||||
error = errno; | error = errno; | ||||
free(buf); | free(buf); | ||||
errno = error; | errno = error; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
reply.IOCStatus = le16toh(reply.IOCStatus); | |||||
if (!IOC_STATUS_SUCCESS(reply.IOCStatus)) { | if (!IOC_STATUS_SUCCESS(reply.IOCStatus)) { | ||||
scottl: IOCStatus should be byte-swapped here and stored for return to the caller so it doesn't have to… | |||||
if (IOCStatus != NULL) | if (IOCStatus != NULL) | ||||
*IOCStatus = reply.IOCStatus; | *IOCStatus = reply.IOCStatus; | ||||
else | else | ||||
warnx("Reading config page failed: 0x%x %s", | warnx("Reading config page failed: 0x%x %s", | ||||
reply.IOCStatus, mps_ioc_status(reply.IOCStatus)); | reply.IOCStatus, mps_ioc_status(reply.IOCStatus)); | ||||
free(buf); | free(buf); | ||||
errno = EIO; | errno = EIO; | ||||
return (NULL); | return (NULL); | ||||
Show All 20 Lines | mps_read_extended_config_page(int fd, U8 ExtPageType, U8 PageVersion, | ||||
if (error) { | if (error) { | ||||
errno = error; | errno = error; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
bzero(&req, sizeof(req)); | bzero(&req, sizeof(req)); | ||||
req.Function = MPI2_FUNCTION_CONFIG; | req.Function = MPI2_FUNCTION_CONFIG; | ||||
req.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | req.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; | ||||
req.PageAddress = PageAddress; | req.PageAddress = htole32(PageAddress); | ||||
req.Header = header; | req.Header = header; | ||||
if (pagelen == 0) | if (pagelen == 0) | ||||
pagelen = 4; | pagelen = htole16(4); | ||||
req.ExtPageLength = pagelen; | req.ExtPageLength = pagelen; | ||||
req.ExtPageType = ExtPageType; | req.ExtPageType = ExtPageType; | ||||
len = pagelen * 4; | len = le16toh(pagelen) * 4; | ||||
buf = malloc(len); | buf = malloc(len); | ||||
if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), | if (mps_pass_command(fd, &req, sizeof(req), &reply, sizeof(reply), | ||||
buf, len, NULL, 0, 30)) { | buf, len, NULL, 0, 30)) { | ||||
error = errno; | error = errno; | ||||
free(buf); | free(buf); | ||||
errno = error; | errno = error; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
reply.IOCStatus = le16toh(reply.IOCStatus); | |||||
if (!IOC_STATUS_SUCCESS(reply.IOCStatus)) { | if (!IOC_STATUS_SUCCESS(reply.IOCStatus)) { | ||||
Done Inline ActionsIOCStatus should be byte-swapped here and stored for return to the caller so it doesn't have to be byte swapped by the caller scottl: IOCStatus should be byte-swapped here and stored for return to the caller so it doesn't have to… | |||||
if (IOCStatus != NULL) | if (IOCStatus != NULL) | ||||
*IOCStatus = reply.IOCStatus; | *IOCStatus = reply.IOCStatus; | ||||
else | else | ||||
warnx("Reading extended config page failed: %s", | warnx("Reading extended config page failed: %s", | ||||
mps_ioc_status(reply.IOCStatus)); | mps_ioc_status(reply.IOCStatus)); | ||||
free(buf); | free(buf); | ||||
errno = EIO; | errno = EIO; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
return (buf); | return (buf); | ||||
} | } | ||||
int | int | ||||
mps_firmware_send(int fd, unsigned char *fw, uint32_t len, bool bios) | mps_firmware_send(int fd, unsigned char *fw, uint32_t len, bool bios) | ||||
{ | { | ||||
MPI2_FW_DOWNLOAD_REQUEST req; | MPI2_FW_DOWNLOAD_REQUEST req; | ||||
MPI2_FW_DOWNLOAD_REPLY reply; | MPI2_FW_DOWNLOAD_REPLY reply; | ||||
bzero(&req, sizeof(req)); | bzero(&req, sizeof(req)); | ||||
bzero(&reply, sizeof(reply)); | bzero(&reply, sizeof(reply)); | ||||
req.Function = MPI2_FUNCTION_FW_DOWNLOAD; | req.Function = MPI2_FUNCTION_FW_DOWNLOAD; | ||||
req.ImageType = bios ? MPI2_FW_DOWNLOAD_ITYPE_BIOS : MPI2_FW_DOWNLOAD_ITYPE_FW; | req.ImageType = bios ? MPI2_FW_DOWNLOAD_ITYPE_BIOS : MPI2_FW_DOWNLOAD_ITYPE_FW; | ||||
req.TotalImageSize = len; | req.TotalImageSize = htole32(len); | ||||
req.MsgFlags = MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT; | req.MsgFlags = MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT; | ||||
if (mps_user_command(fd, &req, sizeof(req), &reply, sizeof(reply), | if (mps_user_command(fd, &req, sizeof(req), &reply, sizeof(reply), | ||||
fw, len, 0)) { | fw, len, 0)) { | ||||
return (-1); | return (-1); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 14 Lines | mps_firmware_get(int fd, unsigned char **firmware, bool bios) | ||||
if (mps_user_command(fd, &req, sizeof(req), &reply, sizeof(reply), | if (mps_user_command(fd, &req, sizeof(req), &reply, sizeof(reply), | ||||
NULL, 0, 0)) { | NULL, 0, 0)) { | ||||
return (-1); | return (-1); | ||||
} | } | ||||
if (reply.ActualImageSize == 0) { | if (reply.ActualImageSize == 0) { | ||||
return (-1); | return (-1); | ||||
} | } | ||||
size = reply.ActualImageSize; | size = le32toh(reply.ActualImageSize); | ||||
*firmware = calloc(size, sizeof(unsigned char)); | *firmware = calloc(size, sizeof(unsigned char)); | ||||
if (*firmware == NULL) { | if (*firmware == NULL) { | ||||
warn("calloc"); | warn("calloc"); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
if (mps_user_command(fd, &req, sizeof(req), &reply, sizeof(reply), | if (mps_user_command(fd, &req, sizeof(req), &reply, sizeof(reply), | ||||
*firmware, size, 0)) { | *firmware, size, 0)) { | ||||
free(*firmware); | free(*firmware); | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | mps_read_config_page(int fd, U8 PageType, U8 PageNumber, U32 PageAddress, | ||||
req.buf = buf; | req.buf = buf; | ||||
bcopy(&req.header, buf, sizeof(req.header)); | bcopy(&req.header, buf, sizeof(req.header)); | ||||
if (ioctl(fd, MPSIO_READ_CFG_PAGE, &req) < 0) { | if (ioctl(fd, MPSIO_READ_CFG_PAGE, &req) < 0) { | ||||
error = errno; | error = errno; | ||||
free(buf); | free(buf); | ||||
errno = error; | errno = error; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
req.ioc_status = le16toh(req.ioc_status); | |||||
if (!IOC_STATUS_SUCCESS(req.ioc_status)) { | if (!IOC_STATUS_SUCCESS(req.ioc_status)) { | ||||
if (IOCStatus != NULL) | if (IOCStatus != NULL) | ||||
*IOCStatus = req.ioc_status; | *IOCStatus = req.ioc_status; | ||||
else | else | ||||
warnx("Reading config page failed: 0x%x %s", | warnx("Reading config page failed: 0x%x %s", | ||||
req.ioc_status, mps_ioc_status(req.ioc_status)); | req.ioc_status, mps_ioc_status(req.ioc_status)); | ||||
free(buf); | free(buf); | ||||
errno = EIO; | errno = EIO; | ||||
Show All 11 Lines | mps_read_extended_config_page(int fd, U8 ExtPageType, U8 PageVersion, | ||||
int error; | int error; | ||||
if (IOCStatus != NULL) | if (IOCStatus != NULL) | ||||
*IOCStatus = MPI2_IOCSTATUS_SUCCESS; | *IOCStatus = MPI2_IOCSTATUS_SUCCESS; | ||||
bzero(&req, sizeof(req)); | bzero(&req, sizeof(req)); | ||||
req.header.PageVersion = PageVersion; | req.header.PageVersion = PageVersion; | ||||
req.header.PageNumber = PageNumber; | req.header.PageNumber = PageNumber; | ||||
req.header.ExtPageType = ExtPageType; | req.header.ExtPageType = ExtPageType; | ||||
req.page_address = PageAddress; | req.page_address = htole32(PageAddress); | ||||
if (ioctl(fd, MPSIO_READ_EXT_CFG_HEADER, &req) < 0) | if (ioctl(fd, MPSIO_READ_EXT_CFG_HEADER, &req) < 0) | ||||
return (NULL); | return (NULL); | ||||
req.ioc_status = le16toh(req.ioc_status); | |||||
if (!IOC_STATUS_SUCCESS(req.ioc_status)) { | if (!IOC_STATUS_SUCCESS(req.ioc_status)) { | ||||
if (IOCStatus != NULL) | if (IOCStatus != NULL) | ||||
*IOCStatus = req.ioc_status; | *IOCStatus = req.ioc_status; | ||||
else | else | ||||
warnx("Reading extended config page header failed: %s", | warnx("Reading extended config page header failed: %s", | ||||
mps_ioc_status(req.ioc_status)); | mps_ioc_status(req.ioc_status)); | ||||
errno = EIO; | errno = EIO; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
req.len = req.header.ExtPageLength * 4; | req.len = req.header.ExtPageLength * 4; | ||||
buf = malloc(req.len); | buf = malloc(req.len); | ||||
req.buf = buf; | req.buf = buf; | ||||
bcopy(&req.header, buf, sizeof(req.header)); | bcopy(&req.header, buf, sizeof(req.header)); | ||||
if (ioctl(fd, MPSIO_READ_EXT_CFG_PAGE, &req) < 0) { | if (ioctl(fd, MPSIO_READ_EXT_CFG_PAGE, &req) < 0) { | ||||
error = errno; | error = errno; | ||||
free(buf); | free(buf); | ||||
errno = error; | errno = error; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
req.ioc_status = le16toh(req.ioc_status); | |||||
if (!IOC_STATUS_SUCCESS(req.ioc_status)) { | if (!IOC_STATUS_SUCCESS(req.ioc_status)) { | ||||
if (IOCStatus != NULL) | if (IOCStatus != NULL) | ||||
*IOCStatus = req.ioc_status; | *IOCStatus = req.ioc_status; | ||||
else | else | ||||
warnx("Reading extended config page failed: %s", | warnx("Reading extended config page failed: %s", | ||||
mps_ioc_status(req.ioc_status)); | mps_ioc_status(req.ioc_status)); | ||||
free(buf); | free(buf); | ||||
errno = EIO; | errno = EIO; | ||||
▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | if (error) { | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
if (!IOC_STATUS_SUCCESS(facts->IOCStatus)) { | if (!IOC_STATUS_SUCCESS(facts->IOCStatus)) { | ||||
free(facts); | free(facts); | ||||
errno = EINVAL; | errno = EINVAL; | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
adjust_iocfacts_endianness(facts); | |||||
return (facts); | return (facts); | ||||
} | } | ||||
static void | |||||
adjust_iocfacts_endianness(MPI2_IOC_FACTS_REPLY *facts) | |||||
{ | |||||
facts->MsgVersion = le16toh(facts->MsgVersion); | |||||
facts->HeaderVersion = le16toh(facts->HeaderVersion); | |||||
facts->Reserved1 = le16toh(facts->Reserved1); | |||||
facts->IOCExceptions = le16toh(facts->IOCExceptions); | |||||
facts->IOCStatus = le16toh(facts->IOCStatus); | |||||
facts->IOCLogInfo = le32toh(facts->IOCLogInfo); | |||||
facts->RequestCredit = le16toh(facts->RequestCredit); | |||||
facts->ProductID = le16toh(facts->ProductID); | |||||
facts->IOCCapabilities = le32toh(facts->IOCCapabilities); | |||||
facts->IOCRequestFrameSize = | |||||
le16toh(facts->IOCRequestFrameSize); | |||||
facts->FWVersion.Word = le32toh(facts->FWVersion.Word); | |||||
facts->MaxInitiators = le16toh(facts->MaxInitiators); | |||||
facts->MaxTargets = le16toh(facts->MaxTargets); | |||||
facts->MaxSasExpanders = le16toh(facts->MaxSasExpanders); | |||||
facts->MaxEnclosures = le16toh(facts->MaxEnclosures); | |||||
facts->ProtocolFlags = le16toh(facts->ProtocolFlags); | |||||
facts->HighPriorityCredit = le16toh(facts->HighPriorityCredit); | |||||
facts->MaxReplyDescriptorPostQueueDepth = | |||||
le16toh(facts->MaxReplyDescriptorPostQueueDepth); | |||||
facts->MaxDevHandle = le16toh(facts->MaxDevHandle); | |||||
facts->MaxPersistentEntries = | |||||
le16toh(facts->MaxPersistentEntries); | |||||
facts->MinDevHandle = le16toh(facts->MinDevHandle); | |||||
} |
IOCStatus should be byte-swapped here and stored for return to the caller so it doesn't have to be byte swapped by the caller