diff --git a/sys/dev/mrsas/mrsas.c b/sys/dev/mrsas/mrsas.c index 6247cc2b142..c944ba46d85 100644 --- a/sys/dev/mrsas/mrsas.c +++ b/sys/dev/mrsas/mrsas.c @@ -1449,7 +1449,14 @@ mrsas_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, int ret = 0, i = 0; MRSAS_DRV_PCI_INFORMATION *pciDrvInfo; - sc = mrsas_get_softc_instance(dev, cmd, arg); + switch (cmd) { + case MFIIO_PASSTHRU: + sc = (struct mrsas_softc *)(dev->si_drv1); + break; + default: + sc = mrsas_get_softc_instance(dev, cmd, arg); + break; + } if (!sc) return ENOENT; @@ -1512,6 +1519,10 @@ mrsas_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, ret = 0; break; + case MFIIO_PASSTHRU: + ret = mrsas_user_command(sc, (struct mfi_ioc_passthru *)arg); + break; + default: mrsas_dprint(sc, MRSAS_TRACE, "IOCTL command 0x%lx is not handled\n", cmd); ret = ENOENT; diff --git a/sys/dev/mrsas/mrsas.h b/sys/dev/mrsas/mrsas.h index 069db02fadf..f2e82047f8a 100644 --- a/sys/dev/mrsas/mrsas.h +++ b/sys/dev/mrsas/mrsas.h @@ -3660,4 +3660,7 @@ mrsas_test_bit(int b, volatile void *p) return ((volatile int *)p)[b >> 5] & (1 << (b & 0x1f)); } +#include "mrsas_ioctl.h" +extern int mrsas_user_command(struct mrsas_softc *, struct mfi_ioc_passthru *); + #endif /* MRSAS_H */ diff --git a/sys/dev/mrsas/mrsas_ioctl.c b/sys/dev/mrsas/mrsas_ioctl.c index 1044fcbbcf9..b8d88c164e8 100644 --- a/sys/dev/mrsas/mrsas_ioctl.c +++ b/sys/dev/mrsas/mrsas_ioctl.c @@ -43,6 +43,18 @@ __FBSDID("$FreeBSD$"); #include #include +struct mrsas_passthru_cmd { + struct iovec *kern_sge; + struct mrsas_softc *sc; + struct mrsas_mfi_cmd *cmd; + bus_dma_tag_t ioctl_data_tag; + bus_dmamap_t ioctl_data_dmamap; + + u_int32_t error_code; + u_int32_t sge_count; + int complete; +}; + /* * Function prototypes */ @@ -62,6 +74,54 @@ extern int mrsas_issue_blocked_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); +/* + * mrsas_data_load_cb: Callback entry point + * input: Pointer to command packet as argument + * Pointer to segment + * Number of segments Error + * + * This is the callback function of the bus dma map load. It builds the SG + * list. + */ +static void +mrsas_passthru_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + struct mrsas_passthru_cmd *cb = (struct mrsas_passthru_cmd *)arg; + struct mrsas_softc *sc = cb->sc; + int i = 0; + + if (error) { + cb->error_code = error; + if (error == EFBIG) { + device_printf(sc->mrsas_dev, "mrsas_passthru_load_cb: " + "error=%d EFBIG\n", error); + cb->complete = 1; + return; + } else { + device_printf(sc->mrsas_dev, "mrsas_passthru_load_cb: " + "error=%d UNKNOWN\n", error); + } + } + if (nseg > MAX_IOCTL_SGE) { + cb->error_code = EFBIG; + device_printf(sc->mrsas_dev, "mrsas_passthru_load_cb: " + "too many segments: %d\n", nseg); + cb->complete = 1; + return; + } + + for (i = 0; i < nseg; i++) { + cb->kern_sge[i].iov_base = PTRIN(segs[i].ds_addr); + cb->kern_sge[i].iov_len = segs[i].ds_len; + } + cb->sge_count = nseg; + + bus_dmamap_sync(cb->ioctl_data_tag, cb->ioctl_data_dmamap, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + cb->complete = 1; +} + /* * mrsas_passthru: Handle pass-through commands * input: Adapter instance soft state argument pointer @@ -344,6 +404,200 @@ mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd) return (ret); } +/** + * mrsas_user_command: Handle user mode DCMD and buffer + * input: Adapter instance soft state + * argument pointer + * + * This function is called from mrsas_ioctl() DCMDs to firmware for mfiutil + */ +int +mrsas_user_command(struct mrsas_softc *sc, struct mfi_ioc_passthru *ioc) +{ + struct mrsas_mfi_cmd *cmd; + struct mrsas_dcmd_frame *dcmd; + struct mrsas_passthru_cmd *passcmd; + bus_dma_tag_t ioctl_data_tag; + bus_dmamap_t ioctl_data_dmamap; + bus_addr_t ioctl_data_phys_addr; + struct iovec *kern_sge; + int ret, ioctl_data_size; + char *ioctl_temp_data_mem; + + ret = 0; + ioctl_temp_data_mem = NULL; + passcmd = NULL; + ioctl_data_phys_addr = 0; + dcmd = NULL; + cmd = NULL; + ioctl_data_tag = NULL; + ioctl_data_dmamap = NULL; + ioctl_data_dmamap = NULL; + + /* Get a command */ + cmd = mrsas_get_mfi_cmd(sc); + if (!cmd) { + device_printf(sc->mrsas_dev, + "Failed to get a free cmd for IOCTL\n"); + return(ENOMEM); + } + + /* + * Frame is DCMD + */ + dcmd = (struct mrsas_dcmd_frame *)cmd->frame; + memcpy(dcmd, &ioc->ioc_frame, sizeof(struct mrsas_dcmd_frame)); + + ioctl_data_size = ioc->buf_size; + + cmd->frame->hdr.context = cmd->index; + cmd->frame->hdr.pad_0 = 0; + cmd->frame->hdr.flags = MFI_FRAME_DIR_BOTH; + if (sizeof(bus_addr_t) == 8) + cmd->frame->hdr.flags |= MFI_FRAME_SGL64 | MFI_FRAME_SENSE64; + + kern_sge = (struct iovec *)(&dcmd->sgl); + + if (ioctl_data_size == 0) { + kern_sge[0].iov_base = 0; + kern_sge[0].iov_len = 0; + } else { + ioctl_temp_data_mem = malloc(ioc->buf_size, M_MRSAS, M_WAITOK); + if (ioctl_temp_data_mem == NULL) { + device_printf(sc->mrsas_dev, "Could not allocate " + "%d memory for temporary passthrough ioctl\n", + ioc->buf_size); + ret = ENOMEM; + goto out; + } + + /* Copy in data from user space */ + ret = copyin(ioc->buf, ioctl_temp_data_mem, ioc->buf_size); + if (ret) { + device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n"); + goto out; + } + + /* + * Allocate a temporary struct to hold parameters for the + * callback + */ + passcmd = malloc(sizeof(struct mrsas_passthru_cmd), M_MRSAS, + M_WAITOK); + if (passcmd == NULL) { + device_printf(sc->mrsas_dev, "Could not allocate " + "memory for temporary passthrough cb struct\n"); + ret = ENOMEM; + goto out; + } + passcmd->complete = 0; + passcmd->sc = sc; + passcmd->cmd = cmd; + passcmd->kern_sge = kern_sge; + + /* + * Create a dma tag for passthru buffers + */ + if (bus_dma_tag_create(sc->mrsas_parent_tag, /* parent */ + 1, 0, /* algnmnt, boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + ioctl_data_size, /* maxsize */ + MAX_IOCTL_SGE, /* msegments */ + ioctl_data_size, /* maxsegsize */ + BUS_DMA_ALLOCNOW, /* flags */ + busdma_lock_mutex, /* lockfunc */ + &sc->ioctl_lock, /* lockarg */ + &ioctl_data_tag)) { + device_printf(sc->mrsas_dev, + "Cannot allocate ioctl data tag %d\n", + ioc->buf_size); + ret = ENOMEM; + goto out; + } + + /* Create memmap */ + if (bus_dmamap_create(ioctl_data_tag, 0, &ioctl_data_dmamap)) { + device_printf(sc->mrsas_dev, "Cannot create ioctl " + "passthru dmamap\n"); + ret = ENOMEM; + goto out; + } + + passcmd->ioctl_data_tag = ioctl_data_tag; + passcmd->ioctl_data_dmamap = ioctl_data_dmamap; + + /* Map data buffer into bus space */ + if (bus_dmamap_load(ioctl_data_tag, ioctl_data_dmamap, + ioctl_temp_data_mem, ioc->buf_size, mrsas_passthru_load_cb, + passcmd, BUS_DMA_NOWAIT)) { + device_printf(sc->mrsas_dev, "Cannot load ioctl " + "passthru data mem%s %d\n", curproc->p_comm, ioctl_data_size); + ret = ENOMEM; + goto out; + } + + while (passcmd->complete == 0) { + pause("mrsas_passthru", hz); + } + + cmd->frame->dcmd.sge_count = passcmd->sge_count; + } + + /* + * Set the sync_cmd flag so that the ISR knows not to complete this + * cmd to the SCSI mid-layer + */ + cmd->sync_cmd = 1; + mrsas_issue_blocked_cmd(sc, cmd); + cmd->sync_cmd = 0; + + if (ioctl_data_size != 0) { + bus_dmamap_sync(ioctl_data_tag, ioctl_data_dmamap, + BUS_DMASYNC_POSTREAD); + /* + * copy out the kernel buffers to user buffers + */ + ret = copyout(ioctl_temp_data_mem, ioc->buf, ioc->buf_size); + if (ret) { + device_printf(sc->mrsas_dev, + "IOCTL copyout failed!\n"); + goto out; + } + } + + /* + * Return command status to user space + */ + memcpy(&ioc->ioc_frame.cmd_status, &cmd->frame->hdr.cmd_status, + sizeof(u_int8_t)); + +out: + /* + * Release temporary passthrough ioctl + */ + if (ioctl_temp_data_mem) + free(ioctl_temp_data_mem, M_MRSAS); + if (passcmd) + free(passcmd, M_MRSAS); + + /* + * Release data buffers + */ + if (ioctl_data_phys_addr) { + bus_dmamap_unload(ioctl_data_tag, ioctl_data_dmamap); + bus_dmamap_destroy(ioctl_data_tag, ioctl_data_dmamap); + } + if (ioctl_data_tag != NULL) + bus_dma_tag_destroy(ioctl_data_tag); + /* Free command */ + mrsas_release_mfi_cmd(cmd); + + return(ret); +} + + /* * mrsas_alloc_mfi_cmds: Allocates the command packets * input: Adapter instance soft state diff --git a/sys/dev/mrsas/mrsas_ioctl.h b/sys/dev/mrsas/mrsas_ioctl.h index adba0d52951..f212ba4a287 100644 --- a/sys/dev/mrsas/mrsas_ioctl.h +++ b/sys/dev/mrsas/mrsas_ioctl.h @@ -124,4 +124,13 @@ struct mrsas_iocpacket32 { #pragma pack() #endif /* COMPAT_FREEBSD32 */ +struct mfi_ioc_passthru { + struct mrsas_dcmd_frame ioc_frame; + uint32_t pad_skinny_flag; + uint32_t buf_size; + uint8_t *buf; +} __packed; + +#define MFIIO_PASSTHRU _IOWR('C', 102, struct mfi_ioc_passthru) + #endif /* MRSAS_IOCTL_H */ diff --git a/usr.sbin/mfiutil/mfi_bbu.c b/usr.sbin/mfiutil/mfi_bbu.c index 343d101661d..91684e90120 100644 --- a/usr.sbin/mfiutil/mfi_bbu.c +++ b/usr.sbin/mfiutil/mfi_bbu.c @@ -134,7 +134,7 @@ start_bbu_learn(int ac, char **av __unused) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -171,7 +171,7 @@ update_bbu_props(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); diff --git a/usr.sbin/mfiutil/mfi_cmd.c b/usr.sbin/mfiutil/mfi_cmd.c index 094c9017348..34795bd5721 100644 --- a/usr.sbin/mfiutil/mfi_cmd.c +++ b/usr.sbin/mfiutil/mfi_cmd.c @@ -209,16 +209,20 @@ mfi_volume_busy(int fd, uint8_t target_id) * configuration of the mfi controller. */ int -mfi_reconfig_supported(void) +mfi_reconfig_supported(char *name) { char mibname[64]; size_t len; int dummy; - len = sizeof(dummy); - snprintf(mibname, sizeof(mibname), "dev.mfi.%d.delete_busy_volumes", - mfi_unit); - return (sysctlbyname(mibname, &dummy, &len, NULL, 0) == 0); + if (strcmp(name, MRSAS_TYPE) == 0) + return (1); + else { + len = sizeof(dummy); + snprintf(mibname, sizeof(mibname), + "dev.mfi.%d.delete_busy_volumes", mfi_unit); + return (sysctlbyname(mibname, &dummy, &len, NULL, 0) == 0); + } } int @@ -304,11 +308,11 @@ mfi_ctrl_get_info(int fd, struct mfi_ctrl_info *info, uint8_t *statusp) } int -mfi_open(int unit, int acs) +mfi_open(char *name, int unit, int acs) { char path[MAXPATHLEN]; - snprintf(path, sizeof(path), "/dev/mfi%d", unit); + snprintf(path, sizeof(path), "/dev/%s%d", name, unit); return (open(path, acs)); } diff --git a/usr.sbin/mfiutil/mfi_config.c b/usr.sbin/mfiutil/mfi_config.c index 0ee78fca061..acbe4a81f24 100644 --- a/usr.sbin/mfiutil/mfi_config.c +++ b/usr.sbin/mfiutil/mfi_config.c @@ -162,16 +162,16 @@ clear_config(int ac __unused, char **av __unused) int ch, error, fd; u_int i; - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); return (error); } - if (!mfi_reconfig_supported()) { - warnx("The current mfi(4) driver does not support " - "configuration changes."); + if (!mfi_reconfig_supported(mfi_type)) { + warnx("The current %s(4) driver does not support " + "configuration changes.", mfi_type); close(fd); return (EOPNOTSUPP); } @@ -193,8 +193,8 @@ clear_config(int ac __unused, char **av __unused) } printf( - "Are you sure you wish to clear the configuration on mfi%u? [y/N] ", - mfi_unit); + "Are you sure you wish to clear the configuration on %s%u? [y/N] ", + mfi_type, mfi_unit); ch = getchar(); if (ch != 'y' && ch != 'Y') { printf("\nAborting\n"); @@ -209,7 +209,7 @@ clear_config(int ac __unused, char **av __unused) return (error); } - printf("mfi%d: Configuration cleared\n", mfi_unit); + printf("%s%d: Configuration cleared\n", mfi_type, mfi_unit); close(fd); return (0); @@ -587,16 +587,16 @@ create_volume(int ac, char **av) narrays = 0; error = 0; - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); return (error); } - if (!mfi_reconfig_supported()) { - warnx("The current mfi(4) driver does not support " - "configuration changes."); + if (!mfi_reconfig_supported(mfi_type)) { + warnx("The current %s(4) driver does not support " + "configuration changes.", mfi_type); error = EOPNOTSUPP; goto error; } @@ -869,16 +869,16 @@ delete_volume(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); return (error); } - if (!mfi_reconfig_supported()) { - warnx("The current mfi(4) driver does not support " - "configuration changes."); + if (!mfi_reconfig_supported(mfi_type)) { + warnx("The current %s(4) driver does not support " + "configuration changes.", mfi_type); close(fd); return (EOPNOTSUPP); } @@ -937,7 +937,7 @@ add_spare(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -1062,7 +1062,7 @@ remove_spare(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -1120,7 +1120,7 @@ dump_config(int fd, struct mfi_config_data *config, const char *msg_prefix) msg_prefix = "Configuration (Debug)"; printf( - "mfi%d %s: %d arrays, %d volumes, %d spares\n", mfi_unit, + "%s%d %s: %d arrays, %d volumes, %d spares\n", mfi_type, mfi_unit, msg_prefix, config->array_count, config->log_drv_count, config->spares_count); printf(" array size: %u\n", config->array_size); @@ -1211,7 +1211,7 @@ debug_config(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -1248,7 +1248,7 @@ dump(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); diff --git a/usr.sbin/mfiutil/mfi_drive.c b/usr.sbin/mfiutil/mfi_drive.c index 4fd8fb93dd4..fac59349857 100644 --- a/usr.sbin/mfiutil/mfi_drive.c +++ b/usr.sbin/mfiutil/mfi_drive.c @@ -74,7 +74,7 @@ mfi_drive_name(struct mfi_pd_info *pinfo, uint16_t device_id, uint32_t def) else snprintf(buf, sizeof(buf), "%2u", device_id); - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { warn("mfi_open"); return (buf); @@ -388,7 +388,7 @@ drive_set_state(char *drive, uint16_t new_state) uint8_t mbox[6]; int error, fd; - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -503,7 +503,7 @@ start_rebuild(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -560,7 +560,7 @@ abort_rebuild(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -616,7 +616,7 @@ drive_progress(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -682,7 +682,7 @@ drive_clear(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -742,7 +742,7 @@ drive_locate(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); diff --git a/usr.sbin/mfiutil/mfi_evt.c b/usr.sbin/mfiutil/mfi_evt.c index 915fbb7125b..f2f9347ae99 100644 --- a/usr.sbin/mfiutil/mfi_evt.c +++ b/usr.sbin/mfiutil/mfi_evt.c @@ -77,7 +77,7 @@ show_logstate(int ac, char **av __unused) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -91,7 +91,7 @@ show_logstate(int ac, char **av __unused) return (error); } - printf("mfi%d Event Log Sequence Numbers:\n", mfi_unit); + printf("%s%d Event Log Sequence Numbers:\n", mfi_type, mfi_unit); printf(" Newest Seq #: %u\n", info.newest_seq_num); printf(" Oldest Seq #: %u\n", info.oldest_seq_num); printf(" Clear Seq #: %u\n", info.clear_seq_num); @@ -547,7 +547,7 @@ show_events(int ac, char **av) int ch, error, fd, num_events, verbose; u_int i; - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); diff --git a/usr.sbin/mfiutil/mfi_flash.c b/usr.sbin/mfiutil/mfi_flash.c index 239390acf7b..dd076f4b81f 100644 --- a/usr.sbin/mfiutil/mfi_flash.c +++ b/usr.sbin/mfiutil/mfi_flash.c @@ -58,7 +58,7 @@ display_pending_firmware(int fd) return (error); } - printf("mfi%d Pending Firmware Images:\n", mfi_unit); + printf("%s%d Pending Firmware Images:\n", mfi_type, mfi_unit); strcpy(header.name, "Name"); strcpy(header.version, "Version"); strcpy(header.build_date, "Date"); @@ -122,7 +122,7 @@ flash_adapter(int ac, char **av) goto error; } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); diff --git a/usr.sbin/mfiutil/mfi_foreign.c b/usr.sbin/mfiutil/mfi_foreign.c index ce4b8a704be..4be109326ec 100644 --- a/usr.sbin/mfiutil/mfi_foreign.c +++ b/usr.sbin/mfiutil/mfi_foreign.c @@ -48,7 +48,7 @@ foreign_clear(__unused int ac, __unused char **av) { int ch, error, fd; - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -74,7 +74,7 @@ foreign_clear(__unused int ac, __unused char **av) return (error); } - printf("mfi%d: Foreign configuration cleared\n", mfi_unit); + printf("%s%d: Foreign configuration cleared\n", mfi_type, mfi_unit); close(fd); return (0); } @@ -86,7 +86,7 @@ foreign_scan(__unused int ac, __unused char **av) struct mfi_foreign_scan_info info; int error, fd; - fd = mfi_open(mfi_unit, O_RDONLY); + fd = mfi_open(mfi_type, mfi_unit, O_RDONLY); if (fd < 0) { error = errno; warn("mfi_open"); @@ -101,7 +101,7 @@ foreign_scan(__unused int ac, __unused char **av) return (error); } - printf("mfi%d: Found %d foreign configurations\n", mfi_unit, + printf("%s%d: Found %d foreign configurations\n", mfi_type, mfi_unit, info.count); close(fd); return (0); @@ -222,7 +222,7 @@ display_format(int ac, char **av, int diagnostic, mfi_dcmd_t display_cmd) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDONLY); + fd = mfi_open(mfi_type, mfi_unit, O_RDONLY); if (fd < 0) { error = errno; warn("mfi_open"); @@ -294,7 +294,7 @@ foreign_import(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -355,11 +355,11 @@ foreign_import(int ac, char **av) } if (ac == 1) - printf("mfi%d: All foreign configurations imported\n", - mfi_unit); + printf("%s%d: All foreign configurations imported\n", + mfi_type, mfi_unit); else - printf("mfi%d: Foreign configuration %d imported\n", mfi_unit, - cfgidx); + printf("%s%d: Foreign configuration %d imported\n", + mfi_type, mfi_unit, cfgidx); close(fd); return (0); } diff --git a/usr.sbin/mfiutil/mfi_patrol.c b/usr.sbin/mfiutil/mfi_patrol.c index a1dbb1336f1..bdb3dc98b83 100644 --- a/usr.sbin/mfiutil/mfi_patrol.c +++ b/usr.sbin/mfiutil/mfi_patrol.c @@ -89,7 +89,7 @@ show_patrol(int ac __unused, char **av __unused) int error, fd; u_int i; - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -199,7 +199,7 @@ start_patrol(int ac __unused, char **av __unused) { int error, fd; - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -225,7 +225,7 @@ stop_patrol(int ac __unused, char **av __unused) { int error, fd; - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -295,7 +295,7 @@ patrol_config(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); diff --git a/usr.sbin/mfiutil/mfi_properties.c b/usr.sbin/mfiutil/mfi_properties.c index f5affe14bd5..104e7a11708 100644 --- a/usr.sbin/mfiutil/mfi_properties.c +++ b/usr.sbin/mfiutil/mfi_properties.c @@ -78,7 +78,7 @@ mfi_ctrl_rebuild_rate(int ac, char **av) return(-1); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -130,7 +130,7 @@ mfi_ctrl_alarm_enable(int ac, char **av) return(-1); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); diff --git a/usr.sbin/mfiutil/mfi_show.c b/usr.sbin/mfiutil/mfi_show.c index 17c96776296..fb87669819a 100644 --- a/usr.sbin/mfiutil/mfi_show.c +++ b/usr.sbin/mfiutil/mfi_show.c @@ -66,7 +66,7 @@ show_adapter(int ac, char **av __unused) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDONLY); + fd = mfi_open(mfi_type, mfi_unit, O_RDONLY); if (fd < 0) { error = errno; warn("mfi_open"); @@ -79,7 +79,7 @@ show_adapter(int ac, char **av __unused) close(fd); return (error); } - printf("mfi%d Adapter:\n", mfi_unit); + printf("%s%d Adapter:\n", mfi_type, mfi_unit); printf(" Product Name: %.80s\n", info.product_name); printf(" Serial Number: %.32s\n", info.serial_number); if (info.package_version[0] != '\0') @@ -155,7 +155,7 @@ show_battery(int ac, char **av __unused) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDONLY); + fd = mfi_open(mfi_type, mfi_unit, O_RDONLY); if (fd < 0) { error = errno; warn("mfi_open"); @@ -170,7 +170,7 @@ show_battery(int ac, char **av __unused) return (error); } if (status == MFI_STAT_NO_HW_PRESENT) { - printf("mfi%d: No battery present\n", mfi_unit); + printf("%s%d: No battery present\n", mfi_type, mfi_unit); close(fd); return (0); } @@ -200,7 +200,7 @@ show_battery(int ac, char **av __unused) } show_props = (status == MFI_STAT_OK); - printf("mfi%d: Battery State:\n", mfi_unit); + printf("%s%d: Battery State:\n", mfi_type, mfi_unit); printf(" Manufacture Date: %d/%d/%d\n", design.mfg_date >> 5 & 0x0f, design.mfg_date & 0x1f, design.mfg_date >> 9 & 0xffff); printf(" Serial Number: %d\n", design.serial_number); @@ -357,7 +357,7 @@ show_config(int ac, char **av __unused) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDONLY); + fd = mfi_open(mfi_type, mfi_unit, O_RDONLY); if (fd < 0) { error = errno; warn("mfi_open"); @@ -373,8 +373,8 @@ show_config(int ac, char **av __unused) } /* Dump out the configuration. */ - printf("mfi%d Configuration: %d arrays, %d volumes, %d spares\n", - mfi_unit, config->array_count, config->log_drv_count, + printf("%s%d Configuration: %d arrays, %d volumes, %d spares\n", + mfi_type, mfi_unit, config->array_count, config->log_drv_count, config->spares_count); p = (char *)config->array; @@ -458,7 +458,7 @@ show_volumes(int ac, char **av __unused) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDONLY); + fd = mfi_open(mfi_type, mfi_unit, O_RDONLY); if (fd < 0) { error = errno; warn("mfi_open"); @@ -474,7 +474,7 @@ show_volumes(int ac, char **av __unused) } /* List the volumes. */ - printf("mfi%d Volumes:\n", mfi_unit); + printf("%s%d Volumes:\n", mfi_type, mfi_unit); state_len = strlen("State"); for (i = 0; i < list.ld_count; i++) { len = strlen(mfi_ldstate(list.ld_list[i].state)); @@ -541,7 +541,7 @@ show_drives(int ac, char **av __unused) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDONLY); + fd = mfi_open(mfi_type, mfi_unit, O_RDONLY); if (fd < 0) { error = errno; warn("mfi_open"); @@ -576,7 +576,7 @@ show_drives(int ac, char **av __unused) } /* List the drives. */ - printf("mfi%d Physical Drives:\n", mfi_unit); + printf("%s%d Physical Drives:\n", mfi_type, mfi_unit); for (i = 0; i < list->count; i++) { /* Skip non-hard disks. */ @@ -621,7 +621,7 @@ show_firmware(int ac, char **av __unused) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDONLY); + fd = mfi_open(mfi_type, mfi_unit, O_RDONLY); if (fd < 0) { error = errno; warn("mfi_open"); @@ -636,9 +636,9 @@ show_firmware(int ac, char **av __unused) } if (info.package_version[0] != '\0') - printf("mfi%d Firmware Package Version: %s\n", mfi_unit, - info.package_version); - printf("mfi%d Firmware Images:\n", mfi_unit); + printf("%s%d Firmware Package Version: %s\n", mfi_type, + mfi_unit, info.package_version); + printf("%s%d Firmware Images:\n", mfi_type, mfi_unit); strcpy(header.name, "Name"); strcpy(header.version, "Version"); strcpy(header.build_date, "Date"); @@ -681,7 +681,7 @@ show_progress(int ac, char **av __unused) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDONLY); + fd = mfi_open(mfi_type, mfi_unit, O_RDONLY); if (fd < 0) { error = errno; warn("mfi_open"); @@ -776,7 +776,8 @@ show_progress(int ac, char **av __unused) close(fd); if (!busy) - printf("No activity in progress for adapter mfi%d\n", mfi_unit); + printf("No activity in progress for adapter %s%d\n", + mfi_type, mfi_unit); return (0); } diff --git a/usr.sbin/mfiutil/mfi_volume.c b/usr.sbin/mfiutil/mfi_volume.c index 2bc913374b8..a1832e1efa7 100644 --- a/usr.sbin/mfiutil/mfi_volume.c +++ b/usr.sbin/mfiutil/mfi_volume.c @@ -297,7 +297,7 @@ volume_cache(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -406,7 +406,7 @@ volume_name(int ac, char **av) return (ENOSPC); } - fd = mfi_open(mfi_unit, O_RDWR); + fd = mfi_open(mfi_type, mfi_unit, O_RDWR); if (fd < 0) { error = errno; warn("mfi_open"); @@ -457,7 +457,7 @@ volume_progress(int ac, char **av) return (EINVAL); } - fd = mfi_open(mfi_unit, O_RDONLY); + fd = mfi_open(mfi_type, mfi_unit, O_RDONLY); if (fd < 0) { error = errno; warn("mfi_open"); diff --git a/usr.sbin/mfiutil/mfiutil.8 b/usr.sbin/mfiutil/mfiutil.8 index e3adc0b6569..b5bb6b6fc84 100644 --- a/usr.sbin/mfiutil/mfiutil.8 +++ b/usr.sbin/mfiutil/mfiutil.8 @@ -31,26 +31,31 @@ .Dt MFIUTIL 8 .Os .Sh NAME -.Nm mfiutil +.Nm mfiutil, mrsasutil .Nd Utility for managing LSI MegaRAID SAS controllers .Sh SYNOPSIS .Nm .Cm version .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm show adapter .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm show battery .Nm .Op Fl d .Op Fl e +.Op Fl t Ar type .Op Fl u Ar unit .Cm show config .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm show drives .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm show events .Op Fl c Ar class @@ -59,67 +64,87 @@ .Op Fl v .Op Ar start Op Ar stop .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm show firmware .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm show foreign Op Ar volume .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm show logstate .Nm .Op Fl d .Op Fl e +.Op Fl t Ar type .Op Fl u Ar unit .Cm show patrol .Nm .Op Fl d .Op Fl e +.Op Fl t Ar type .Op Fl u Ar unit .Cm show progress .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm show volumes .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm fail Ar drive .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm good Ar drive .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm rebuild Ar drive .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm syspd Ar drive .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm drive progress Ar drive .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm drive clear Ar drive Brq "start | stop" .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm start rebuild Ar drive .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm abort rebuild Ar drive .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm locate Ar drive Brq "on | off" .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm cache Ar volume Op Ar setting Oo Ar value Oc Op ... .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm name Ar volume Ar name .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm volume progress Ar volume .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm clear .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm create Ar type .Op Fl v @@ -127,51 +152,67 @@ .Ar drive Ns Op \&, Ns Ar drive Ns Op ",..." .Op Ar drive Ns Op \&, Ns Ar drive Ns Op ",..." .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm delete Ar volume .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm add Ar drive Op Ar volume .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm remove Ar drive .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm start patrol .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm stop patrol .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm patrol Ar command Op Ar interval Op Ar start .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm foreign scan .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm foreign clear Op Ar config .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm foreign diag Op Ar config .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm foreign preview Op Ar config .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm foreign import Op Ar config .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm flash Ar file .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm start learn .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm bbu Ar setting Ar value .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm ctrlprop Ar rebuild Op Ar rate .Nm +.Op Fl t Ar type .Op Fl u Ar unit .Cm ctrlprop Ar alarm Op Ar 0/1 .Sh DESCRIPTION @@ -185,8 +226,13 @@ consists of zero or more global options followed by a command. Commands may support additional optional or required arguments after the command. .Pp -Currently one global option is supported: +Currently two global option is supported: .Bl -tag -width indent +.It Fl t Ar type +.Ar unit +specifies the type of the controller to work with either mfi or mrsas +If no type is specified, +then the name of the invoked tool used for the type. .It Fl u Ar unit .Ar unit specifies the unit of the controller to work with. diff --git a/usr.sbin/mfiutil/mfiutil.c b/usr.sbin/mfiutil/mfiutil.c index 8d4dffc0c91..c62e01e85b4 100644 --- a/usr.sbin/mfiutil/mfiutil.c +++ b/usr.sbin/mfiutil/mfiutil.c @@ -45,7 +45,8 @@ MFI_TABLE(top, start); MFI_TABLE(top, stop); MFI_TABLE(top, abort); -int mfi_unit; +int mfi_unit = 0; +char *mfi_type = NULL; u_int mfi_opts; static int fw_name_width, fw_version_width, fw_date_width, fw_time_width; @@ -53,7 +54,7 @@ static void usage(void) { - fprintf(stderr, "usage: mfiutil [-de] [-u unit] ...\n\n"); + fprintf(stderr, "usage: mfiutil [-de] [-u unit] [-t type] ...\n\n"); fprintf(stderr, "Commands include:\n"); fprintf(stderr, " version\n"); fprintf(stderr, " show adapter - display controller information\n"); @@ -122,8 +123,27 @@ main(int ac, char **av) { struct mfiutil_command **cmd; int ch; + const char *pn; + + pn = getprogname(); + + if (strcmp(pn, "mrsasutil") == 0) { + mfi_type = malloc(strlen(MRSAS_TYPE) + 1); + if (mfi_type == NULL) { + fprintf(stderr, "Can't malloc\n"); + exit(1); + } + strcpy(mfi_type, MRSAS_TYPE); + } else { + mfi_type = malloc(strlen(MFI_TYPE) + 1); + if (mfi_type == NULL) { + fprintf(stderr, "Can't malloc\n"); + exit(1); + } + strcpy(mfi_type, MFI_TYPE); + } - while ((ch = getopt(ac, av, "deu:")) != -1) { + while ((ch = getopt(ac, av, "deu:t:")) != -1) { switch (ch) { case 'd': mfi_opts |= MFI_DNAME_DEVICE_ID; @@ -134,6 +154,9 @@ main(int ac, char **av) case 'u': mfi_unit = atoi(optarg); break; + case 't': + mfi_type = optarg; + break; case '?': usage(); } diff --git a/usr.sbin/mfiutil/mfiutil.h b/usr.sbin/mfiutil/mfiutil.h index cedac5ac1dd..bd7c6dcce4d 100644 --- a/usr.sbin/mfiutil/mfiutil.h +++ b/usr.sbin/mfiutil/mfiutil.h @@ -39,6 +39,9 @@ #include +#define MRSAS_TYPE "mrsas" +#define MFI_TYPE "mfi" + /* 4.x compat */ #ifndef SET_DECLARE @@ -123,6 +126,7 @@ struct mfiutil_command { #define MFI_DNAME_HONOR_OPTS 0x8000 /* Allow cmd line to override default */ extern int mfi_unit; +extern char *mfi_type; extern u_int mfi_opts; @@ -154,7 +158,7 @@ int mfi_lookup_drive(int fd, char *drive, uint16_t *device_id); int mfi_lookup_volume(int fd, const char *name, uint8_t *target_id); int mfi_dcmd_command(int fd, uint32_t opcode, void *buf, size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp); -int mfi_open(int unit, int acs); +int mfi_open(char *name, int unit, int acs); int mfi_ctrl_get_info(int fd, struct mfi_ctrl_info *info, uint8_t *statusp); int mfi_ld_get_info(int fd, uint8_t target_id, struct mfi_ld_info *info, uint8_t *statusp); @@ -162,7 +166,7 @@ int mfi_ld_get_list(int fd, struct mfi_ld_list *list, uint8_t *statusp); int mfi_pd_get_info(int fd, uint16_t device_id, struct mfi_pd_info *info, uint8_t *statusp); int mfi_pd_get_list(int fd, struct mfi_pd_list **listp, uint8_t *statusp); -int mfi_reconfig_supported(void); +int mfi_reconfig_supported(char *name); const char *mfi_status(u_int status_code); const char *mfi_drive_name(struct mfi_pd_info *pinfo, uint16_t device_id, uint32_t def);