diff --git a/sys/dev/mfi/mfireg.h b/sys/dev/mfi/mfireg.h index 8f88f103e319..acb1df58c2d1 100644 --- a/sys/dev/mfi/mfireg.h +++ b/sys/dev/mfi/mfireg.h @@ -230,7 +230,11 @@ typedef enum { MFI_DCMD_CFG_CLEAR = 0x04030000, MFI_DCMD_CFG_MAKE_SPARE = 0x04040000, MFI_DCMD_CFG_REMOVE_SPARE = 0x04050000, + MFI_DCMD_CFG_FOREIGN_SCAN = 0x04060100, + MFI_DCMD_CFG_FOREIGN_DISPLAY = 0x04060200, + MFI_DCMD_CFG_FOREIGN_PREVIEW = 0x04060300, MFI_DCMD_CFG_FOREIGN_IMPORT = 0x04060400, + MFI_DCMD_CFG_FOREIGN_CLEAR = 0x04060500, MFI_DCMD_BBU_GET_STATUS = 0x05010000, MFI_DCMD_BBU_GET_CAPACITY_INFO =0x05020000, MFI_DCMD_BBU_GET_DESIGN_INFO = 0x05030000, diff --git a/usr.sbin/mfiutil/Makefile b/usr.sbin/mfiutil/Makefile index c460b3fa02ed..f6e358a24e62 100644 --- a/usr.sbin/mfiutil/Makefile +++ b/usr.sbin/mfiutil/Makefile @@ -2,7 +2,7 @@ PROG= mfiutil SRCS= mfiutil.c mfi_bbu.c mfi_cmd.c mfi_config.c mfi_drive.c mfi_evt.c \ - mfi_flash.c mfi_patrol.c mfi_show.c mfi_volume.c + mfi_flash.c mfi_patrol.c mfi_show.c mfi_volume.c mfi_foreign.c MAN8= mfiutil.8 CFLAGS+= -fno-builtin-strftime diff --git a/usr.sbin/mfiutil/mfi_config.c b/usr.sbin/mfiutil/mfi_config.c index 8576bc3325cf..a91921491518 100644 --- a/usr.sbin/mfiutil/mfi_config.c +++ b/usr.sbin/mfiutil/mfi_config.c @@ -37,19 +37,13 @@ #include #include #include -#ifdef DEBUG #include -#endif #include #include #include #include #include "mfiutil.h" -#ifdef DEBUG -static void dump_config(int fd, struct mfi_config_data *config); -#endif - static int add_spare(int ac, char **av); static int remove_spare(int ac, char **av); @@ -81,8 +75,16 @@ dehumanize(const char *value) } return (iv); } + int mfi_config_read(int fd, struct mfi_config_data **configp) +{ + return mfi_config_read_opcode(fd, MFI_DCMD_CFG_READ, configp, NULL, 0); +} + +int +mfi_config_read_opcode(int fd, uint32_t opcode, struct mfi_config_data **configp, + uint8_t *mbox, size_t mboxlen) { struct mfi_config_data *config; uint32_t config_size; @@ -98,8 +100,8 @@ mfi_config_read(int fd, struct mfi_config_data **configp) config = reallocf(config, config_size); if (config == NULL) return (-1); - if (mfi_dcmd_command(fd, MFI_DCMD_CFG_READ, config, - config_size, NULL, 0, NULL) < 0) { + if (mfi_dcmd_command(fd, opcode, config, + config_size, mbox, mboxlen, NULL) < 0) { error = errno; free(config); errno = error; @@ -366,6 +368,13 @@ parse_array(int fd, int raid_type, char *array_str, struct array_info *info) info->drives = NULL; return (EINVAL); } + + if (pinfo->state.ddf.v.pd_type.is_foreign) { + warnx("Drive %u is foreign", device_id); + free(info->drives); + info->drives = NULL; + return (EINVAL); + } } return (0); @@ -804,7 +813,7 @@ create_volume(int ac, char **av) #ifdef DEBUG if (dump) - dump_config(fd, config); + dump_config(fd, config, NULL); #endif /* Send the new config to the controller. */ @@ -1093,10 +1102,9 @@ remove_spare(int ac, char **av) } MFI_COMMAND(top, remove, remove_spare); -#ifdef DEBUG /* Display raw data about a config. */ -static void -dump_config(int fd, struct mfi_config_data *config) +void +dump_config(int fd, struct mfi_config_data *config, const char *msg_prefix) { struct mfi_array *ar; struct mfi_ld_config *ld; @@ -1106,9 +1114,12 @@ dump_config(int fd, struct mfi_config_data *config) char *p; int i, j; + if (NULL == msg_prefix) + msg_prefix = "Configuration (Debug)"; + printf( - "mfi%d Configuration (Debug): %d arrays, %d volumes, %d spares\n", - mfi_unit, config->array_count, config->log_drv_count, + "mfi%d %s: %d arrays, %d volumes, %d spares\n", mfi_unit, + msg_prefix, config->array_count, config->log_drv_count, config->spares_count); printf(" array size: %u\n", config->array_size); printf(" volume size: %u\n", config->log_drv_size); @@ -1186,6 +1197,7 @@ dump_config(int fd, struct mfi_config_data *config) } } +#ifdef DEBUG static int debug_config(int ac, char **av) { @@ -1213,7 +1225,7 @@ debug_config(int ac, char **av) } /* Dump out the configuration. */ - dump_config(fd, config); + dump_config(fd, config, NULL); free(config); close(fd); @@ -1265,7 +1277,7 @@ dump(int ac, char **av) close(fd); return (error); } - dump_config(fd, config); + dump_config(fd, config, NULL); free(config); close(fd); diff --git a/usr.sbin/mfiutil/mfi_foreign.c b/usr.sbin/mfiutil/mfi_foreign.c new file mode 100644 index 000000000000..8c6183d7788d --- /dev/null +++ b/usr.sbin/mfiutil/mfi_foreign.c @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2013 smh@freebsd.org + * 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. + * + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mfiutil.h" + +MFI_TABLE(top, foreign); + +static int +foreign_clear(__unused int ac, __unused char **av) +{ + int ch, error, fd; + + fd = mfi_open(mfi_unit, O_RDWR); + if (fd < 0) { + error = errno; + warn("mfi_open"); + return (error); + } + + printf( + "Are you sure you wish to clear ALL foreign configurations" + " on mfi%u? [y/N] ", mfi_unit); + + ch = getchar(); + if (ch != 'y' && ch != 'Y') { + printf("\nAborting\n"); + close(fd); + return (0); + } + + if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_CLEAR, NULL, 0, NULL, + 0, NULL) < 0) { + error = errno; + warn("Failed to clear foreign configuration"); + close(fd); + return (error); + } + + printf("mfi%d: Foreign configuration cleared\n", mfi_unit); + close(fd); + return (0); +} +MFI_COMMAND(foreign, clear, foreign_clear); + +static int +foreign_scan(__unused int ac, __unused char **av) +{ + struct mfi_foreign_scan_info info; + int error, fd; + + fd = mfi_open(mfi_unit, O_RDONLY); + if (fd < 0) { + error = errno; + warn("mfi_open"); + return (error); + } + + if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_SCAN, &info, + sizeof(info), NULL, 0, NULL) < 0) { + error = errno; + warn("Failed to scan foreign configuration"); + close(fd); + return (error); + } + + printf("mfi%d: Found %d foreign configurations\n", mfi_unit, + info.count); + close(fd); + return (0); +} +MFI_COMMAND(foreign, scan, foreign_scan); + +static int +foreign_show_cfg(int fd, uint32_t opcode, uint8_t cfgidx, int diagnostic) +{ + struct mfi_config_data *config; + char prefix[26]; + int error; + uint8_t mbox[4]; + + bzero(mbox, sizeof(mbox)); + mbox[0] = cfgidx; + if (mfi_config_read_opcode(fd, opcode, &config, mbox, sizeof(mbox)) < 0) { + error = errno; + warn("Failed to get foreign config %d", error); + close(fd); + return (error); + } + + if (opcode == MFI_DCMD_CFG_FOREIGN_PREVIEW) + sprintf(prefix, "Foreign configuration preview %d", cfgidx); + else + sprintf(prefix, "Foreign configuration %d", cfgidx); + /* + * MegaCli uses DCMD opcodes: 0x03100200 (which fails) followed by + * 0x1a721880 which returns what looks to be drive / volume info + * but we have no real information on what these are or what they do + * so we're currently relying solely on the config returned above + */ + if (diagnostic) + dump_config(fd, config, prefix); + else { + char *ld_list; + int i; + + ld_list = (char *)(config->array); + + printf("%s: %d arrays, %d volumes, %d spares\n", prefix, + config->array_count, config->log_drv_count, + config->spares_count); + + + for (i = 0; i < config->array_count; i++) + ld_list += config->array_size; + + for (i = 0; i < config->log_drv_count; i++) { + const char *level; + char size[6], stripe[5]; + struct mfi_ld_config *ld; + + ld = (struct mfi_ld_config *)ld_list; + + format_stripe(stripe, sizeof(stripe), + ld->params.stripe_size); + /* + * foreign configs don't seem to have a secondary raid level + * but, we can use span depth here as if a LD spans multiple + * arrays of disks (2 raid 1 sets for example), we will have an + * indication based on the spam depth. swb + */ + level = mfi_raid_level(ld->params.primary_raid_level, + (ld->params.span_depth - 1)); + + humanize_number(size, sizeof(size), ld->span[0].num_blocks * 512, + "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); + + printf(" ID%d ", i); + printf("(%6s) %-8s |", + size, level); + printf("volume spans %d %s\n", ld->params.span_depth, + (ld->params.span_depth > 1) ? "arrays" : "array"); + for (int j = 0; j < ld->params.span_depth; j++) { + char *ar_list; + struct mfi_array *ar; + uint16_t device_id; + + printf(" array %u @ ", ld->span[j].array_ref); + humanize_number(size, sizeof(size), ld->span[j].num_blocks * 512, + "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); + + printf("(%6s)\n",size); + ar_list = (char *)config->array + (ld->span[j].array_ref * config->array_size); + + ar = (struct mfi_array *)ar_list; + for (int k = 0; k < ar->num_drives; k++) { + device_id = ar->pd[k].ref.v.device_id; + if (device_id == 0xffff) + printf(" drive MISSING\n"); + else { + printf(" drive %u %s\n", device_id, + mfi_pdstate(ar->pd[k].fw_state)); + } + } + + } + ld_list += config->log_drv_size; + } + } + + free(config); + + return (0); +} + +int +display_format(int ac, char **av, int diagnostic, mfi_dcmd_t display_cmd) +{ + struct mfi_foreign_scan_info info; + uint8_t i; + int error, fd; + + if (ac > 2) { + warnx("foreign display: extra arguments"); + return (EINVAL); + } + + fd = mfi_open(mfi_unit, O_RDONLY); + if (fd < 0) { + error = errno; + warn("mfi_open"); + return (error); + } + + if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_SCAN, &info, + sizeof(info), NULL, 0, NULL) < 0) { + error = errno; + warn("Failed to scan foreign configuration"); + close(fd); + return (error); + } + + if (info.count == 0) { + warnx("foreign display: no foreign configs found"); + close(fd); + return (EINVAL); + } + + if (ac == 1) { + for (i = 0; i < info.count; i++) { + error = foreign_show_cfg(fd, + display_cmd, i, diagnostic); + if(error != 0) { + close(fd); + return (error); + } + if (i < info.count - 1) + printf("\n"); + } + } else if (ac == 2) { + error = foreign_show_cfg(fd, + display_cmd, atoi(av[1]), diagnostic); + if (error != 0) { + close(fd); + return (error); + } + } + + close(fd); + return (0); +} + +static int +foreign_display(int ac, char **av) +{ + return(display_format(ac, av, 1/*diagnostic output*/, MFI_DCMD_CFG_FOREIGN_DISPLAY)); +} +MFI_COMMAND(foreign, diag, foreign_display); + +static int +foreign_preview(int ac, char **av) +{ + return(display_format(ac, av, 1/*diagnostic output*/, MFI_DCMD_CFG_FOREIGN_PREVIEW)); +} +MFI_COMMAND(foreign, preview, foreign_preview); + +static int +foreign_import(int ac, char **av) +{ + struct mfi_foreign_scan_info info; + int ch, error, fd; + uint8_t cfgidx; + uint8_t mbox[4]; + + if (ac > 2) { + warnx("foreign preview: extra arguments"); + return (EINVAL); + } + + fd = mfi_open(mfi_unit, O_RDWR); + if (fd < 0) { + error = errno; + warn("mfi_open"); + return (error); + } + + if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_SCAN, &info, + sizeof(info), NULL, 0, NULL) < 0) { + error = errno; + warn("Failed to scan foreign configuration"); + close(fd); + return (error); + } + + if (info.count == 0) { + warnx("foreign import: no foreign configs found"); + close(fd); + return (EINVAL); + } + + if (ac == 1) { + cfgidx = 0xff; + printf("Are you sure you wish to import ALL foreign " + "configurations on mfi%u? [y/N] ", mfi_unit); + } else { + /* + * While this is docmmented for MegaCli this failed with + * exit code 0x03 on the test controller which was a Supermicro + * SMC2108 with firmware 12.12.0-0095 which is a LSI 2108 based + * controller. + */ + cfgidx = atoi(av[1]); + if (cfgidx >= info.count) { + warnx("Invalid foreign config %d specified max is %d", + cfgidx, info.count - 1); + close(fd); + return (EINVAL); + } + printf("Are you sure you wish to import the foreign " + "configuration %d on mfi%u? [y/N] ", cfgidx, mfi_unit); + } + + ch = getchar(); + if (ch != 'y' && ch != 'Y') { + printf("\nAborting\n"); + close(fd); + return (0); + } + + bzero(mbox, sizeof(mbox)); + mbox[0] = cfgidx; + if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_IMPORT, NULL, 0, mbox, + sizeof(mbox), NULL) < 0) { + error = errno; + warn("Failed to import foreign configuration"); + close(fd); + return (error); + } + + if (ac == 1) + printf("mfi%d: All foreign configurations imported\n", + mfi_unit); + else + printf("mfi%d: Foreign configuration %d imported\n", mfi_unit, + cfgidx); + close(fd); + return (0); +} +MFI_COMMAND(foreign, import, foreign_import); diff --git a/usr.sbin/mfiutil/mfi_show.c b/usr.sbin/mfiutil/mfi_show.c index 06721c2e8a04..6bb86124f996 100644 --- a/usr.sbin/mfiutil/mfi_show.c +++ b/usr.sbin/mfiutil/mfi_show.c @@ -40,9 +40,11 @@ #include #include "mfiutil.h" +static const char* foreign_state = " (FOREIGN)"; + MFI_TABLE(top, show); -static void +void format_stripe(char *buf, size_t buflen, uint8_t stripe) { @@ -291,7 +293,7 @@ show_battery(int ac, char **av __unused) } MFI_COMMAND(show, battery, show_battery); -static void +void print_ld(struct mfi_ld_info *info, int state_len) { struct mfi_ld_params *params = &info->ld_config.params; @@ -312,19 +314,24 @@ print_ld(struct mfi_ld_info *info, int state_len) mfi_ldstate(params->state)); } -static void +void print_pd(struct mfi_pd_info *info, int state_len) { const char *s; - char buf[6]; + char buf[256]; humanize_number(buf, sizeof(buf), info->raw_size * 512, "", HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL); printf("(%6s) ", buf); + if (info->state.ddf.v.pd_type.is_foreign) { + sprintf(buf, "%s%s", mfi_pdstate(info->fw_state), foreign_state); + s = buf; + } else + s = mfi_pdstate(info->fw_state); if (state_len > 0) - printf("%-*s", state_len, mfi_pdstate(info->fw_state)); + printf("%-*s", state_len, s); else - printf("%s", mfi_pdstate(info->fw_state)); + printf("%s",s); s = mfi_pd_inq_string(info); if (s != NULL) printf(" %s", s); @@ -560,6 +567,8 @@ show_drives(int ac, char **av __unused) goto error; } len = strlen(mfi_pdstate(info.fw_state)); + if (info.state.ddf.v.pd_type.is_foreign) + len += strlen(foreign_state); if (len > state_len) state_len = len; } @@ -757,7 +766,7 @@ show_progress(int ac, char **av __unused) printf("drive %s ", mfi_drive_name(NULL, device_id, MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); mfi_display_progress("Clear", &pinfo.prog_info.clear); - busy = 1; + } } @@ -770,3 +779,10 @@ show_progress(int ac, char **av __unused) return (0); } MFI_COMMAND(show, progress, show_progress); + +static int +show_foreign(int ac, char **av) +{ + return(display_format(ac, av, 0/*normal display*/, MFI_DCMD_CFG_FOREIGN_DISPLAY)); +} +MFI_COMMAND(show, foreign, show_foreign); diff --git a/usr.sbin/mfiutil/mfiutil.8 b/usr.sbin/mfiutil/mfiutil.8 index e507ae001df0..6dcc927e1081 100644 --- a/usr.sbin/mfiutil/mfiutil.8 +++ b/usr.sbin/mfiutil/mfiutil.8 @@ -63,6 +63,9 @@ .Cm show firmware .Nm .Op Fl u Ar unit +.Cm show foreign Op Ar volume +.Nm +.Op Fl u Ar unit .Cm show logstate .Nm .Op Fl d @@ -140,6 +143,21 @@ .Cm patrol Ar command Op Ar interval Op Ar start .Nm .Op Fl u Ar unit +.Cm foreign scan +.Nm +.Op Fl u Ar unit +.Cm foreign clear Op Ar config +.Nm +.Op Fl u Ar unit +.Cm foreign diag Op Ar config +.Nm +.Op Fl u Ar unit +.Cm foreign preview Op Ar config +.Nm +.Op Fl u Ar unit +.Cm foreign import Op Ar config +.Nm +.Op Fl u Ar unit .Cm flash Ar file .Nm .Op Fl u Ar unit @@ -321,6 +339,8 @@ The entry in the event log corresponding to the most recent boot. .El .It Cm show firmware Lists all of the firmware images present on the controller. +.It Cm show foreign +Displays detected foreign configurations on disks for importation or removal. .It Cm show logstate Display the various sequence numbers associated with the event log. .It Cm show patrol @@ -567,6 +587,35 @@ Enable manual patrol reads that are only initiated by the user. Start a patrol read operation. .It Cm stop patrol Stop a currently running patrol read operation. +.It Cm foreign scan +Scan for foreign configurations and display the number found. The +.Ar config +argument for the commands below takes the form of a number from 0 to the total +configurations found. +.It Cm foreign clear Op config +Clear the specifed foreign +.Ar config +or all if no +.Ar config +argument is provided. +.It Cm foreign diag Op config +Display a diagnostic display of the specifed foreign +.Ar config +or all if no +.Ar config +argument is provided. +.It Cm foreign preview Op config +Preview the specifed foreign +.Ar config +after import or all if no +.Ar config +argument is provided. +.It Cm foreign import Op config +Import the specifed foreign +.Ar config +or all if no +.Ar config +argument is provided. .It Cm flash Ar file Updates the flash on the controller with the firmware stored in .Ar file . @@ -634,6 +683,10 @@ Configure the adapter to run periodic patrol reads once a week with the first patrol read starting in 5 minutes: .Pp .Dl Nm Cm patrol auto 604800 300 +.Pp +Display the second detected foreign configuration: +.Pp +.Dl Nm Cm show foreign 1 .Sh SEE ALSO .Xr mfi 4 .Sh HISTORY diff --git a/usr.sbin/mfiutil/mfiutil.c b/usr.sbin/mfiutil/mfiutil.c index 7488e24d825e..2fb5adf522c6 100644 --- a/usr.sbin/mfiutil/mfiutil.c +++ b/usr.sbin/mfiutil/mfiutil.c @@ -60,6 +60,7 @@ usage(void) fprintf(stderr, " show drives - list physical drives\n"); fprintf(stderr, " show events - display event log\n"); fprintf(stderr, " show firmware - list firmware images\n"); + fprintf(stderr, " show foreign - display detected foreign volumes\n"); fprintf(stderr, " show logstate - display event log sequence numbers\n"); fprintf(stderr, " show volumes - list logical volumes\n"); fprintf(stderr, " show patrol - display patrol read status\n"); @@ -83,6 +84,11 @@ usage(void) fprintf(stderr, " patrol [interval [start]]\n"); fprintf(stderr, " start patrol - start a patrol read\n"); fprintf(stderr, " stop patrol - stop a patrol read\n"); + fprintf(stderr, " foreign scan - scan for foreign configurations\n"); + fprintf(stderr, " foreign clear [volume] - clear foreign configurations (default all)\n"); + fprintf(stderr, " foreign diag [volume] - diagnostic display foreign configurations (default all)\n"); + fprintf(stderr, " foreign preview [volume] - preview foreign configurations (default all)\n"); + fprintf(stderr, " foreign import [volume] - import foreign configurations (default all)\n"); fprintf(stderr, " flash \n"); fprintf(stderr, " start learn - start a BBU relearn\n"); fprintf(stderr, " bbu - set BBU properties\n"); diff --git a/usr.sbin/mfiutil/mfiutil.h b/usr.sbin/mfiutil/mfiutil.h index 8a544c29350e..251816a51e75 100644 --- a/usr.sbin/mfiutil/mfiutil.h +++ b/usr.sbin/mfiutil/mfiutil.h @@ -124,6 +124,16 @@ extern int mfi_unit; extern u_int mfi_opts; +/* We currently don't know the full details of the following struct */ +struct mfi_foreign_scan_cfg { + char data[24]; +}; + +struct mfi_foreign_scan_info { + uint32_t count; /* Number of foreign configs found */ + struct mfi_foreign_scan_cfg cfgs[8]; +}; + void mbox_store_ldref(uint8_t *mbox, union mfi_ld_ref *ref); void mbox_store_pdref(uint8_t *mbox, union mfi_pd_ref *ref); void mfi_display_progress(const char *label, struct mfi_progress *prog); @@ -136,6 +146,8 @@ const char *mfi_pd_inq_string(struct mfi_pd_info *info); const char *mfi_volume_name(int fd, uint8_t target_id); int mfi_volume_busy(int fd, uint8_t target_id); int mfi_config_read(int fd, struct mfi_config_data **configp); +int mfi_config_read_opcode(int fd, uint32_t opcode, + struct mfi_config_data **configp, uint8_t *mbox, size_t mboxlen); 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, @@ -152,6 +164,10 @@ int mfi_reconfig_supported(void); 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); +void format_stripe(char *buf, size_t buflen, uint8_t stripe); +void print_ld(struct mfi_ld_info *info, int state_len); +void print_pd(struct mfi_pd_info *info, int state_len); +void dump_config(int fd, struct mfi_config_data *config, const char *msg_prefix); int mfi_bbu_get_props(int fd, struct mfi_bbu_properties *props, uint8_t *statusp); int mfi_bbu_set_props(int fd, struct mfi_bbu_properties *props, @@ -163,4 +179,5 @@ void mfi_autolearn_mode(uint8_t, char *, size_t); void scan_firmware(struct mfi_info_component *comp); void display_firmware(struct mfi_info_component *comp, const char *tag); +int display_format(int ac, char **av, int diagnostic, mfi_dcmd_t display_cmd); #endif /* !__MFIUTIL_H__ */