kern/172091: [mfi] [patch] Improvements to mfi support including foreign disks / configs in mfiutil

Steven Hartland killing at multiplay.co.uk
Thu Nov 1 12:10:02 UTC 2012


The following reply was made to PR kern/172091; it has been noted by GNATS.

From: "Steven Hartland" <killing at multiplay.co.uk>
To: <bug-followup at freebsd.org>
Cc:  
Subject: Re: kern/172091: [mfi] [patch] Improvements to mfi support including foreign disks / configs in mfiutil
Date: Thu, 1 Nov 2012 12:04:31 -0000

 This is a multi-part message in MIME format.
 
 ------=_NextPart_000_02D4_01CDB829.0CDC8180
 Content-Type: text/plain;
 	format=flowed;
 	charset="Windows-1252";
 	reply-type=original
 Content-Transfer-Encoding: 7bit
 
 Trying to send the updated patch again (renamed to .txt)
 
 ================================================
 This e.mail is private and confidential between Multiplay (UK) Ltd. and the person or entity to whom it is addressed. In the event of misdirection, the recipient is prohibited from using, copying, printing or otherwise disseminating it or any information contained in it. 
 
 In the event of misdirection, illegible or incomplete transmission please telephone +44 845 868 1337
 or return the E.mail to postmaster at multiplay.co.uk.
 ------=_NextPart_000_02D4_01CDB829.0CDC8180
 Content-Type: text/plain;
 	format=flowed;
 	name="z-mfi-foreign-timeout.txt";
 	reply-type=original
 Content-Transfer-Encoding: quoted-printable
 Content-Disposition: attachment;
 	filename="z-mfi-foreign-timeout.txt"
 
 Add support for foreign disks / configs this implements the following new=0A=
 methods to mfiutil=0A=
 * foreign scan - lists the number of foreign configs=0A=
 * foreign drives - lists the drives which are flagged as foreign=0A=
 * foreign display - displays the specified foreign configuration=0A=
 * foreign preview - previews the specified foreign configuration (after =
 import)=0A=
 * foreign clear - clears the foreign configuration=0A=
 * foreign import - imports the foreign configuration=0A=
 =0A=
 mfiutil show drives - now identifies foreign drives=0A=
 =0A=
 It should be noted that although foreign import takes a configuration =
 option=0A=
 this currently fails with error code 0x03 (invalid argument). This also=0A=
 occurs with MegaCli so its currently thought this is a firmware bug.=0A=
 =0A=
 Fixes a panic when MFI_DCMD_CFG_FOREIGN_IMPORT is called from user space.=0A=
 =0A=
 Adds hw.mfi.cmd_timeout loader / sysctl tuneable which controls the =
 default=0A=
 timeout used in the mfi driver. This is useful for long running commands=0A=
 such as secure erase.=0A=
 =0A=
 Additional debugging of DCMD commands has also been added which added=0A=
 identifying the DCMD's used by MegaCli to perform the various actions.=0A=
 --- usr.sbin/mfiutil/Makefile.orig	2012-03-03 06:15:13.000000000 +0000=0A=
 +++ usr.sbin/mfiutil/Makefile	2012-09-21 15:52:24.648147593 +0000=0A=
 @@ -2,7 +2,7 @@=0A=
  PROG=3D	mfiutil=0A=
  =0A=
  SRCS=3D	mfiutil.c mfi_cmd.c mfi_config.c mfi_drive.c mfi_evt.c =
 mfi_flash.c \=0A=
 -	mfi_patrol.c mfi_show.c mfi_volume.c=0A=
 +	mfi_patrol.c mfi_show.c mfi_volume.c mfi_foreign.c=0A=
  MAN8=3D	mfiutil.8=0A=
  =0A=
  CFLAGS+=3D -fno-builtin-strftime=0A=
 --- usr.sbin/mfiutil/mfi_cmd.c.orig	2012-03-03 06:15:13.000000000 +0000=0A=
 +++ usr.sbin/mfiutil/mfi_cmd.c	2012-09-24 13:22:53.204020111 +0000=0A=
 @@ -284,7 +284,7 @@=0A=
  	if (statusp !=3D NULL)=0A=
  		*statusp =3D dcmd->header.cmd_status;=0A=
  	else if (dcmd->header.cmd_status !=3D MFI_STAT_OK) {=0A=
 -		warnx("Command failed: %s",=0A=
 +		warnx("Command 0x%08x failed: %s", opcode,=0A=
  		    mfi_status(dcmd->header.cmd_status));=0A=
  		errno =3D EIO;=0A=
  		return (-1);=0A=
 --- usr.sbin/mfiutil/mfi_config.c.orig	2012-03-03 06:15:13.000000000 =
 +0000=0A=
 +++ usr.sbin/mfiutil/mfi_config.c	2012-09-24 16:39:46.856313431 +0000=0A=
 @@ -36,19 +36,13 @@=0A=
  #include <err.h>=0A=
  #include <errno.h>=0A=
  #include <libutil.h>=0A=
 -#ifdef DEBUG=0A=
  #include <stdint.h>=0A=
 -#endif=0A=
  #include <stdio.h>=0A=
  #include <stdlib.h>=0A=
  #include <string.h>=0A=
  #include <unistd.h>=0A=
  #include "mfiutil.h"=0A=
  =0A=
 -#ifdef DEBUG=0A=
 -static void	dump_config(int fd, struct mfi_config_data *config);=0A=
 -#endif=0A=
 -=0A=
  static int	add_spare(int ac, char **av);=0A=
  static int	remove_spare(int ac, char **av);=0A=
  =0A=
 @@ -80,9 +74,17 @@=0A=
          }=0A=
          return (iv);=0A=
  }=0A=
 +=0A=
  int=0A=
  mfi_config_read(int fd, struct mfi_config_data **configp)=0A=
  {=0A=
 +	return mfi_config_read_opcode(fd, MFI_DCMD_CFG_READ, configp, NULL, 0);=0A=
 +}=0A=
 +=0A=
 +int=0A=
 +mfi_config_read_opcode(int fd, uint32_t opcode, struct mfi_config_data =
 **configp,=0A=
 +	uint8_t *mbox, size_t mboxlen)=0A=
 +{=0A=
  	struct mfi_config_data *config;=0A=
  	uint32_t config_size;=0A=
  	int error;=0A=
 @@ -97,8 +99,8 @@=0A=
  	config =3D reallocf(config, config_size);=0A=
  	if (config =3D=3D NULL)=0A=
  		return (-1);=0A=
 -	if (mfi_dcmd_command(fd, MFI_DCMD_CFG_READ, config,=0A=
 -	    config_size, NULL, 0, NULL) < 0) {=0A=
 +	if (mfi_dcmd_command(fd, opcode, config,=0A=
 +	    config_size, mbox, mboxlen, NULL) < 0) {=0A=
  		error =3D errno;=0A=
  		free(config);=0A=
  		errno =3D error;=0A=
 @@ -366,6 +368,13 @@=0A=
  			info->drives =3D NULL;=0A=
  			return (EINVAL);=0A=
  		}=0A=
 +=0A=
 +		if (pinfo->state.ddf.v.pd_type.is_foreign) {=0A=
 +			warnx("Drive %u is foreign", device_id);=0A=
 +			free(info->drives);=0A=
 +			info->drives =3D NULL;=0A=
 +			return (EINVAL);=0A=
 +		}=0A=
  	}=0A=
  =0A=
  	return (0);=0A=
 @@ -804,7 +813,7 @@=0A=
  =0A=
  #ifdef DEBUG=0A=
  	if (dump)=0A=
 -		dump_config(fd, config);=0A=
 +		dump_config(fd, config, NULL);=0A=
  #endif=0A=
  =0A=
  	/* Send the new config to the controller. */=0A=
 @@ -1093,10 +1102,9 @@=0A=
  }=0A=
  MFI_COMMAND(top, remove, remove_spare);=0A=
  =0A=
 -#ifdef DEBUG=0A=
  /* Display raw data about a config. */=0A=
 -static void=0A=
 -dump_config(int fd, struct mfi_config_data *config)=0A=
 +void=0A=
 +dump_config(int fd, struct mfi_config_data *config, const char =
 *msg_prefix)=0A=
  {=0A=
  	struct mfi_array *ar;=0A=
  	struct mfi_ld_config *ld;=0A=
 @@ -1106,9 +1114,12 @@=0A=
  	char *p;=0A=
  	int i, j;=0A=
  =0A=
 +	if (NULL =3D=3D msg_prefix)=0A=
 +		msg_prefix =3D "Configuration (Debug)";=0A=
 +=0A=
  	printf(=0A=
 -	    "mfi%d Configuration (Debug): %d arrays, %d volumes, %d spares\n",=0A=
 -	    mfi_unit, config->array_count, config->log_drv_count,=0A=
 +	    "mfi%d %s: %d arrays, %d volumes, %d spares\n", mfi_unit,=0A=
 +	    msg_prefix, config->array_count, config->log_drv_count,=0A=
  	    config->spares_count);=0A=
  	printf("  array size: %u\n", config->array_size);=0A=
  	printf("  volume size: %u\n", config->log_drv_size);=0A=
 @@ -1186,6 +1197,7 @@=0A=
  	}=0A=
  }=0A=
  =0A=
 +#ifdef DEBUG=0A=
  static int=0A=
  debug_config(int ac, char **av)=0A=
  {=0A=
 @@ -1213,7 +1225,7 @@=0A=
  	}=0A=
  =0A=
  	/* Dump out the configuration. */=0A=
 -	dump_config(fd, config);=0A=
 +	dump_config(fd, config, NULL);=0A=
  	free(config);=0A=
  	close(fd);=0A=
  =0A=
 @@ -1265,7 +1277,7 @@=0A=
  		close(fd);=0A=
  		return (error);=0A=
  	}=0A=
 -	dump_config(fd, config);=0A=
 +	dump_config(fd, config, NULL);=0A=
  	free(config);=0A=
  	close(fd);=0A=
  =0A=
 --- usr.sbin/mfiutil/mfi_show.c.orig	2012-03-03 06:15:13.000000000 +0000=0A=
 +++ usr.sbin/mfiutil/mfi_show.c	2012-09-21 15:53:51.791817529 +0000=0A=
 @@ -39,9 +39,11 @@=0A=
  #include <unistd.h>=0A=
  #include "mfiutil.h"=0A=
  =0A=
 +const char* foreign_state =3D " (FOREIGN)";=0A=
 +=0A=
  MFI_TABLE(top, show);=0A=
  =0A=
 -static void=0A=
 +void=0A=
  format_stripe(char *buf, size_t buflen, uint8_t stripe)=0A=
  {=0A=
  =0A=
 @@ -241,7 +243,7 @@=0A=
  }=0A=
  MFI_COMMAND(show, battery, show_battery);=0A=
  =0A=
 -static void=0A=
 +void=0A=
  print_ld(struct mfi_ld_info *info, int state_len)=0A=
  {=0A=
  	struct mfi_ld_params *params =3D &info->ld_config.params;=0A=
 @@ -262,19 +264,24 @@=0A=
  		    mfi_ldstate(params->state));=0A=
  }=0A=
  =0A=
 -static void=0A=
 +void=0A=
  print_pd(struct mfi_pd_info *info, int state_len)=0A=
  {=0A=
  	const char *s;=0A=
 -	char buf[6];=0A=
 +	char buf[256];=0A=
  =0A=
  	humanize_number(buf, sizeof(buf), info->raw_size * 512, "",=0A=
  	    HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL);=0A=
  	printf("(%6s) ", buf);=0A=
 +	if (info->state.ddf.v.pd_type.is_foreign) {=0A=
 +		sprintf(buf, "%s%s", mfi_pdstate(info->fw_state), foreign_state);=0A=
 +		s =3D buf;=0A=
 +	} else=0A=
 +		s =3D mfi_pdstate(info->fw_state);=0A=
  	if (state_len > 0)=0A=
 -		printf("%-*s", state_len, mfi_pdstate(info->fw_state));=0A=
 +		printf("%-*s", state_len, s);=0A=
  	else=0A=
 -		printf("%s", mfi_pdstate(info->fw_state));=0A=
 +		printf(s);=0A=
  	s =3D mfi_pd_inq_string(info);=0A=
  	if (s !=3D NULL)=0A=
  		printf(" %s", s);=0A=
 @@ -510,6 +517,8 @@=0A=
  			goto error;=0A=
  		}=0A=
  		len =3D strlen(mfi_pdstate(info.fw_state));=0A=
 +		if (info.state.ddf.v.pd_type.is_foreign)=0A=
 +			len +=3D strlen(foreign_state);=0A=
  		if (len > state_len)=0A=
  			state_len =3D len;=0A=
  	}=0A=
 --- usr.sbin/mfiutil/mfiutil.c.orig	2012-03-03 06:15:13.000000000 +0000=0A=
 +++ usr.sbin/mfiutil/mfiutil.c	2012-09-25 12:16:01.912563546 +0000=0A=
 @@ -83,6 +83,12 @@=0A=
  	fprintf(stderr, "    patrol <disable|auto|manual> [interval =
 [start]]\n");=0A=
  	fprintf(stderr, "    start patrol              - start a patrol =
 read\n");=0A=
  	fprintf(stderr, "    stop patrol               - stop a patrol =
 read\n");=0A=
 +	fprintf(stderr, "    foreign scan              - scan for foreign =
 configurations\n");=0A=
 +	fprintf(stderr, "    foreign drives            - list foreign =
 drives\n");=0A=
 +	fprintf(stderr, "    foreign clear [volume]    - clear foreign =
 configurations (default all)\n");=0A=
 +	fprintf(stderr, "    foreign display [volume]  - display foreign =
 configurations (default all)\n");=0A=
 +	fprintf(stderr, "    foreign preview [volume]  - preview foreign =
 configurations (default all)\n");=0A=
 +	fprintf(stderr, "    foreign import [volume]   - import foreign =
 configurations (default all)\n");=0A=
  	fprintf(stderr, "    flash <firmware>\n");=0A=
  #ifdef DEBUG=0A=
  	fprintf(stderr, "    debug                     - debug 'show =
 config'\n");=0A=
 --- usr.sbin/mfiutil/mfiutil.h.orig	2012-03-03 06:15:13.000000000 +0000=0A=
 +++ usr.sbin/mfiutil/mfiutil.h	2012-09-24 16:35:21.816610669 +0000=0A=
 @@ -135,6 +135,8 @@=0A=
  const char *mfi_volume_name(int fd, uint8_t target_id);=0A=
  int	mfi_volume_busy(int fd, uint8_t target_id);=0A=
  int	mfi_config_read(int fd, struct mfi_config_data **configp);=0A=
 +int	mfi_config_read_opcode(int fd, uint32_t opcode,=0A=
 +    struct mfi_config_data **configp, uint8_t *mbox, size_t mboxlen);=0A=
  int	mfi_lookup_drive(int fd, char *drive, uint16_t *device_id);=0A=
  int	mfi_lookup_volume(int fd, const char *name, uint8_t *target_id);=0A=
  int	mfi_dcmd_command(int fd, uint32_t opcode, void *buf, size_t bufsize,=0A=
 @@ -151,5 +153,9 @@=0A=
  const char *mfi_status(u_int status_code);=0A=
  const char *mfi_drive_name(struct mfi_pd_info *pinfo, uint16_t =
 device_id,=0A=
      uint32_t def);=0A=
 +void	format_stripe(char *buf, size_t buflen, uint8_t stripe);=0A=
 +void	print_ld(struct mfi_ld_info *info, int state_len);=0A=
 +void	print_pd(struct mfi_pd_info *info, int state_len);=0A=
 +void	dump_config(int fd, struct mfi_config_data *config, const char* =
 msg_prefix);=0A=
  =0A=
  #endif /* !__MFIUTIL_H__ */=0A=
 --- sys/dev/mfi/mfi_debug.c.orig	2012-03-03 06:15:13.000000000 +0000=0A=
 +++ sys/dev/mfi/mfi_debug.c	2012-09-25 15:07:09.318736816 +0000=0A=
 @@ -54,6 +54,88 @@=0A=
  #include <dev/mfi/mfi_ioctl.h>=0A=
  #include <dev/mfi/mfivar.h>=0A=
  =0A=
 +struct mfi_op_table_entry {=0A=
 +	uint32_t    opcode;=0A=
 +	const char  *desc;=0A=
 +};=0A=
 +=0A=
 +/* Keep in sync with mfi_dcmd_t in mfireg.h */=0A=
 +static struct mfi_op_table_entry mfi_op_codes[] =3D {=0A=
 +	{ MFI_DCMD_CTRL_GETINFO, "MFI_DCMD_CTRL_GETINFO" },=0A=
 +	{ MFI_DCMD_CTRL_MFI_HOST_MEM_ALLOC, "MFI_DCMD_CTRL_MFI_HOST_MEM_ALLOC" =
 },=0A=
 +	{ MFI_DCMD_CTRL_EVENT_GETINFO, "MFI_DCMD_CTRL_EVENT_GETINFO" },=0A=
 +	{ MFI_DCMD_CTRL_EVENT_GET, "MFI_DCMD_CTRL_EVENT_GET" },=0A=
 +	{ MFI_DCMD_CTRL_EVENT_WAIT, "MFI_DCMD_CTRL_EVENT_WAIT" },=0A=
 +	{ MFI_DCMD_CTRL_SHUTDOWN, "MFI_DCMD_CTRL_SHUTDOWN" },=0A=
 +	{ MFI_DCMD_PR_GET_STATUS, "MFI_DCMD_PR_GET_STATUS" },=0A=
 +	{ MFI_DCMD_PR_GET_PROPERTIES, "MFI_DCMD_PR_GET_PROPERTIES" },=0A=
 +	{ MFI_DCMD_PR_SET_PROPERTIES, "MFI_DCMD_PR_SET_PROPERTIES" },=0A=
 +	{ MFI_DCMD_PR_START, "MFI_DCMD_PR_START" },=0A=
 +	{ MFI_DCMD_PR_STOP, "MFI_DCMD_PR_STOP" },=0A=
 +	{ MFI_DCMD_TIME_SECS_GET, "MFI_DCMD_TIME_SECS_GET" },=0A=
 +	{ MFI_DCMD_CTRL_MFC_DEFAULTS_GET, "MFI_DCMD_CTRL_MFC_DEFAULTS_GET" },=0A=
 +	{ MFI_DCMD_CTRL_MFC_DEFAULTS_SET, "MFI_DCMD_CTRL_MFC_DEFAULTS_SET" },=0A=
 +	{ MFI_DCMD_FLASH_FW_OPEN, "MFI_DCMD_FLASH_FW_OPEN" },=0A=
 +	{ MFI_DCMD_FLASH_FW_DOWNLOAD, "MFI_DCMD_FLASH_FW_DOWNLOAD" },=0A=
 +	{ MFI_DCMD_FLASH_FW_FLASH, "MFI_DCMD_FLASH_FW_FLASH" },=0A=
 +	{ MFI_DCMD_FLASH_FW_CLOSE, "MFI_DCMD_FLASH_FW_CLOSE" },=0A=
 +	{ MFI_DCMD_CTRL_FLUSHCACHE, "MFI_DCMD_CTRL_FLUSHCACHE" },=0A=
 +	{ MFI_DCMD_PD_GET_LIST, "MFI_DCMD_PD_GET_LIST" },=0A=
 +	{ MFI_DCMD_PD_LIST_QUERY, "MFI_DCMD_PD_LIST_QUERY" },=0A=
 +	{ MFI_DCMD_PD_GET_INFO, "MFI_DCMD_PD_GET_INFO" },=0A=
 +	{ MFI_DCMD_PD_STATE_SET, "MFI_DCMD_PD_STATE_SET" },=0A=
 +	{ MFI_DCMD_PD_REBUILD_START, "MFI_DCMD_PD_REBUILD_START" },=0A=
 +	{ MFI_DCMD_PD_REBUILD_ABORT, "MFI_DCMD_PD_REBUILD_ABORT" },=0A=
 +	{ MFI_DCMD_PD_CLEAR_START, "MFI_DCMD_PD_CLEAR_START" },=0A=
 +	{ MFI_DCMD_PD_CLEAR_ABORT, "MFI_DCMD_PD_CLEAR_ABORT" },=0A=
 +	{ MFI_DCMD_PD_GET_PROGRESS, "MFI_DCMD_PD_GET_PROGRESS" },=0A=
 +	{ MFI_DCMD_PD_LOCATE_START, "MFI_DCMD_PD_LOCATE_START" },=0A=
 +	{ MFI_DCMD_PD_LOCATE_STOP, "MFI_DCMD_PD_LOCATE_STOP" },=0A=
 +	{ MFI_DCMD_LD_MAP_GET_INFO, "MFI_DCMD_LD_MAP_GET_INFO" },=0A=
 +	{ MFI_DCMD_LD_SYNC, "MFI_DCMD_LD_SYNC" },=0A=
 +	{ MFI_DCMD_LD_GET_LIST, "MFI_DCMD_LD_GET_LIST" },=0A=
 +	{ MFI_DCMD_LD_GET_INFO, "MFI_DCMD_LD_GET_INFO" },=0A=
 +	{ MFI_DCMD_LD_GET_PROP, "MFI_DCMD_LD_GET_PROP" },=0A=
 +	{ MFI_DCMD_LD_SET_PROP, "MFI_DCMD_LD_SET_PROP" },=0A=
 +	{ MFI_DCMD_LD_INIT_START, "MFI_DCMD_LD_INIT_START" },=0A=
 +	{ MFI_DCMD_LD_DELETE, "MFI_DCMD_LD_DELETE" },=0A=
 +	{ MFI_DCMD_CFG_READ, "MFI_DCMD_CFG_READ" },=0A=
 +	{ MFI_DCMD_CFG_ADD, "MFI_DCMD_CFG_ADD" },=0A=
 +	{ MFI_DCMD_CFG_CLEAR, "MFI_DCMD_CFG_CLEAR" },=0A=
 +	{ MFI_DCMD_CFG_MAKE_SPARE, "MFI_DCMD_CFG_MAKE_SPARE" },=0A=
 +	{ MFI_DCMD_CFG_REMOVE_SPARE, "MFI_DCMD_CFG_REMOVE_SPARE" },=0A=
 +	{ MFI_DCMD_CFG_FOREIGN_SCAN, "MFI_DCMD_CFG_FOREIGN_SCAN" },=0A=
 +	{ MFI_DCMD_CFG_FOREIGN_DISPLAY, "MFI_DCMD_CFG_FOREIGN_DISPLAY" },=0A=
 +	{ MFI_DCMD_CFG_FOREIGN_PREVIEW, "MFI_DCMD_CFG_FOREIGN_PREVIEW" },=0A=
 +	{ MFI_DCMD_CFG_FOREIGN_IMPORT, "MFI_DCMD_CFG_FOREIGN_IMPORT" },=0A=
 +	{ MFI_DCMD_CFG_FOREIGN_CLEAR, "MFI_DCMD_CFG_FOREIGN_CLEAR" },=0A=
 +	{ MFI_DCMD_BBU_GET_STATUS, "MFI_DCMD_BBU_GET_STATUS" },=0A=
 +	{ MFI_DCMD_BBU_GET_CAPACITY_INFO, "MFI_DCMD_BBU_GET_CAPACITY_INFO" },=0A=
 +	{ MFI_DCMD_BBU_GET_DESIGN_INFO, "MFI_DCMD_BBU_GET_DESIGN_INFO" },=0A=
 +	{ MFI_DCMD_CLUSTER, "MFI_DCMD_CLUSTER" },=0A=
 +	{ MFI_DCMD_CLUSTER_RESET_ALL, "MFI_DCMD_CLUSTER_RESET_ALL" },=0A=
 +	{ MFI_DCMD_CLUSTER_RESET_LD, "MFI_DCMD_CLUSTER_RESET_LD" }=0A=
 +};=0A=
 +=0A=
 +static void=0A=
 +mfi_dump_bytes(const char *prefix, unsigned char *p, int len)=0A=
 +{=0A=
 +       int i, c =3D 1, j =3D 0;=0A=
 +=0A=
 +       if (prefix)=0A=
 +	       printf("%s: ", prefix);=0A=
 +       printf("[%d]\ndata[%d] ", len, j);=0A=
 +       for (i =3D 0; i < len; ++i) {=0A=
 +	       printf(" %02x", p[i]);=0A=
 +	       c++;=0A=
 +	       if ( 32 =3D=3D c ) {=0A=
 +		       printf("\ndata[%d] ", j++);=0A=
 +		       c =3D 1;=0A=
 +	       }=0A=
 +       }=0A=
 +       printf("\n");=0A=
 +}=0A=
 +=0A=
  static void=0A=
  mfi_print_frame_flags(device_t dev, uint32_t flags)=0A=
  {=0A=
 @@ -118,64 +197,16 @@=0A=
  {=0A=
  	struct mfi_dcmd_frame *dcmd;=0A=
  	struct mfi_frame_header *hdr;=0A=
 -	const char *opcode;=0A=
  =0A=
  	dcmd =3D &cm->cm_frame->dcmd;=0A=
  	hdr =3D &dcmd->header;=0A=
  =0A=
 -	switch (dcmd->opcode) {=0A=
 -	case MFI_DCMD_CTRL_GETINFO:=0A=
 -		opcode =3D "CTRL_GETINFO";=0A=
 -		break;=0A=
 -	case MFI_DCMD_CTRL_FLUSHCACHE:=0A=
 -		opcode =3D "CTRL_FLUSHCACHE";=0A=
 -		break;=0A=
 -	case MFI_DCMD_CTRL_SHUTDOWN:=0A=
 -		opcode =3D "CTRL_SHUTDOWN";=0A=
 -		break;=0A=
 -	case MFI_DCMD_CTRL_EVENT_GETINFO:=0A=
 -		opcode =3D "EVENT_GETINFO";=0A=
 -		break;=0A=
 -	case MFI_DCMD_CTRL_EVENT_GET:=0A=
 -		opcode =3D "EVENT_GET";=0A=
 -		break;=0A=
 -	case MFI_DCMD_CTRL_EVENT_WAIT:=0A=
 -		opcode =3D "EVENT_WAIT";=0A=
 -		break;=0A=
 -	case MFI_DCMD_LD_GET_LIST:=0A=
 -		opcode =3D "LD_GET_LIST";=0A=
 -		break;=0A=
 -	case MFI_DCMD_LD_GET_INFO:=0A=
 -		opcode =3D "LD_GET_INFO";=0A=
 -		break;=0A=
 -	case MFI_DCMD_LD_GET_PROP:=0A=
 -		opcode =3D "LD_GET_PROP";=0A=
 -		break;=0A=
 -	case MFI_DCMD_LD_SET_PROP:=0A=
 -		opcode =3D "LD_SET_PROP";=0A=
 -		break;=0A=
 -	case MFI_DCMD_CLUSTER:=0A=
 -		opcode =3D "CLUSTER";=0A=
 -		break;=0A=
 -	case MFI_DCMD_CLUSTER_RESET_ALL:=0A=
 -		opcode =3D "CLUSTER_RESET_ALL";=0A=
 -		break;=0A=
 -	case MFI_DCMD_CLUSTER_RESET_LD:=0A=
 -		opcode =3D "CLUSTER_RESET_LD";=0A=
 -		break;=0A=
 -	case MFI_DCMD_LD_MAP_GET_INFO:=0A=
 -		opcode =3D "LD_MAP_GET_INFO";=0A=
 -		break;=0A=
 -	default:=0A=
 -		opcode =3D "UNKNOWN";=0A=
 -		break;=0A=
 -	}=0A=
 -=0A=
 -	device_printf(dev, "cmd=3DMFI_CMD_DCMD opcode=3D%s data_len=3D%d\n",=0A=
 -	    opcode, hdr->data_len);=0A=
 +	device_printf(dev, "cmd=3DMFI_CMD_DCMD opcode=3D%s (0x%08x) =
 data_len=3D%d\n",=0A=
 +	    mfi_op_desc(dcmd->opcode), dcmd->opcode, hdr->data_len);=0A=
  	mfi_print_frame_flags(dev, hdr->flags);=0A=
  	mfi_print_sgl(hdr, &dcmd->sgl, hdr->sg_count);=0A=
 -=0A=
 +	if (NULL !=3D dcmd->mbox)=0A=
 +                mfi_dump_bytes("dcmd->mbox", dcmd->mbox, MFI_MBOX_SIZE);=0A=
  }=0A=
  =0A=
  static void=0A=
 @@ -261,4 +295,19 @@=0A=
  	}=0A=
  }=0A=
  =0A=
 +const char *=0A=
 +mfi_op_desc(uint32_t opcode)=0A=
 +{=0A=
 +	int i;=0A=
 +	int num_ops =3D sizeof(mfi_op_codes)/sizeof(mfi_op_codes[0]);=0A=
 +	for (i =3D 0; i < num_ops; i++) {=0A=
 +		if (mfi_op_codes[i].opcode =3D=3D opcode)=0A=
 +			return(mfi_op_codes[i].desc);=0A=
 +		else if (mfi_op_codes[i].opcode > opcode)=0A=
 +			break;=0A=
 +	}=0A=
 +=0A=
 +	return ("UNKNOWN");=0A=
 +}=0A=
 +=0A=
  #endif=0A=
 --- sys/dev/mfi/mfireg.h.orig	2012-03-03 06:15:13.000000000 +0000=0A=
 +++ sys/dev/mfi/mfireg.h	2012-09-25 14:29:58.800392000 +0000=0A=
 @@ -143,27 +143,31 @@=0A=
  	MFI_CMD_STP=0A=
  } mfi_cmd_t;=0A=
  =0A=
 -/* Direct commands */=0A=
 +/*=0A=
 + * Direct commands=0A=
 + *=0A=
 + * NOTE: Keep mfi_op_codes in mfi_debug.c up to date when adding values=0A=
 + */=0A=
  typedef enum {=0A=
  	MFI_DCMD_CTRL_GETINFO =3D		0x01010000,=0A=
 -	MFI_DCMD_CTRL_MFI_HOST_MEM_ALLOC =3D0x0100e100,=0A=
 -	MFI_DCMD_CTRL_MFC_DEFAULTS_GET =3D0x010e0201,=0A=
 -	MFI_DCMD_CTRL_MFC_DEFAULTS_SET =3D0x010e0202,=0A=
 -	MFI_DCMD_CTRL_FLUSHCACHE =3D	0x01101000,=0A=
 -	MFI_DCMD_CTRL_SHUTDOWN =3D	0x01050000,=0A=
  	MFI_DCMD_CTRL_EVENT_GETINFO =3D	0x01040100,=0A=
  	MFI_DCMD_CTRL_EVENT_GET =3D	0x01040300,=0A=
  	MFI_DCMD_CTRL_EVENT_WAIT =3D	0x01040500,=0A=
 +	MFI_DCMD_CTRL_SHUTDOWN =3D	0x01050000,=0A=
  	MFI_DCMD_PR_GET_STATUS =3D	0x01070100,=0A=
  	MFI_DCMD_PR_GET_PROPERTIES =3D	0x01070200,=0A=
  	MFI_DCMD_PR_SET_PROPERTIES =3D	0x01070300,=0A=
  	MFI_DCMD_PR_START =3D		0x01070400,=0A=
  	MFI_DCMD_PR_STOP =3D		0x01070500,=0A=
  	MFI_DCMD_TIME_SECS_GET =3D	0x01080201,=0A=
 +	MFI_DCMD_CTRL_MFI_HOST_MEM_ALLOC =3D0x0100e100,=0A=
 +	MFI_DCMD_CTRL_MFC_DEFAULTS_GET =3D0x010e0201,=0A=
 +	MFI_DCMD_CTRL_MFC_DEFAULTS_SET =3D0x010e0202,=0A=
  	MFI_DCMD_FLASH_FW_OPEN =3D	0x010f0100,=0A=
  	MFI_DCMD_FLASH_FW_DOWNLOAD =3D	0x010f0200,=0A=
  	MFI_DCMD_FLASH_FW_FLASH =3D	0x010f0300,=0A=
  	MFI_DCMD_FLASH_FW_CLOSE =3D	0x010f0400,=0A=
 +	MFI_DCMD_CTRL_FLUSHCACHE =3D	0x01101000,=0A=
  	MFI_DCMD_PD_GET_LIST =3D		0x02010000,=0A=
 	MFI_DCMD_PD_LIST_QUERY =3D	0x02010100,=0A=
  	MFI_DCMD_PD_GET_INFO =3D 		0x02020000,=0A=
 @@ -184,7 +189,11 @@=0A=
 	MFI_DCMD_CFG_CLEAR =3D		0x04030000,=0A=
 	MFI_DCMD_CFG_MAKE_SPARE =3D	0x04040000,=0A=
 	MFI_DCMD_CFG_REMOVE_SPARE =3D	0x04050000,=0A=
 +	MFI_DCMD_CFG_FOREIGN_SCAN =3D	0x04060100,=0A=
 +	MFI_DCMD_CFG_FOREIGN_DISPLAY =3D	0x04060200,=0A=
 +	MFI_DCMD_CFG_FOREIGN_PREVIEW =3D	0x04060300,=0A=
 	MFI_DCMD_CFG_FOREIGN_IMPORT =3D	0x04060400,=0A=
 +	MFI_DCMD_CFG_FOREIGN_CLEAR =3D	0x04060500,=0A=
 	MFI_DCMD_BBU_GET_STATUS =3D	0x05010000,=0A=
 	MFI_DCMD_BBU_GET_CAPACITY_INFO =3D0x05020000,=0A=
 	MFI_DCMD_BBU_GET_DESIGN_INFO =3D	0x05030000,=0A=
 --- sys/dev/mfi/mfivar.h.orig	2012-03-03 06:15:13.000000000 +0000=0A=
 +++ sys/dev/mfi/mfivar.h	2012-09-25 14:50:12.073354183 +0000=0A=
 @@ -387,6 +387,7 @@=0A=
  extern void mfi_print_cmd(struct mfi_command *cm);=0A=
  extern void mfi_dump_cmds(struct mfi_softc *sc);=0A=
  extern void mfi_validate_sg(struct mfi_softc *, struct mfi_command *, =
 const char *, int );=0A=
 +extern const char * mfi_op_desc(uint32_t opcode);=0A=
  #define MFI_PRINT_CMD(cm)	mfi_print_cmd(cm)=0A=
  #define MFI_DUMP_CMDS(sc)	mfi_dump_cmds(sc)=0A=
  #define MFI_VALIDATE_CMD(sc, cm) mfi_validate_sg(sc, cm, __FUNCTION__, =
 __LINE__)=0A=
 --- /dev/null	2012-10-27 22:11:00.000000000 +0000=0A=
 +++ usr.sbin/mfiutil/mfi_foreign.c	2012-10-27 22:15:26.676979633 +0000=0A=
 @@ -0,0 +1,405 @@=0A=
 +/*-=0A=
 + * Copyright (c) 2008, 2009 Yahoo!, Inc.=0A=
 + * All rights reserved.=0A=
 + *=0A=
 + * Redistribution and use in source and binary forms, with or without=0A=
 + * modification, are permitted provided that the following conditions=0A=
 + * are met:=0A=
 + * 1. Redistributions of source code must retain the above copyright=0A=
 + *    notice, this list of conditions and the following disclaimer.=0A=
 + * 2. Redistributions in binary form must reproduce the above copyright=0A=
 + *    notice, this list of conditions and the following disclaimer in =
 the=0A=
 + *    documentation and/or other materials provided with the =
 distribution.=0A=
 + * 3. The names of the authors may not be used to endorse or promote=0A=
 + *    products derived from this software without specific prior written=0A=
 + *    permission.=0A=
 + *=0A=
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' =
 AND=0A=
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE=0A=
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR =
 PURPOSE=0A=
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE =
 LIABLE=0A=
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR =
 CONSEQUENTIAL=0A=
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE =
 GOODS=0A=
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)=0A=
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, =
 STRICT=0A=
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN =
 ANY WAY=0A=
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY =
 OF=0A=
 + * SUCH DAMAGE.=0A=
 + *=0A=
 + * $FreeBSD$=0A=
 + */=0A=
 +=0A=
 +#include <sys/param.h>=0A=
 +#include <err.h>=0A=
 +#include <errno.h>=0A=
 +#include <fcntl.h>=0A=
 +#include <libutil.h>=0A=
 +#include <stdio.h>=0A=
 +#include <stdlib.h>=0A=
 +#include <string.h>=0A=
 +#include <unistd.h>=0A=
 +#include "mfiutil.h"=0A=
 +=0A=
 +MFI_TABLE(top, foreign);=0A=
 +=0A=
 +/* We currently don't know the full details of the following struct */=0A=
 +struct mfi_foreign_scan_cfg {=0A=
 +	char data[24];=0A=
 +};=0A=
 +=0A=
 +struct mfi_foreign_scan_info {=0A=
 +	uint32_t count; /* Number of foreign configs found */=0A=
 +	struct mfi_foreign_scan_cfg cfgs[8];=0A=
 +};=0A=
 +=0A=
 +static int=0A=
 +foreign_drives(int ac, char **av)=0A=
 +{=0A=
 +	struct mfi_pd_info info;=0A=
 +	struct mfi_pd_list *list;=0A=
 +	int error, fd;=0A=
 +	u_int i;=0A=
 +	fd =3D mfi_open(mfi_unit, O_RDONLY);=0A=
 +	if (fd < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("mfi_open");=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	list =3D NULL;=0A=
 +	if (mfi_pd_get_list(fd, &list, NULL) < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("Failed to get drive list");=0A=
 +		goto error;=0A=
 +	}=0A=
 +	/* List the drives. */=0A=
 +	printf("mfi%d Foreign disks:\n", mfi_unit);=0A=
 +	for (i =3D 0; i < list->count; i++) {=0A=
 +		/* Skip non-hard disks. */=0A=
 +		if (list->addr[i].scsi_dev_type !=3D 0)=0A=
 +			continue;=0A=
 +		/* Fetch details for this drive. */=0A=
 +		if (mfi_pd_get_info(fd, list->addr[i].device_id, &info,=0A=
 +		    NULL) < 0) {=0A=
 +			error =3D errno;=0A=
 +			warn("Failed to fetch info for drive %u",=0A=
 +			    list->addr[i].device_id);=0A=
 +			goto error;=0A=
 +		}=0A=
 +=0A=
 +		if (!info.state.ddf.v.pd_type.is_foreign)=0A=
 +			continue;=0A=
 +					=0A=
 +		printf("%s ", mfi_drive_name(&info, list->addr[i].device_id,=0A=
 +		    MFI_DNAME_DEVICE_ID));=0A=
 +		print_pd(&info, -1);=0A=
 +		printf(" %s\n", mfi_drive_name(&info, list->addr[i].device_id,=0A=
 +		    MFI_DNAME_ES));=0A=
 +	}=0A=
 +error:=0A=
 +	if(list)=0A=
 +		free(list);=0A=
 +	close(fd);=0A=
 +	error =3D 0;=0A=
 +	return (0);=0A=
 +}=0A=
 +MFI_COMMAND(foreign, drives, foreign_drives);=0A=
 +=0A=
 +static int=0A=
 +foreign_clear(int ac, char **av)=0A=
 +{=0A=
 +	int ch, error, fd;=0A=
 +=0A=
 +	fd =3D mfi_open(mfi_unit, O_RDWR);=0A=
 +	if (fd < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("mfi_open");=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	printf(=0A=
 +	    "Are you sure you wish to clear ALL foreign configurations"=0A=
 +	    " on mfi%u? [y/N] ", mfi_unit);=0A=
 +=0A=
 +	ch =3D getchar();=0A=
 +	if (ch !=3D 'y' && ch !=3D 'Y') {=0A=
 +		printf("\nAborting\n");=0A=
 +		close(fd);=0A=
 +		return (0);=0A=
 +	}=0A=
 +=0A=
 +	if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_CLEAR, NULL, 0, NULL,=0A=
 +	    0, NULL) < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("Failed to clear foreign configuration");=0A=
 +		close(fd);=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	printf("mfi%d: Foreign configuration cleared\n", mfi_unit);=0A=
 +	close(fd);=0A=
 +	return (0);=0A=
 +}=0A=
 +MFI_COMMAND(foreign, clear, foreign_clear);=0A=
 +=0A=
 +static int=0A=
 +foreign_scan(int ac, char **av)=0A=
 +{=0A=
 +	struct mfi_foreign_scan_info info;=0A=
 +	int error, fd;=0A=
 +=0A=
 +	fd =3D mfi_open(mfi_unit, O_RDONLY);=0A=
 +	if (fd < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("mfi_open");=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_SCAN, &info,=0A=
 +	    sizeof(info), NULL, 0, NULL) < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("Failed to scan foreign configuration");=0A=
 +		close(fd);=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	printf("mfi%d: Found %d foreign configurations\n", mfi_unit,=0A=
 +	       info.count);=0A=
 +	close(fd);=0A=
 +	return (0);=0A=
 +}=0A=
 +MFI_COMMAND(foreign, scan, foreign_scan);=0A=
 +=0A=
 +static int=0A=
 +foreign_show_cfg(int fd, uint32_t opcode, uint8_t cfgidx)=0A=
 +{=0A=
 +	struct mfi_config_data *config;=0A=
 +	char prefix[26];=0A=
 +	int error, i;=0A=
 +	uint8_t mbox[4];=0A=
 +=0A=
 +	bzero(mbox, sizeof(mbox));=0A=
 +	mbox[0] =3D cfgidx;=0A=
 +	if (mfi_config_read_opcode(fd, opcode, &config, mbox, sizeof(mbox))=0A=
 +	    < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("Failed to get foreign config %d", i);=0A=
 +		close(fd);=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	if (opcode =3D=3D MFI_DCMD_CFG_FOREIGN_PREVIEW)=0A=
 +		sprintf(prefix, "Foreign configuration preview %d", cfgidx);=0A=
 +	else=0A=
 +		sprintf(prefix, "Foreign configuration %d", cfgidx);=0A=
 +	/*=0A=
 +	 * MegaCli uses DCMD opcodes: 0x03100200 (which fails) followed by=0A=
 +	 * 0x1a721880 which returns what looks to be drive / volume info=0A=
 +	 * but we have no real information on what these are or what they do=0A=
 +	 * so we're currently relying solely on the config returned above=0A=
 +	 */=0A=
 +	dump_config(fd, config, prefix);=0A=
 +	free(config);=0A=
 +=0A=
 +	return (0);=0A=
 +}=0A=
 +=0A=
 +static int=0A=
 +foreign_display(int ac, char **av)=0A=
 +{=0A=
 +	struct mfi_foreign_scan_info info;=0A=
 +	uint8_t i;=0A=
 +	int error, fd;=0A=
 +=0A=
 +	if (2 < ac) {=0A=
 +		warnx("foreign display: extra arguments");=0A=
 +                return (EINVAL);=0A=
 +	}=0A=
 +=0A=
 +	fd =3D mfi_open(mfi_unit, O_RDONLY);=0A=
 +	if (fd < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("mfi_open");=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_SCAN, &info,=0A=
 +	    sizeof(info), NULL, 0, NULL) < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("Failed to scan foreign configuration");=0A=
 +		close(fd);=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	if (0 =3D=3D info.count) {=0A=
 +		warnx("foreign display: no foreign configs found");=0A=
 +		close(fd);=0A=
 +		return (EINVAL);=0A=
 +	}=0A=
 +=0A=
 +	if (1 =3D=3D ac) {=0A=
 +		for (i =3D 0; i < info.count; i++) {=0A=
 +			error =3D foreign_show_cfg(fd,=0A=
 +				MFI_DCMD_CFG_FOREIGN_DISPLAY, i);=0A=
 +			if(0 !=3D error) {=0A=
 +				close(fd);=0A=
 +				return (error);=0A=
 +			}=0A=
 +			if (i < info.count - 1)=0A=
 +				printf("\n");=0A=
 +		}=0A=
 +	} else if (2 =3D=3D ac) {=0A=
 +		error =3D foreign_show_cfg(fd,=0A=
 +			MFI_DCMD_CFG_FOREIGN_DISPLAY, atoi(av[1]));=0A=
 +		if (0 !=3D error) {=0A=
 +			close(fd);=0A=
 +			return (error);=0A=
 +		}=0A=
 +	}=0A=
 +	=0A=
 +	close(fd);=0A=
 +	return (0);=0A=
 +}=0A=
 +MFI_COMMAND(foreign, display, foreign_display);=0A=
 +=0A=
 +static int=0A=
 +foreign_preview(int ac, char **av)=0A=
 +{=0A=
 +	struct mfi_foreign_scan_info info;=0A=
 +	uint8_t i;=0A=
 +	int error, fd;=0A=
 +=0A=
 +	if (2 < ac) {=0A=
 +		warnx("foreign preview: extra arguments");=0A=
 +                return (EINVAL);=0A=
 +	}=0A=
 +=0A=
 +	fd =3D mfi_open(mfi_unit, O_RDONLY);=0A=
 +	if (fd < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("mfi_open");=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_SCAN, &info,=0A=
 +	    sizeof(info), NULL, 0, NULL) < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("Failed to scan foreign configuration");=0A=
 +		close(fd);=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	if (0 =3D=3D info.count) {=0A=
 +		warnx("foreign preview: no foreign configs found");=0A=
 +		close(fd);=0A=
 +		return (EINVAL);=0A=
 +	}=0A=
 +=0A=
 +	if (1 =3D=3D ac) {=0A=
 +		for (i =3D 0; i < info.count; i++) {=0A=
 +			error =3D foreign_show_cfg(fd,=0A=
 +				MFI_DCMD_CFG_FOREIGN_PREVIEW, i);=0A=
 +			if(0 !=3D error) {=0A=
 +				close(fd);=0A=
 +				return (error);=0A=
 +			}=0A=
 +			if (i < info.count - 1)=0A=
 +				printf("\n");=0A=
 +		}=0A=
 +	} else if (2 =3D=3D ac) {=0A=
 +		error =3D foreign_show_cfg(fd,=0A=
 +			MFI_DCMD_CFG_FOREIGN_PREVIEW, atoi(av[1]));=0A=
 +		if (0 !=3D error) {=0A=
 +			close(fd);=0A=
 +			return (error);=0A=
 +		}=0A=
 +	}=0A=
 +	=0A=
 +	close(fd);=0A=
 +	return (0);=0A=
 +}=0A=
 +MFI_COMMAND(foreign, preview, foreign_preview);=0A=
 +=0A=
 +static int=0A=
 +foreign_import(int ac, char **av)=0A=
 +{=0A=
 +	struct mfi_foreign_scan_info info;=0A=
 +	int ch, error, fd;=0A=
 +	uint8_t cfgidx;=0A=
 +	uint8_t mbox[4];=0A=
 +=0A=
 +	if (2 < ac) {=0A=
 +		warnx("foreign preview: extra arguments");=0A=
 +                return (EINVAL);=0A=
 +	}=0A=
 +=0A=
 +	fd =3D mfi_open(mfi_unit, O_RDWR);=0A=
 +	if (fd < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("mfi_open");=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_SCAN, &info,=0A=
 +	    sizeof(info), NULL, 0, NULL) < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("Failed to scan foreign configuration");=0A=
 +		close(fd);=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	if (0 =3D=3D info.count) {=0A=
 +		warnx("foreign import: no foreign configs found");=0A=
 +		close(fd);=0A=
 +		return (EINVAL);=0A=
 +	}=0A=
 +=0A=
 +	if (1 =3D=3D ac) {=0A=
 +		cfgidx =3D 0xff;=0A=
 +		printf("Are you sure you wish to import ALL foreign "=0A=
 +		       "configurations on mfi%u? [y/N] ", mfi_unit);=0A=
 +	} else {=0A=
 +		/*=0A=
 +		 * While this is docmmented for MegaCli this failed with=0A=
 +		 * exit code 0x03 on the test controller which was a Supermicro=0A=
 +		 * SMC2108 with firmware 12.12.0-0095 which is a LSI 2108 based=0A=
 +		 * controller.=0A=
 +		 */=0A=
 +		cfgidx =3D atoi(av[1]);=0A=
 +		if (cfgidx >=3D info.count) {=0A=
 +			warnx("Invalid foreign config %d specified max is %d",=0A=
 +			      cfgidx, info.count - 1);=0A=
 +			close(fd);=0A=
 +			return (EINVAL);=0A=
 +		}=0A=
 +		printf("Are you sure you wish to import the foreign "=0A=
 +		       "configuration %d on mfi%u? [y/N] ", cfgidx, mfi_unit);=0A=
 +	}=0A=
 +=0A=
 +	ch =3D getchar();=0A=
 +	if (ch !=3D 'y' && ch !=3D 'Y') {=0A=
 +		printf("\nAborting\n");=0A=
 +		close(fd);=0A=
 +		return (0);=0A=
 +	}=0A=
 +=0A=
 +	bzero(mbox, sizeof(mbox));=0A=
 +	mbox[0] =3D cfgidx;=0A=
 +	if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_IMPORT, NULL, 0, mbox,=0A=
 +	    sizeof(mbox), NULL) < 0) {=0A=
 +		error =3D errno;=0A=
 +		warn("Failed to import foreign configuration");=0A=
 +		close(fd);=0A=
 +		return (error);=0A=
 +	}=0A=
 +=0A=
 +	if (1 =3D=3D ac)=0A=
 +		printf("mfi%d: All foreign configurations imported\n",=0A=
 +		       mfi_unit);=0A=
 +	else=0A=
 +		printf("mfi%d: Foreign configuration %d imported\n", mfi_unit,=0A=
 +		       cfgidx);=0A=
 +	close(fd);=0A=
 +	return (0);=0A=
 +}=0A=
 +MFI_COMMAND(foreign, import, foreign_import);=0A=
 --- usr.sbin/mfiutil/mfiutil.8.orig	2012-03-03 06:15:13.000000000 +0000=0A=
 +++ usr.sbin/mfiutil/mfiutil.8	2012-09-26 11:59:05.298961617 +0000=0A=
 @@ -140,6 +140,24 @@=0A=
  .Cm patrol Ar command Op Ar interval Op Ar start=0A=
  .Nm=0A=
  .Op Fl u Ar unit=0A=
 +.Cm foreign scan=0A=
 +.Nm=0A=
 +.Op Fl u Ar unit=0A=
 +.Cm foreign drives=0A=
 +.Nm=0A=
 +.Op Fl u Ar unit=0A=
 +.Cm foreign clear Op Ar config=0A=
 +.Nm=0A=
 +.Op Fl u Ar unit=0A=
 +.Cm foreign display Op Ar config=0A=
 +.Nm=0A=
 +.Op Fl u Ar unit=0A=
 +.Cm foreign preview Op Ar config=0A=
 +.Nm=0A=
 +.Op Fl u Ar unit=0A=
 +.Cm foreign import Op Ar config=0A=
 +.Nm=0A=
 +.Op Fl u Ar unit=0A=
  .Cm flash Ar file=0A=
  .Sh DESCRIPTION=0A=
  The=0A=
 @@ -561,6 +579,37 @@=0A=
  Start a patrol read operation.=0A=
  .It Cm stop patrol=0A=
  Stop a currently running patrol read operation.=0A=
 +.It Cm foreign scan=0A=
 +Scan for foreign configurations and display the number found. The=0A=
 +.Ar config=0A=
 +argument for the commands below takes the form of a number from 0 to =
 the total=0A=
 +configurations found.=0A=
 +.It Cm foreign drives=0A=
 +Scan for drives flagged as foreign and display them.=0A=
 +.It Cm foreign clear Op config=0A=
 +Clear the specifed foreign=0A=
 +.Ar config=0A=
 +or all if no=0A=
 +.Ar config=0A=
 +argument is provided.=0A=
 +.It Cm foreign display Op config=0A=
 +Display the specifed foreign=0A=
 +.Ar config=0A=
 +or all if no=0A=
 +.Ar config=0A=
 +argument is provided.=0A=
 +.It Cm foreign preview Op config=0A=
 +Preview the specifed foreign=0A=
 +.Ar config=0A=
 +after import or all if no=0A=
 +.Ar config=0A=
 +argument is provided.=0A=
 +.It Cm foreign import Op config=0A=
 +Import the specifed foreign=0A=
 +.Ar config=0A=
 +or all if no=0A=
 +.Ar config=0A=
 +argument is provided.=0A=
  .It Cm flash Ar file=0A=
  Updates the flash on the controller with the firmware stored in=0A=
  .Ar file .=0A=
 --- sys/dev/mfi/mfi.c.orig	2012-03-03 06:15:13.000000000 +0000=0A=
 +++ sys/dev/mfi/mfi.c	2012-09-26 01:40:03.283617692 +0000=0A=
 @@ -133,6 +133,11 @@=0A=
  SYSCTL_INT(_hw_mfi, OID_AUTO, max_cmds, CTLFLAG_RD, &mfi_max_cmds,=0A=
  	   0, "Max commands");=0A=
  =0A=
 +static int	mfi_cmd_timeout =3D MFI_CMD_TIMEOUT;=0A=
 +TUNABLE_INT("hw.mfi.cmd_timeout", &mfi_cmd_timeout);=0A=
 +SYSCTL_INT(_hw_mfi, OID_AUTO, cmd_timeout, CTLFLAG_RW, &mfi_cmd_timeout,=0A=
 +	   0, "Command timeout (in seconds)");=0A=
 +=0A=
  /* Management interface */=0A=
  static d_open_t		mfi_open;=0A=
  static d_close_t	mfi_close;=0A=
 @@ -535,7 +540,7 @@=0A=
  =0A=
  	/* Start the timeout watchdog */=0A=
  	callout_init(&sc->mfi_watchdog_callout, CALLOUT_MPSAFE);=0A=
 -	callout_reset(&sc->mfi_watchdog_callout, MFI_CMD_TIMEOUT * hz,=0A=
 +	callout_reset(&sc->mfi_watchdog_callout, mfi_cmd_timeout * hz,=0A=
  	    mfi_timeout, sc);=0A=
  =0A=
  	return (0);=0A=
 @@ -655,6 +661,7 @@=0A=
  	cm->cm_data =3D buf;=0A=
  	cm->cm_private =3D buf;=0A=
  	cm->cm_len =3D bufsize;=0A=
 +	MFI_PRINT_CMD(cm);=0A=
  =0A=
  	*cmp =3D cm;=0A=
  	if ((bufp !=3D NULL) && (*bufp =3D=3D NULL) && (buf !=3D NULL))=0A=
 @@ -1778,6 +1786,7 @@=0A=
  	struct mfi_disk *ld, *ld2;=0A=
  	int error;=0A=
  =0A=
 +	MFI_PRINT_CMD(cm);=0A=
  	mtx_assert(&sc->mfi_io_lock, MA_OWNED);=0A=
  	error =3D 0;=0A=
  	switch (cm->cm_frame->dcmd.opcode) {=0A=
 @@ -1817,6 +1826,7 @@=0A=
  {=0A=
  	struct mfi_disk *ld, *ldn;=0A=
  =0A=
 +	MFI_PRINT_CMD(cm);=0A=
  	switch (cm->cm_frame->dcmd.opcode) {=0A=
  	case MFI_DCMD_LD_DELETE:=0A=
  		TAILQ_FOREACH(ld, &sc->mfi_ld_tqh, ld_link) {=0A=
 @@ -1848,10 +1858,9 @@=0A=
  		}=0A=
  		break;=0A=
  	case MFI_DCMD_CFG_ADD:=0A=
 -		mfi_ldprobe(sc);=0A=
 -		break;=0A=
  	case MFI_DCMD_CFG_FOREIGN_IMPORT:=0A=
 -		mfi_ldprobe(sc);=0A=
 +		if (cm->cm_frame->header.cmd_status =3D=3D MFI_STAT_OK)=0A=
 +			mfi_ldprobe(sc);=0A=
  		break;=0A=
  	}=0A=
  }=0A=
 @@ -2509,7 +2518,7 @@=0A=
  			break;=0A=
  		device_printf(sc->mfi_dev, "Dumping\n\n");=0A=
  		timedout =3D 0;=0A=
 -		deadline =3D time_uptime - MFI_CMD_TIMEOUT;=0A=
 +		deadline =3D time_uptime - mfi_cmd_timeout;=0A=
  		mtx_lock(&sc->mfi_io_lock);=0A=
  		TAILQ_FOREACH(cm, &sc->mfi_busy, cm_link) {=0A=
  			if (cm->cm_timestamp < deadline) {=0A=
 @@ -2540,10 +2549,11 @@=0A=
  	time_t deadline;=0A=
  	int timedout =3D 0;=0A=
  =0A=
 -	deadline =3D time_uptime - MFI_CMD_TIMEOUT;=0A=
 +	deadline =3D time_uptime - mfi_cmd_timeout;=0A=
 	if (sc->adpreset =3D=3D 0) {=0A=
 		if (!mfi_tbolt_reset(sc)) {=0A=
 -			callout_reset(&sc->mfi_watchdog_callout, MFI_CMD_TIMEOUT * hz, =
 mfi_timeout, sc);=0A=
 +			callout_reset(&sc->mfi_watchdog_callout,=0A=
 +			    mfi_cmd_timeout * hz, mfi_timeout, sc);=0A=
 			return;=0A=
 		}=0A=
 	}=0A=
 @@ -2562,7 +2571,7 @@=0A=
  =0A=
  	mtx_unlock(&sc->mfi_io_lock);=0A=
  =0A=
 -	callout_reset(&sc->mfi_watchdog_callout, MFI_CMD_TIMEOUT * hz,=0A=
 +	callout_reset(&sc->mfi_watchdog_callout, mfi_cmd_timeout * hz,=0A=
  	    mfi_timeout, sc);=0A=
  =0A=
  	if (0)=0A=
 
 ------=_NextPart_000_02D4_01CDB829.0CDC8180--
 


More information about the freebsd-bugs mailing list