/*
 * Copyright 1999-2002 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS__MDIO_H
#define	_SYS__MDIO_H

#pragma ident	"@(#)mdio.h	2.8	02/10/18 SMI"

#include <sys/debug.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/int_types.h>
#include <sys/dditypes.h>
#ifdef _KERNEL
#include <sys/lvm/md_mdiox.h>
#else /* !_KERNEL */
#include <mdiox.h>
#endif
#include <sys/ddipropdefs.h>
#include <sys/hwconf.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * driver version number
 */
#define	MD_DVERSION	0x00040003	/* major.minor */
#define	MD_SET_SHIFT	(NBITSMINOR32 - MD_BITSSET)
#define	MD_MAXUNITS	(1 << MD_SET_SHIFT)
#define	MD_UNIT_MASK	(MD_MAXUNITS - 1)

#define	MD_MIN2UNIT(m)	((m) & MD_UNIT_MASK)
#define	MD_MIN2SET(m)	((m) >> MD_SET_SHIFT)
#define	MD_SID(u)	((u)->c.un_self_id)
#define	MD_RECID(u)	((u)->c.un_record_id)
#define	MD_STATUS(u)	((u)->c.un_status)
#define	MD_PARENT(u)	((u)->c.un_parent)
#define	MD_CAPAB(u)	((u)->c.un_capabilities)
#define	MD_UN2SET(u)	MD_MIN2SET(MD_SID(u))
#define	MD_UL2SET(l)	MD_MIN2SET(MAXMIN32 & ((l)->un_dev))

#define	MD_MKMIN(s, u)	((((s) & MD_SETMASK) << MD_SET_SHIFT) | \
			((u) & MD_UNIT_MASK))

#define	HSP_BITSID	31
#define	HSP_SET_SHIFT	(HSP_BITSID - MD_BITSSET)
#define	HSP_SET_MASK	(MD_SETMASK << HSP_SET_SHIFT)
#define	HSP_SET(hspid)	(((hspid) & HSP_SET_MASK) >> HSP_SET_SHIFT)
#define	HSP_ID(hspid)	((hspid) & ~HSP_SET_MASK)
#define	MAKE_HSP_ID(setno, id)  (((setno) << HSP_SET_SHIFT) | (id))

/*
 * for did stat ioctl
 */
#define	MD_FIND_INVDID	0x01
#define	MD_GET_INVDID	0x02

/*
 * for setting the un_revision
 */
#define	MD_32BIT_META_DEV	0
#define	MD_64BIT_META_DEV	1

/*
 * common unit structure
 */
typedef struct mdc_unit {
	u_longlong_t	un_revision;	/* revision # (keep this a longlong) */
	md_types_t	un_type;	/* type of record */
	md_status_t	un_status;	/* status flags */
	int		un_parent_res; /* parent reserve index */
	int		un_child_res;	/* child reserve index */
	minor_t		un_self_id;	/* metadevice unit number */
	mddb_recid_t	un_record_id;	/* db record id */
	uint_t		un_size;	/* db record size for unit structure */
	ushort_t	un_flag;	/* configuration info */
	diskaddr_t	un_total_blocks; /* external # blocks in metadevice */
	diskaddr_t	un_actual_tb;	/* actual # blocks in metadevice */
	uint_t		un_nhead;	/* saved value of # heads */
	uint_t		un_nsect;	/* saved value of # sectors */
	ushort_t	un_rpm;		/* saved value of rpm's */
	ushort_t	un_wr_reinstruct; /* worse case write reinstruct */
	ushort_t	un_rd_reinstruct; /* worse case read reinstruct */
	mddb_recid_t	un_vtoc_id;	/* vtoc db record id */
	md_stackcap_t	un_capabilities; /* subdevice capabilities */
	md_parent_t	un_parent;	/* -1 none, -2 many, positive unit # */
	uint_t		un_user_flags;	/* provided for userland */
} mdc_unit_t;

/*
 * For old 32 bit format use only
 */
typedef struct mdc_unit32_od {
	u_longlong_t	un_revision;
	md_types_t	un_type;
	md_status_t	un_status;
	int		un_parent_res;
	int		un_child_res;
	minor_t		un_self_id;
	mddb_recid_t	un_record_id;
	uint_t		un_size;
	ushort_t	un_flag;
	daddr32_t	un_total_blocks; /* external # blocks in metadevice */
	daddr32_t	un_actual_tb;	/* actual # blocks in metadevice */
	ushort_t	un_nhead;
	ushort_t	un_nsect;
	ushort_t	un_rpm;
	ushort_t	un_wr_reinstruct;
	ushort_t	un_rd_reinstruct;
	mddb_recid_t	un_vtoc_id;
	md_stackcap_t	un_capabilities;
	md_parent_t	un_parent;
	uint_t		un_user_flags;
} mdc_unit32_od_t;

typedef struct md_unit {
	mdc_unit_t	c;		  /* common stuff */
} md_unit_t;

/*
 * miscname stuff
 */
typedef struct md_driver {
	char	md_drivername[MD_MAXDRVNM];
	set_t	md_setno;
} md_driver_t;

#define	MD_DRIVER md_driver_t md_driver;

#define	MD_DRIVERNAMELEN	16
#define	MD_SETDRIVERNAME(to, from, setno) \
	if ((from) != NULL) \
		(void) strcpy((to)->md_driver.md_drivername, (from)); \
	(to)->md_driver.md_setno = (setno);


#define	MD_GETDRIVERNAME(to, from) \
	(void) strcpy((to), (from)->md_driver.md_drivername);

#define	MD_PNTDRIVERNAME(from) \
	((from)->md_driver.md_drivername)

/*
 * ioctl parameter structures
 */

typedef struct md_i_driverinfo {
	MD_DRIVER
	md_error_t	mde;
	minor_t		mnum;
} md_i_driverinfo_t;

typedef struct md_i_getnext {
	MD_DRIVER
	md_error_t	mde;
	minor_or_hsp_t	id;
} md_i_getnext_t;

typedef struct md_i_getnum {
	MD_DRIVER
	md_error_t	mde;
	int		start;
	int		size;
	uint64_t	minors;	/* Pointer to minor #'s */
} md_i_getnum_t;

typedef struct md_i_get {
	MD_DRIVER
	md_error_t	mde;
	minor_or_hsp_t	id;
	int		size;
	uint64_t	mdp;	/* Contains pointer */
} md_i_get_t;

typedef struct md_set_params {
	MD_DRIVER
	md_error_t	mde;
	minor_t		mnum;
	md_types_t	type;
	uint_t		size;
	int		options;
	uint64_t	mdp;	/* Contains pointer */
} md_set_params_t;

typedef struct md_i_reset {
	MD_DRIVER
	md_error_t	mde;
	minor_t		mnum;		/* Unit to clear */
	int		force;
} md_i_reset_t;

/* soft partition reset parameters */
typedef struct md_sp_reset {
	MD_DRIVER
	md_error_t	mde;		/* Error return */
	minor_t		mnum;		/* Unit to clear */
	int		force;		/* Force reset */
	md_parent_t	new_parent;	/* New parent for child component */
} md_sp_reset_t;

/* soft partition status change parameters */
typedef struct md_sp_statusset {
	MD_DRIVER
	md_error_t	mde;		/* Error return */
	int		num_units;	/* Number of units */
	int		new_status;	/* New status */
	int		size;		/* Array size */
	uint64_t	minors;		/* Pointer to array of minor numbers */
} md_sp_statusset_t;

typedef struct md_sp_update_wm {
	MD_DRIVER
	md_error_t	mde;		/* Error return */
	minor_t		mnum;		/* Unit to update */
	uint_t		count;		/* Number of watermarks */
	uint64_t	wmp;		/* Pointer to array of watermarks */
	uint64_t	osp;		/* Pointer to array of offsets */
} md_sp_update_wm_t;

typedef struct md_sp_read_wm {
	MD_DRIVER
	md_error_t	mde;		/* Error return */
	md_dev64_t	rdev;		/* Device from which to read */
	uint64_t	wmp;		/* Pointer to wm buffer */
	xsp_offset_t	offset;		/* Offset of wm */
} md_sp_read_wm_t;

typedef struct md_set_userflags {
	MD_DRIVER
	md_error_t	mde;
	minor_t		mnum;
	uint_t		userflags;
} md_set_userflags_t;

typedef struct md_stripe_params {
	MD_DRIVER
	md_error_t	mde;		/* Error return */
	minor_t		mnum;
	ms_params_t	params;
} md_stripe_params_t;

typedef struct md_raid_params {
	MD_DRIVER
	md_error_t	mde;		/* Error return */
	minor_t		mnum;
	mr_params_t	params;
} md_raid_params_t;

typedef struct md_mirror_params {
	MD_DRIVER
	md_error_t	mde;		/* Error return */
	minor_t		mnum;
	mm_params_t	params;
} md_mirror_params_t;

typedef struct md_grow_params {
	MD_DRIVER
	md_error_t	mde;	/* Error return */
	minor_t		mnum;	/* Unit to grow */
	int		options; /* create a 64 or 32 bit device */
	uint64_t	mdp;	/* Optional - pointer to new unit struct */
	int		size;	/* Optional - size of new unit struct */
	int		nrows;	/* Optional - original number of rows */
	int		npar;	/* Optional - number of parents to lock */
	uint64_t	par;	/* Optional - pointer to parent units */
} md_grow_params_t;

/* if the didstat struct changes you will need to change the following macro */
typedef struct md_i_didstat {
	md_error_t	mde;	/* Error return */
	set_t		setno;	/* which set to use */
	side_t		side;	/* which side to use */
	int		mode;	/* find or get ? */
	int		cnt;	/* return number of invalid devid's found */
	int		maxsz;	/* return max size of invalid device id */
	uint64_t	ctdp;	/* pointer to structure to fill with ctds */
} md_i_didstat_t;

typedef struct mdnm_params {
	md_error_t	mde;		/* Error return */
	char		drvnm[MD_MAXDRVNM];  /* drvnm for get/set/rem nm */
	major_t		major;		/* major #, (alternative) for get nm */
	minor_t		mnum;		/* minor #, for get/set/rem nm */
	uint_t		devname_len;	/* Length of device name, for set nm */
	uint64_t	devname;	/* Address of device name for set/get */
	set_t		setno;		/* Which namespace set to use */
	side_t		side;		/* -1 == current side, >0 specified */
	mdkey_t		key;		/* 0 == alloc one, else use this key */
	mdkey_t		retkey;		/* return key here! */
	ushort_t	devid_size;	/* 0 == ret size, else use this one */
	uint64_t	devid;		/* pointer to devid, supplied by user */
	uint_t		pathname_len;	/* length of pathname */
	uint64_t	pathname;	/* address of pathname for update */
	md_dev64_t	devt;		/* devt for updating namespace */
} mdnm_params_t;

typedef struct md_getdevs_params {
	MD_DRIVER
	md_error_t	mde;
	minor_t		mnum;
	int		cnt;
	uint64_t	devs;	/* Pointer to devs */
} md_getdevs_params_t;


typedef struct md_i_get_tstate {
	minor_or_hsp_t	id;
	uint_t		tstate;		/* Transient state */
	md_error_t	mde;
} md_i_get_tstate_t;

/*
 * Flags to coordinate sending device id between kernel and user space.
 * To get devid from kernel:
 *   User calls ioctl with l_devid_flags set to GETSZ flag to get size of
 *   devid which is returned in the l_devid_sz field if the SZ flag is set.
 *   Then user allocs that size and sends same ioctl with SPACE flag set
 *   and l_devid_sz set to alloc'd size.  Kernel either sets the NOSPACE
 *   flag (if alloc'd space is not big enough) or sets the VALID flag and
 *   fills in the devid.
 *
 * To send devid to kernel:
 *   User alloc's space for devid, fills in devid, sets (SPACE|VALID|SZ) flags
 *   and sets size of devid into l_devid_sz field.
 *
 * If MDDB_DEVID_SPACE is set, MDDB_DEVID_GETSZ is ignored.
 * If no flags are set, devid information is ignored.
 */
#define	MDDB_DEVID_SPACE	0x0001	/* l_devid_sz bytes of space alloc'd */
#define	MDDB_DEVID_VALID	0x0002	/* kernel has filled in devid */
#define	MDDB_DEVID_NOSPACE	0x0004	/* not enough alloc'd space for devid */
#define	MDDB_DEVID_GETSZ	0x0008	/* fill in l_devid_sz with devid size */
#define	MDDB_DEVID_SZ		0x0010	/* l_devid_sz filled in with devid sz */

/*
 * maximum size of allowable bootlist property string - only used to
 * read in and write out boolist property strings to conf files.
 */
#define	MDDB_BOOTLIST_MAX_LEN	MAX_HWC_LINESIZE

/*
 * Percentage of free space left in replica during conversion of non-devid
 * style replica to devid style replica.
 */
#define	MDDB_DEVID_CONV_PERC	5

typedef struct mddb_cfg_loc {
	dev32_t		l_dev;
	daddr32_t	l_blkno;
	int		l_flags;
	char		l_driver[MD_MAXDRVNM];
	minor_t		l_mnum;
	int		l_devid_flags;
	uint64_t	l_devid;	/* pointer to devid */
	int		l_devid_sz;
	char		l_minor_name[MDDB_MINOR_NAME_MAX];
} mddb_cfg_loc_t;

typedef struct mddb_dtag {
	md_timeval32_t	dt_tv;
	int		dt_id;
	set_t		dt_setno;
	char		dt_sn[MDDB_SN_LEN];
	char		dt_hn[MD_MAX_NODENAME_PLUS_1];
} mddb_dtag_t;

typedef struct mddb_dtag_lst {
	struct mddb_dtag_lst	*dtl_nx;
	mddb_dtag_t		dtl_dt;
} mddb_dtag_lst_t;

typedef struct mddb_dtag_get_parm {
	set_t		dtgp_setno;
	mddb_dtag_t	dtgp_dt;
	md_error_t	dtgp_mde;
} mddb_dtag_get_parm_t;

typedef struct mddb_dtag_use_parm {
	int		dtup_id;
	set_t		dtup_setno;
	md_error_t	dtup_mde;
} mddb_dtag_use_parm_t;

typedef struct mddb_accept_parm {
	set_t		accp_setno;
	md_error_t	accp_mde;
} mddb_accept_parm_t;

typedef struct mddb_med_parm {
	set_t		med_setno;
	md_hi_arr_t	med;
	md_error_t	med_mde;		/* error return */
} mddb_med_parm_t;

typedef struct mddb_med_upd_parm {
	set_t		med_setno;
	md_error_t	med_mde;		/* error return */
} mddb_med_upd_parm_t;

#define	MED_TE_NM_LEN	64

typedef struct mddb_med_t_ent {
	char		med_te_nm[MED_TE_NM_LEN];
	md_dev64_t	med_te_dev;		/* fixed size dev_t */
} mddb_med_t_ent_t;

typedef struct mddb_med_t_parm {
	md_error_t		med_tp_mde;		/* error return */
	int			med_tp_nents;		/* number of entries */
	int			med_tp_setup;		/* setup flag */
	mddb_med_t_ent_t	med_tp_ents[1];		/* Var. sized array */
} mddb_med_t_parm_t;

typedef struct mddb_config {
	md_error_t	c_mde;			/* error return */
	int		c_id;			/* used with getnext locator */
	md_splitname	c_devname;		/* contains name or keys */
	int		c_dbcnt;		/* number of dbs */
	int		c_dbmax;		/* maximum number of dbs */
	int		c_flags;
	int		c_dbend;		/* size of database */
	set_t		c_setno;		/* set number of replica */
	side_t		c_sideno;		/* side number of replica */
	md_timeval32_t	c_timestamp;		/* creation of set */
						/* setname */
	char		c_setname[MD_MAX_SETNAME_PLUS_1];
	md_hi_arr_t	c_med;			/* Mediator host information */
	int		c_spare[14];		/* unused must be zero */
	md_dev64_t	c_devt;			/* devt to get/set */
	mddb_cfg_loc_t	c_locator;		/* device specific info */
} mddb_config_t;


#define	c_subcmd	c_spare[0]
/*
 * Subcommands.
 */
#define	MDDB_CONFIG_ABS	1		/* treat c_id as abs index */

typedef	struct mddb_optloc {
	int	recid;	/* really mddb_recid_t */
	int	li[2];
} mddb_optloc_t;

typedef struct md_gs_stat_parm {
	set_t		gs_setno;
	uint_t		gs_status;
	md_error_t	gs_mde;
} md_gs_stat_parm_t;

typedef struct {
	int	setno;
	int	owns_set;
} mddb_ownset_t;

typedef enum md_rename_operation_t {
	MDRNOP_UNK = 0, MDRNOP_RENAME, MDRNOP_EXCHANGE
} md_renop_t;

typedef struct md_rename {
	md_error_t	mde;
	md_renop_t	op;
	int		revision;
	uint_t		flags;
	struct {
		minor_t	mnum;
		key_t	key;
	} from, to;
} md_rename_t;

typedef struct md_regen_param {
	MD_DRIVER
	md_error_t	mde;
	minor_t		mnum;   /* Unit to regenerate parity for */
} md_regen_param_t;

/* Base ioctl's defined here */
#define	MDIOC		('V' << 8)
#define	ISMDIOC(c)	(((c) >> 8) == 'V')

#define	MD_IOCSET	(MDIOC|0)	/* set config    (metainit) */
#define	MD_IOCRESET	(MDIOC|1)	/* reset config  (metaclear) */
#define	MD_IOCGET	(MDIOC|2)	/* get config    (metastat) */
#define	MD_IOCGROW	(MDIOC|3)	/* grow config   (dyn concat) */
#define	MD_IOCCHANGE	(MDIOC|4)	/* change config (metaparam) */
#define	MD_IOCSET_NM	(MDIOC|5)	/* set device name */
#define	MD_IOCGET_NM	(MDIOC|6)	/* get device name */
#define	MD_IOCREM_NM	(MDIOC|7)	/* remove device name */
#define	MD_IOCGET_DRVNM	(MDIOC|8)	/* get driver name */
#define	MD_IOCGET_NEXT	(MDIOC|9)	/* get next unit id */
#define	MD_IOCGET_DEVS	(MDIOC|10)	/* get device list */
#define	MD_DB_NEWDEV	(MDIOC|11)	/* add a db replica */
#define	MD_DB_USEDEV	(MDIOC|12)	/* patch in a db location */
#define	MD_DB_GETDEV	(MDIOC|13)	/* get a db replica */
#define	MD_DB_DELDEV	(MDIOC|14)	/* remove a db replica */
#define	MD_DB_ENDDEV	(MDIOC|15)	/* get db replica and size */
#define	MD_DB_GETDRVNM	(MDIOC|16)	/* get db replica driver name */
#define	MD_HALT		(MDIOC|17)	/* halt driver   (metahalt) */
#define	MD_GRAB_SET	(MDIOC|18)
#define	MD_RELEASE_SET	(MDIOC|20)	/* release a set */
#define	MD_IOCSETSYNC	(MDIOC|21)
#define	MD_IOCGETSYNC	(MDIOC|22)
#define	MD_IOCOFFLINE	(MDIOC|23)
#define	MD_IOCONLINE	(MDIOC|24)
#define	MD_IOCATTACH	(MDIOC|25)
#define	MD_IOCDETACH	(MDIOC|26)
#define	MD_IOCREPLACE	(MDIOC|27)
#define	MD_DB_USERREQ	(MDIOC|28)
#define	MD_DB_GETOPTLOC	(MDIOC|29)	/* get locators for opt resync rec. */
#define	MD_DB_OWNSET	(MDIOC|30)	/* Does caller own the set */
#define	MD_IOCGETNSET	(MDIOC|31)	/* Get the config'd number sets */
#define	MD_IOCNXTKEY_NM	(MDIOC|32)	/* get next key from namespace */
#define	MD_DB_NEWSIDE	(MDIOC|33)	/* add another side to the db replica */
#define	MD_DB_DELSIDE	(MDIOC|34)	/* delete a side from the db replica */
#define	MD_IOCGVERSION	(MDIOC|35)	/* get the driver version */
#define	MD_IOCSET_FLAGS	(MDIOC|36)	/* set the userflags of a metadevice */
#define	MD_IOCGETNUNITS	(MDIOC|37)	/* Get the config'd number units */
#define	MD_IOCNOTIFY	(MDIOC|38)	/* notification */
#define	MD_IOCRENAME	(MDIOC|39)	/* (Ex)Change/Rename unit identities */
#define	MD_IOCISOPEN	(MDIOC|40)	/* Is metadevice open? */
#define	MD_IOCSETREGEN	(MDIOC|41)	/* regen ioctl for raid */
#define	MD_MED_GET_LST	(MDIOC|42)	/* Get the mediator list */
#define	MD_MED_SET_LST	(MDIOC|43)	/* Set the mediator list */
#define	MD_MED_UPD_MED	(MDIOC|44)	/* Have the kernel push mediator data */
#define	MD_MED_GET_NMED	(MDIOC|45)	/* Get the max number of mediators */
#define	MD_MED_GET_TLEN	(MDIOC|46)	/* Get the mediator transport tbl len */
#define	MD_MED_GET_T	(MDIOC|47)	/* Get the mediator transport tbl */
#define	MD_MED_SET_T	(MDIOC|48)	/* Set the mediator transport tbl */
#define	MD_MED_GET_TAG	(MDIOC|49)	/* Get the list of data tags */
#define	MD_MED_USE_TAG	(MDIOC|50)	/* Use one of the data tags */
#define	MD_MED_ACCEPT	(MDIOC|51)	/* Accept 1/2 n 1/2 */
#define	MD_GET_SETSTAT	(MDIOC|52)	/* Get the s_status for a set */
#define	MD_SET_SETSTAT	(MDIOC|53)	/* Set the s_status for a set */
#define	MD_IOCPROBE_DEV (MDIOC|54)	/* Force pseudo opens for metadevices */
#define	MD_IOCGET_DID	(MDIOC|55)	/* Get device id */
#define	MD_IOCUPD_NM	(MDIOC|56)	/* Update namespace */
#define	MD_DB_SETDID	(MDIOC|57)	/* Set device id */
#define	MD_IOCUPD_LOCNM	(MDIOC|58)	/* update locator namespace */
#define	MD_SETNMDID	(MDIOC|59)	/* update namespace devid */
#define	MD_IOCDID_STAT	(MDIOC|60)	/* get invalid device id's */
#define	MD_UPGRADE_STAT	(MDIOC|61)	/* get upgrade status information */
#define	MD_IOCGET_NUM	(MDIOC|62)	/* get number of devs and devs */
#define	MD_IOCGET_TSTATE (MDIOC|63)	/* get ui_tstate for metastat */
#define	MDIOC_MISC	(MDIOC|128)	/* misc module base */

#define	NODBNEEDED(c)	((c) == MD_IOCNOTIFY)

typedef struct md_resync_ioctl {
	MD_DRIVER
	md_error_t	mde;
	minor_t		ri_mnum;	    /* mirror to sync */
	diskaddr_t	ri_copysize;	    /* The size of the copy buffer */
	int		ri_zerofill;	    /* Zerofill on lec read error */
	int		ri_percent_done;    /* percent done current phase */
	int		ri_percent_dirty;
	md_riflags_t	ri_flags;
} md_resync_ioctl_t;

typedef struct md_rrsize {
	MD_DRIVER
	md_error_t	mde;		/* error return */
	minor_t		mnum;		/* unit # to get */
	ulong_t		rr_num;		/* Number of resync regions */
	ulong_t		rr_blksize;	/* Blocksize of regions */
} md_rrsize_t;

typedef	enum replace_cmd {
	REPLACE_COMP, ENABLE_COMP, FORCE_REPLACE_COMP, FORCE_ENABLE_COMP
} replace_cmd_t;

typedef struct replace_params {
	MD_DRIVER
	md_error_t	mde;
	replace_cmd_t	cmd;		/* what to do */
	minor_t		mnum;		/* mirror to act upon */
	md_dev64_t	old_dev;	/* enable/replace use this */
	md_dev64_t	new_dev;	/* replace only uses this */
	mdkey_t		new_key;	/* replace only uses this */
	diskaddr_t	start_blk;	/* start block of new device */
	int		has_label;	/* has label flag of new device */
	diskaddr_t	number_blks;	/* # of blocks of new device */
	int		no_resync_raid; /* if cluster replace we don't */
					/*    want to resync */
} replace_params_t;

typedef struct md_i_off_on {
	MD_DRIVER
	md_error_t	mde;
	minor_t		mnum;
	md_dev64_t	submirror;
	int		force_offline;
} md_i_off_on_t;

typedef struct md_att_struct {
	MD_DRIVER
	md_error_t	mde;		/* Normal error */
	minor_t		mnum;
	mdkey_t		key;		/* namespace key of sm */
	md_dev64_t	submirror;	/* The device  to attach */
} md_att_struct_t;

typedef struct md_detach_params {
	MD_DRIVER
	md_error_t	mde;
	minor_t		mnum;		/* mirror to act upon */
	md_dev64_t	submirror;
	int		force_detach;
} md_detach_params_t;

/*
 * Structure for accessing the DB from user land.
 */
typedef struct mddb_userreq {
	md_error_t		ur_mde;
	mddb_usercmd_t		ur_cmd;
	set_t			ur_setno;
	mddb_type_t		ur_type;
	uint_t			ur_type2;
	mddb_recid_t		ur_recid;
	mddb_recstatus_t	ur_recstat;
	int			ur_size;
	uint64_t		ur_data;	/* Pointer to user data */
} mddb_userreq_t;

/*
 * Ioctl structure for MD_IOCISOPEN
 */
typedef struct md_isopen {
	md_error_t	mde;
	md_dev64_t	dev;
	int		isopen;
} md_isopen_t;

/*
 * Ioctl structure for MD_IOCPROBE_DEV
 */

#define	TESTNAME_LEN 32

#define	PROBE_SEMA(p)	p->probe_sema
#define	PROBE_MX(p)	p->probe_mx

/*
 * To categorize user/kernel structures md_probedev is split into two,
 * one used by user and the other by kernel, thereby hiding the semaphore
 * /mutex pointer members from user, which should be the appropriate one.
 */

typedef struct md_probedev {
	MD_DRIVER
	md_error_t	mde;		/* return error status */
	int		nmdevs;		/* number of metadevices */
	char		test_name[TESTNAME_LEN];
	uint64_t	mnum_list;	/* pointer to array of minor numbers */
} md_probedev_t;

typedef struct md_probedev_impl {
	ksema_t		*probe_sema;
	kmutex_t	*probe_mx;
	md_probedev_t	probe;
} md_probedev_impl_t;



/*
 * Per set flags, stored in md_set[n].s_status
 */
#define	MD_SET_HALTED		0x0001	/* Set is shut down */
#define	MD_SET_SNARFED		0x0002	/* incores built for set db recs */
#define	MD_SET_SNARFING		0x0004	/* incores being built for set */
#define	MD_SET_STALE		0x0008	/* set database not correct */
#define	MD_SET_NM_LOADED	0x0010	/* set namespace is loaded */
#define	MD_SET_TAGDATA		0x0020	/* tagged data detected */
#define	MD_SET_ACCOK		0x0040	/* Accept data is possible */
#define	MD_SET_TOOFEW		0x0080	/* not enough replicas */
#define	MD_SET_USETAG		0x0100	/* A tag is selected, use it */
#define	MD_SET_ACCEPT		0x0200	/* User has chosen accept 50/50 mode */
#define	MD_SET_OWNERSHIP	0x0400	/* Set is owned */
#define	MD_SET_BADTAG		0x0800	/* DT is not valid */
#define	MD_SET_CLRTAG		0x1000	/* Clear the tags */
#define	MD_SET_KEEPTAG		0x2000	/* Keep the tag */
#define	MD_SET_PUSHLB		0x4000	/* Indicate a LB push is needed */

/*
 * See meta_prbits() in SUNWmd/lib/libmeta/meta_print.c for a description of
 * the way this is used
 */
#define	MD_SET_STAT_BITS "\020\001HALTED\002SNARFED\003SNARFING\004STALE" \
			    "\005NM_LOADED\006TAGDATA\007ACCOK\010TOOFEW" \
			    "\011USETAG\012ACCEPT\013OWNERSHIP\014BADTAG" \
			    "\015CLRTAG\016KEEPTAG\017PUSHLB"


#ifdef	__cplusplus
}
#endif

#endif	/* _SYS__MDIO_H */
