svn commit: r249658 - in head: bin/chio sys/cam/scsi sys/sys

Warner Losh imp at bsdimp.com
Sat Apr 20 11:45:49 UTC 2013


Hey Ken,

this change doesn't compile for me.  See below

Warner

On Apr 19, 2013, at 2:03 PM, Kenneth D. Merry wrote:

> Author: ken
> Date: Fri Apr 19 20:03:51 2013
> New Revision: 249658
> URL: http://svnweb.freebsd.org/changeset/base/249658
> 
> Log:
>  Update chio(1) and ch(4) to support reporting element designators.
> 
>  This allows mapping a tape drive in a changer (as reported by
>  'chio status') to a sa(4) driver instance by comparing the
>  serial numbers.
> 
>  The designators can be ASCII (which is printed out directly), binary
>  (which is printed in hex format) or UTF-8, which is printed in either
>  native UTF-8 format if the terminal can support it, or in %XX notation
>  for non-ASCII characters.  Thanks to Hiroki Sato <hrs@> for the
>  explaining UTF-8 printing and example UTF-8 printing code.
> 
>  chio.h:		Modify the changer_element_status structure to add new
>  		fields and definitions from the SMC3r16 spec.
> 
>  		Rename the original CHIOGSTATUS ioctl to OCHIOGTATUS and
>  		define a new CHIOGSTATUS ioctl.
> 
>  		Clean up some tab/space issues.
> 
>  chio.c: 	For the 'status' subcommand, print the designator field
>  		if it is supplied by a device.
> 
>  scsi_ch.h:	Add new flags for DVCID and CURDATA to the READ
>  		ELEMENT STATUS command structure.
> 
>  		Add a read_element_status_device_id structure
>  		for the data fields in the new standard. Add new
>  		unions, dt_or_obsolete and voltage_devid, to hold
>  		and address data from either SCSI-2 or newer devices.
> 
>  scsi_ch.c:	Implement support for fetching device IDs with READ
>  		ELEMENT STATUS data.
> 
>  		Add new arguments to scsi_read_element_status() to
>  		allow the user to request the DVCID and CURDATA bits.
>  		This isn't compiled into libcam (it's only an internal
>  		kernel interface), so we don't need any special
>  		handling for the API change.
> 
>  		If the user issues the new CHIOGSTATUS ioctl, copy all of
>  		the available element status data out.  If he issues the
>  		OCHIOGSTATUS ioctl, we don't copy the new fields in the
>  		structure.
> 
>  		Fix a bug in chopen() that would result in the peripheral
>  		never getting unheld if chgetparams() failed.
> 
>  Sponsored by:	Spectra Logic
>  Submitted by:	Po-Li Soong
>  MFC After:	1 week
> 
> Modified:
>  head/bin/chio/chio.c
>  head/sys/cam/scsi/scsi_ch.c
>  head/sys/cam/scsi/scsi_ch.h
>  head/sys/sys/chio.h
> 
> Modified: head/bin/chio/chio.c
> ==============================================================================
> --- head/bin/chio/chio.c	Fri Apr 19 19:45:00 2013	(r249657)
> +++ head/bin/chio/chio.c	Fri Apr 19 20:03:51 2013	(r249658)
> @@ -54,6 +54,8 @@ __FBSDID("$FreeBSD$");
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
> +#include <langinfo.h>
> +#include <locale.h>
> 
> #include "defs.h"
> #include "pathnames.h"
> @@ -81,6 +83,7 @@ static	int do_status(const char *, int, 
> static	int do_ielem(const char *, int, char **);
> static	int do_return(const char *, int, char **);
> static	int do_voltag(const char *, int, char **);
> +static	void print_designator(const char *, u_int8_t, u_int8_t);
> 
> #ifndef CHET_VT
> #define	CHET_VT		10			/* Completely Arbitrary */
> @@ -723,6 +726,10 @@ do_status(const char *cname, int argc, c
> 					putchar('?');
> 				putchar('>');
> 			}
> +			if (ces->ces_designator_length > 0)
> +				print_designator(ces->ces_designator,
> +						 ces->ces_code_set,
> +						 ces->ces_designator_length);
> 			putchar('\n');
> 		}
> 
> @@ -1177,3 +1184,66 @@ usage(void)
> 		"arg1 arg2 [arg3 [...]]\n", getprogname());
> 	exit(1);
> }
> +
> +#define	UTF8CODESET	"UTF-8"
> +
> +static void
> +print_designator(const char *designator, u_int8_t code_set,
> +    u_int8_t designator_length)
> +{
> +	printf(" serial number: <");
> +	switch (code_set) {
> +	case CES_CODE_SET_ASCII: {
> +		/*
> +		 * The driver insures that the string is always NUL terminated.
> +		 */
> +		printf("%s", designator);
> +		break;
> +	}
> +	case CES_CODE_SET_UTF_8: {
> +		char *cs_native;
> +
> +		setlocale(LC_ALL, "");
> +		cs_native = nl_langinfo(CODESET);
> +
> +		/* See if we can natively print UTF-8 */
> +		if (strcmp(cs_native, UTF8CODESET) == 0)
> +			cs_native = NULL;
> +
> +		if (cs_native == NULL) {
> +			/* We can natively print UTF-8, so use printf. */
> +			printf("%s", designator);
> +		} else {
> +			int i;
> +
> +			/*
> +			 * We can't natively print UTF-8.  We should
> +			 * convert it to the terminal's codeset, but that
> +			 * requires iconv(3) and FreeBSD doesn't have
> +			 * iconv(3) in the base system yet.  So we use %XX
> +			 * notation for non US-ASCII characters instead.
> +			 */
> +			for (i = 0; i < designator_length &&
> +			    designator[i] != '\0'; i++) {
> +				if ((unsigned char)designator[i] < 0x80)
> +					printf("%c", designator[i]);
> +				else
> +					printf("%%%02x",
> +					    (unsigned char)designator[i]);
> +			}
> +		}
> +		break;
> +	}
> +	case CES_CODE_SET_BINARY: {
> +		int i;
> +
> +		for (i = 0; i < designator_length; i++)
> +			printf("%02X%s", designator[i],
> +			    (i == designator_length - 1) ? "" : " ");
> +		break;
> +	}
> +	default:
> +		break;
> +	}
> +	printf(">");
> +}
> 
> Modified: head/sys/cam/scsi/scsi_ch.c
> ==============================================================================
> --- head/sys/cam/scsi/scsi_ch.c	Fri Apr 19 19:45:00 2013	(r249657)
> +++ head/sys/cam/scsi/scsi_ch.c	Fri Apr 19 20:03:51 2013	(r249658)
> @@ -194,12 +194,14 @@ static	int		chexchange(struct cam_periph
> static	int		chposition(struct cam_periph *periph,
> 				   struct changer_position *cp);
> static	int		chgetelemstatus(struct cam_periph *periph,
> +				int scsi_version, u_long cmd,
> 				struct changer_element_status_request *csr);
> static	int		chsetvoltag(struct cam_periph *periph,
> 				    struct changer_set_voltag_request *csvr);
> static	int		chielem(struct cam_periph *periph, 
> 				unsigned int timeout);
> static	int		chgetparams(struct cam_periph *periph);
> +static	int		chscsiversion(struct cam_periph *periph);
> 
> static struct periph_driver chdriver =
> {
> @@ -474,6 +476,7 @@ chopen(struct cdev *dev, int flags, int 
> 	 * Load information about this changer device into the softc.
> 	 */
> 	if ((error = chgetparams(periph)) != 0) {
> +		cam_periph_unhold(periph);
> 		cam_periph_release_locked(periph);
> 		cam_periph_unlock(periph);
> 		return(error);
> @@ -772,6 +775,7 @@ chioctl(struct cdev *dev, u_long cmd, ca
> 	switch (cmd) {
> 	case CHIOGPICKER:
> 	case CHIOGPARAMS:
> +	case OCHIOGSTATUS:
> 	case CHIOGSTATUS:
> 		break;
> 
> @@ -824,10 +828,26 @@ chioctl(struct cdev *dev, u_long cmd, ca
> 		error = chielem(periph, *(unsigned int *)addr);
> 		break;
> 
> +	case OCHIOGSTATUS:
> +	{
> +		error = chgetelemstatus(periph, SCSI_REV_2, cmd,
> +		    (struct changer_element_status_request *)addr);
> +		break;
> +	}
> +
> 	case CHIOGSTATUS:
> 	{
> -		error = chgetelemstatus(periph,
> -			       (struct changer_element_status_request *) addr);
> +		int scsi_version;
> +
> +		scsi_version = chscsiversion(periph);
> +		if (scsi_version >= SCSI_REV_0) {
> +			error = chgetelemstatus(periph, scsi_version, cmd,
> +			    (struct changer_element_status_request *)addr);
> +	  	}
> +		else { /* unable to determine the SCSI version */
> +			cam_periph_unlock(periph);
> +			return (ENXIO);
> +		}
> 		break;
> 	}
> 
> @@ -1034,18 +1054,20 @@ copy_voltag(struct changer_voltag *uvolt
> }
> 
> /*
> - * Copy an an element status descriptor to a user-mode
> + * Copy an element status descriptor to a user-mode
>  * changer_element_status structure.
>  */
> -
> -static	void
> +static void
> copy_element_status(struct ch_softc *softc,
> 		    u_int16_t flags,
> 		    struct read_element_status_descriptor *desc,
> -		    struct changer_element_status *ces)
> +		    struct changer_element_status *ces,
> +		    int scsi_version)
> {
> 	u_int16_t eaddr = scsi_2btoul(desc->eaddr);
> 	u_int16_t et;
> +	struct volume_tag *pvol_tag = NULL, *avol_tag = NULL;
> +	struct read_element_status_device_id *devid = NULL;
> 
> 	ces->ces_int_addr = eaddr;
> 	/* set up logical address in element status */
> @@ -1076,7 +1098,7 @@ copy_element_status(struct ch_softc *sof
> 			if ((softc->sc_firsts[et] <= eaddr)
> 			    && ((softc->sc_firsts[et] + softc->sc_counts[et])
> 				> eaddr)) {
> -				ces->ces_source_addr = 
> +				ces->ces_source_addr =
> 					eaddr - softc->sc_firsts[et];
> 				ces->ces_source_type = et;
> 				ces->ces_flags |= CES_SOURCE_VALID;
> @@ -1089,27 +1111,92 @@ copy_element_status(struct ch_softc *sof
> 			       "address %ud to a valid element type\n",
> 			       eaddr);
> 	}
> -			
> 
> +	/*
> +	 * pvoltag and avoltag are common between SCSI-2 and later versions
> +	 */
> 	if (flags & READ_ELEMENT_STATUS_PVOLTAG)
> -		copy_voltag(&(ces->ces_pvoltag), &(desc->pvoltag));
> +		pvol_tag = &desc->voltag_devid.pvoltag;
> 	if (flags & READ_ELEMENT_STATUS_AVOLTAG)
> -		copy_voltag(&(ces->ces_avoltag), &(desc->avoltag));
> -
> -	if (desc->dt_scsi_flags & READ_ELEMENT_STATUS_DT_IDVALID) {
> -		ces->ces_flags |= CES_SCSIID_VALID;
> -		ces->ces_scsi_id = desc->dt_scsi_addr;
> -	}
> +		avol_tag = (flags & READ_ELEMENT_STATUS_PVOLTAG) ?
> +		    &desc->voltag_devid.voltag[1] :&desc->voltag_devid.pvoltag;
> +	/*
> +	 * For SCSI-3 and later, element status can carry designator and
> +	 * other information.
> +	 */
> +	if (scsi_version >= SCSI_REV_SPC) {
> +		if ((flags & READ_ELEMENT_STATUS_PVOLTAG) ^
> +		    (flags & READ_ELEMENT_STATUS_AVOLTAG))
> +			devid = &desc->voltag_devid.pvol_and_devid.devid;
> +		else if (!(flags & READ_ELEMENT_STATUS_PVOLTAG) &&
> +			 !(flags & READ_ELEMENT_STATUS_AVOLTAG))
> +			devid = &desc->voltag_devid.devid;
> +		else /* Have both PVOLTAG and AVOLTAG */
> +			devid = &desc->voltag_devid.vol_tags_and_devid.devid;
> +	}
> +
> +	if (pvol_tag)
> +		copy_voltag(&(ces->ces_pvoltag), pvol_tag);
> +	if (avol_tag)
> +		copy_voltag(&(ces->ces_pvoltag), avol_tag);
> +	if (devid != NULL) {
> +		if (devid->designator_length > 0) {
> +			bcopy((void *)devid->designator,
> +			      (void *)ces->ces_designator,
> +			      devid->designator_length);
> +			ces->ces_designator_length = devid->designator_length;
> +			/*
> +			 * Make sure we are always NUL terminated.  The
> +			 * buffer should be sized for the maximum
> +			 * designator length plus 1, but this will make sure
> +			 * there is always a NUL at the end.  This won't
> +			 * matter for the binary code set, since the user
> +			 * will only pay attention to the length field.
> +			 */
> +			ces->ces_designator[
> +			    MIN(sizeof(ces->ces_designator) - 1,
> +			    devid->designator_length)]= '\0';

compiler complains here that this comparison is always false due to data ranges. I hacked it in my copy by always using devid->designator_length, but I know that's a lame fix. Can you look into it?

Also, just got tinderbox mail.

Warner

> +		}
> +		if (devid->piv_assoc_designator_type &
> +		    READ_ELEMENT_STATUS_PIV_SET) {
> +			ces->ces_flags |= CES_PIV;
> +			ces->ces_protocol_id =
> +			    READ_ELEMENT_STATUS_PROTOCOL_ID(
> +			    devid->prot_code_set);
> +		}
> +		ces->ces_code_set =
> +		    READ_ELEMENT_STATUS_CODE_SET(devid->prot_code_set);
> +		ces->ces_assoc = READ_ELEMENT_STATUS_ASSOCIATION(
> +		    devid->piv_assoc_designator_type);
> +		ces->ces_designator_type = READ_ELEMENT_STATUS_DESIGNATOR_TYPE(
> +		    devid->piv_assoc_designator_type);
> +	} else if (scsi_version > SCSI_REV_2) {
> +		/* SCSI-SPC and No devid, no designator */
> +		ces->ces_designator_length = 0;
> +		ces->ces_designator[0] = '\0';
> +		ces->ces_protocol_id = CES_PROTOCOL_ID_FCP_4;
> +	}
> +
> +	if (scsi_version <= SCSI_REV_2) {
> +		if (desc->dt_or_obsolete.scsi_2.dt_scsi_flags &
> +		    READ_ELEMENT_STATUS_DT_IDVALID) {
> +			ces->ces_flags |= CES_SCSIID_VALID;
> +			ces->ces_scsi_id =
> +			    desc->dt_or_obsolete.scsi_2.dt_scsi_addr;
> +		}
> 
> -	if (desc->dt_scsi_addr & READ_ELEMENT_STATUS_DT_LUVALID) {
> -		ces->ces_flags |= CES_LUN_VALID;
> -		ces->ces_scsi_lun = 
> -			desc->dt_scsi_flags & READ_ELEMENT_STATUS_DT_LUNMASK;
> +		if (desc->dt_or_obsolete.scsi_2.dt_scsi_addr &
> +		    READ_ELEMENT_STATUS_DT_LUVALID) {
> +			ces->ces_flags |= CES_LUN_VALID;
> +			ces->ces_scsi_lun =
> +			    desc->dt_or_obsolete.scsi_2.dt_scsi_flags &
> +			    READ_ELEMENT_STATUS_DT_LUNMASK;
> +		}
> 	}
> }
> 
> static int
> -chgetelemstatus(struct cam_periph *periph, 
> +chgetelemstatus(struct cam_periph *periph, int scsi_version, u_long cmd,
> 		struct changer_element_status_request *cesr)
> {
> 	struct read_element_status_header *st_hdr;
> @@ -1155,6 +1242,8 @@ chgetelemstatus(struct cam_periph *perip
> 				 /* tag_action */ MSG_SIMPLE_Q_TAG,
> 				 /* voltag */ want_voltags,
> 				 /* sea */ softc->sc_firsts[chet],
> +				 /* dvcid */ 1,
> +				 /* curdata */ 1,
> 				 /* count */ 1,
> 				 /* data_ptr */ data,
> 				 /* dxfer_len */ 1024,
> @@ -1177,7 +1266,6 @@ chgetelemstatus(struct cam_periph *perip
> 	size = sizeof(struct read_element_status_header) +
> 	       sizeof(struct read_element_status_page_header) +
> 	       (desclen * cesr->cesr_element_count);
> -
> 	/*
> 	 * Reallocate storage for descriptors and get them from the
> 	 * device.
> @@ -1193,12 +1281,14 @@ chgetelemstatus(struct cam_periph *perip
> 				 /* voltag */ want_voltags,
> 				 /* sea */ softc->sc_firsts[chet]
> 				 + cesr->cesr_element_base,
> +				 /* dvcid */ 1,
> +				 /* curdata */ 1,
> 				 /* count */ cesr->cesr_element_count,
> 				 /* data_ptr */ data,
> 				 /* dxfer_len */ size,
> 				 /* sense_len */ SSD_FULL_SIZE,
> 				 /* timeout */ CH_TIMEOUT_READ_ELEMENT_STATUS);
> -	
> +
> 	error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO,
> 				  /*sense_flags*/ SF_RETRY_UA,
> 				  softc->device_stats);
> @@ -1231,18 +1321,41 @@ chgetelemstatus(struct cam_periph *perip
> 	 * Set up the individual element status structures
> 	 */
> 	for (i = 0; i < avail; ++i) {
> -		struct changer_element_status *ces = &(user_data[i]);
> +		struct changer_element_status *ces;
> 
> -		copy_element_status(softc, pg_hdr->flags, desc, ces);
> +		/*
> +		 * In the changer_element_status structure, fields from
> +		 * the beginning to the field of ces_scsi_lun are common
> +		 * between SCSI-2 and SCSI-3, while all the rest are new
> +		 * from SCSI-3. In order to maintain backward compatibility
> +		 * of the chio command, the ces pointer, below, is computed
> +		 * such that it lines up with the structure boundary
> +		 * corresponding to the SCSI version.
> +		 */
> +		ces = cmd == OCHIOGSTATUS ?
> +		    (struct changer_element_status *)
> +		    ((unsigned char *)user_data + i *
> +		     (offsetof(struct changer_element_status,ces_scsi_lun)+1)):
> +		    &user_data[i];
> +
> +		copy_element_status(softc, pg_hdr->flags, desc,
> +				    ces, scsi_version);
> 
> 		desc = (struct read_element_status_descriptor *)
> -		       ((uintptr_t)desc + desclen);
> +		       ((unsigned char *)desc + desclen);
> 	}
> 
> 	/* Copy element status structures out to userspace. */
> -	error = copyout(user_data,
> -			cesr->cesr_element_status,
> -			avail * sizeof(struct changer_element_status));
> +	if (cmd == OCHIOGSTATUS)
> +		error = copyout(user_data,
> +				cesr->cesr_element_status,
> +				avail* (offsetof(struct changer_element_status,
> +				ces_scsi_lun) + 1));
> +	else
> +		error = copyout(user_data,
> +				cesr->cesr_element_status,
> +				avail * sizeof(struct changer_element_status));
> +
> 	cam_periph_lock(periph);
> 
>  done:
> @@ -1549,6 +1662,39 @@ chgetparams(struct cam_periph *periph)
> 	return(error);
> }
> 
> +static int
> +chscsiversion(struct cam_periph *periph)
> +{
> +	struct scsi_inquiry_data *inq_data;
> +	struct ccb_getdev *cgd;
> +	int dev_scsi_version;
> +	struct cam_sim *sim;
> +
> +	sim = xpt_path_sim(periph->path);
> +	mtx_assert(sim->mtx, MA_OWNED);
> +	if ((cgd = (struct ccb_getdev *)xpt_alloc_ccb_nowait()) == NULL)
> +		return (-1);
> +	/*
> +	 * Get the device information.
> +	 */
> +	xpt_setup_ccb(&cgd->ccb_h,
> +		      periph->path,
> +		      CAM_PRIORITY_NORMAL);
> +	cgd->ccb_h.func_code = XPT_GDEV_TYPE;
> +	xpt_action((union ccb *)cgd);
> +
> +	if (cgd->ccb_h.status != CAM_REQ_CMP) {
> +		xpt_free_ccb((union ccb *)cgd);
> +		return -1;
> +	}
> +
> +	inq_data = &cgd->inq_data;
> +	dev_scsi_version = inq_data->version;
> +	xpt_free_ccb((union ccb *)cgd);
> +
> +	return dev_scsi_version;
> +}
> +
> void
> scsi_move_medium(struct ccb_scsiio *csio, u_int32_t retries,
> 		 void (*cbfcnp)(struct cam_periph *, union ccb *),
> @@ -1654,6 +1800,7 @@ void
> scsi_read_element_status(struct ccb_scsiio *csio, u_int32_t retries,
> 			 void (*cbfcnp)(struct cam_periph *, union ccb *),
> 			 u_int8_t tag_action, int voltag, u_int32_t sea,
> +			 int curdata, int dvcid,
> 			 u_int32_t count, u_int8_t *data_ptr,
> 			 u_int32_t dxfer_len, u_int8_t sense_len,
> 			 u_int32_t timeout)
> @@ -1668,6 +1815,10 @@ scsi_read_element_status(struct ccb_scsi
> 	scsi_ulto2b(sea, scsi_cmd->sea);
> 	scsi_ulto2b(count, scsi_cmd->count);
> 	scsi_ulto3b(dxfer_len, scsi_cmd->len);
> +	if (dvcid)
> +		scsi_cmd->flags |= READ_ELEMENT_STATUS_DVCID;
> +	if (curdata)
> +		scsi_cmd->flags |= READ_ELEMENT_STATUS_CURDATA;
> 
> 	if (voltag)
> 		scsi_cmd->byte2 |= READ_ELEMENT_STATUS_VOLTAG;
> 
> Modified: head/sys/cam/scsi/scsi_ch.h
> ==============================================================================
> --- head/sys/cam/scsi/scsi_ch.h	Fri Apr 19 19:45:00 2013	(r249657)
> +++ head/sys/cam/scsi/scsi_ch.h	Fri Apr 19 20:03:51 2013	(r249658)
> @@ -136,11 +136,14 @@ struct scsi_position_to_element {
> struct scsi_read_element_status {
> 	u_int8_t	opcode;
> 	u_int8_t	byte2;
> -#define READ_ELEMENT_STATUS_VOLTAG	0x10	/* report volume tag info */
> +#define	READ_ELEMENT_STATUS_VOLTAG	0x10	/* report volume tag info */
> 	/* ...next 4 bits are an element type code... */
> 	u_int8_t	sea[2];	/* starting element address */
> 	u_int8_t	count[2]; /* number of elements */
> -	u_int8_t	reserved0;
> +	u_int8_t	flags;
> +#define	READ_ELEMENT_STATUS_DVCID	0x01 /* report device serial number */
> +#define	READ_ELEMENT_STATUS_CURDATA	0x02 /* allow motion during command */
> +
> 	u_int8_t	len[3];	/* length of data buffer */
> 	u_int8_t	reserved1;
> 	u_int8_t	control;
> @@ -149,7 +152,7 @@ struct scsi_read_element_status {
> struct scsi_request_volume_element_address {
> 	u_int8_t	opcode;
> 	u_int8_t	byte2;
> -#define REQUEST_VOLUME_ELEMENT_ADDRESS_VOLTAG	0x10
> +#define	REQUEST_VOLUME_ELEMENT_ADDRESS_VOLTAG	0x10
> 	/* ...next 4 bits are an element type code... */
> 	u_int8_t	eaddr[2];	/* element address */
> 	u_int8_t	count[2];	/* number of elements */
> @@ -182,8 +185,8 @@ struct read_element_status_header {
> struct read_element_status_page_header {
> 	u_int8_t	type;	/* element type code; see type codes below */
> 	u_int8_t	flags;
> -#define READ_ELEMENT_STATUS_AVOLTAG	0x40
> -#define READ_ELEMENT_STATUS_PVOLTAG	0x80
> +#define	READ_ELEMENT_STATUS_AVOLTAG	0x40
> +#define	READ_ELEMENT_STATUS_PVOLTAG	0x80
> 	u_int8_t	edl[2];	/* element descriptor length */
> 	u_int8_t	reserved;
> 	u_int8_t	nbytes[3]; /* byte count of all descriptors */
> @@ -199,50 +202,79 @@ struct volume_tag {
> 	u_int8_t	vsn[2];		/* volume sequence number */
> };
> 
> +struct read_element_status_device_id {
> +	u_int8_t	prot_code_set;
> +#define	READ_ELEMENT_STATUS_CODE_SET(p) ((p) & 0x0F)
> +#define	READ_ELEMENT_STATUS_PROTOCOL_ID(p) ((p) >> 4)
> +
> +	u_int8_t	piv_assoc_designator_type;
> +#define	READ_ELEMENT_STATUS_PIV_SET 0x80
> +#define	READ_ELEMENT_STATUS_ASSOCIATION(p) ((p) >> 4)
> +#define	READ_ELEMENT_STATUS_DESIGNATOR_TYPE(p) ((p) & 0x0F)
> +
> +	u_int8_t	reserved2;
> +	u_int8_t	designator_length;
> +	u_int8_t	designator[256]; /* Allocate max length */
> +};
> +
> struct read_element_status_descriptor {
> 	u_int8_t	eaddr[2];	/* element address */
> 	u_int8_t	flags1;
> 
> -#define READ_ELEMENT_STATUS_FULL	0x01
> -#define READ_ELEMENT_STATUS_IMPEXP	0x02
> -#define READ_ELEMENT_STATUS_EXCEPT	0x04
> -#define READ_ELEMENT_STATUS_ACCESS	0x08
> -#define READ_ELEMENT_STATUS_EXENAB	0x10
> -#define READ_ELEMENT_STATUS_INENAB	0x20
> -
> -#define READ_ELEMENT_STATUS_MT_MASK1	0x05
> -#define READ_ELEMENT_STATUS_ST_MASK1	0x0c
> -#define READ_ELEMENT_STATUS_IE_MASK1	0x3f
> -#define READ_ELEMENT_STATUS_DT_MASK1	0x0c
> +#define	READ_ELEMENT_STATUS_FULL	0x01
> +#define	READ_ELEMENT_STATUS_IMPEXP	0x02
> +#define	READ_ELEMENT_STATUS_EXCEPT	0x04
> +#define	READ_ELEMENT_STATUS_ACCESS	0x08
> +#define	READ_ELEMENT_STATUS_EXENAB	0x10
> +#define	READ_ELEMENT_STATUS_INENAB	0x20
> +
> +#define	READ_ELEMENT_STATUS_MT_MASK1	0x05
> +#define	READ_ELEMENT_STATUS_ST_MASK1	0x0c
> +#define	READ_ELEMENT_STATUS_IE_MASK1	0x3f
> +#define	READ_ELEMENT_STATUS_DT_MASK1	0x0c
> 
> 	u_int8_t	reserved0;
> 	u_int8_t	sense_code;
> 	u_int8_t	sense_qual;
> 
> -	/*
> -	 * dt_scsi_flags and dt_scsi_addr are valid only on data transport
> -	 * elements.  These bytes are undefined for all other element types.
> -	 */
> -	u_int8_t	dt_scsi_flags;
> -
> -#define READ_ELEMENT_STATUS_DT_LUNMASK	0x07
> -#define READ_ELEMENT_STATUS_DT_LUVALID	0x10
> -#define READ_ELEMENT_STATUS_DT_IDVALID	0x20
> -#define READ_ELEMENT_STATUS_DT_NOTBUS	0x80
> -
> -	u_int8_t	dt_scsi_addr;
> -
> -	u_int8_t	reserved1;
> +	union {
> +		struct {
> +			u_int8_t	dt_scsi_flags;
> +
> +#define	READ_ELEMENT_STATUS_DT_LUNMASK	0x07
> +#define	READ_ELEMENT_STATUS_DT_LUVALID	0x10
> +#define	READ_ELEMENT_STATUS_DT_IDVALID	0x20
> +#define	READ_ELEMENT_STATUS_DT_NOTBUS	0x80
> +
> +			u_int8_t	dt_scsi_addr;
> +			u_int8_t	reserved1;
> +		} scsi_2;
> +
> +		/* reserved and obsolete (as of SCSI-3) fields */
> +		u_int8_t	reserved_or_obsolete[3];
> +	} dt_or_obsolete;
> 
> 	u_int8_t	flags2;
> -#define READ_ELEMENT_STATUS_INVERT	0x40
> -#define READ_ELEMENT_STATUS_SVALID	0x80
> -	u_int8_t	ssea[2];	/* source storage element address */
> +#define	READ_ELEMENT_STATUS_INVERT		0x40
> +#define	READ_ELEMENT_STATUS_SVALID		0x80
> +#define	READ_ELEMENT_STATUS_ED			0x80
> +#define	READ_ELEMENT_STATUS_MEDIA_TYPE_MASK	0x07
> 
> -	struct volume_tag pvoltag;	/* omitted if PVOLTAG == 0 */
> -	struct volume_tag avoltag;	/* omitted if AVOLTAG == 0 */
> +	u_int8_t	ssea[2];	/* source storage element address */
> 
> -	/* Other data may follow */
> +	union {
> +		struct volume_tag			pvoltag;
> +		struct volume_tag 			voltag[2];
> +		struct read_element_status_device_id	devid;
> +		struct {
> +			struct volume_tag			pvoltag;
> +			struct read_element_status_device_id	devid;
> +		} pvol_and_devid;
> +		struct {
> +			struct volume_tag			voltag[2];
> +			struct read_element_status_device_id	devid;
> +		} vol_tags_and_devid;
> +	} voltag_devid;
> };
> 
> /* XXX add data returned by REQUEST VOLUME ELEMENT ADDRESS */
> @@ -457,6 +489,7 @@ void scsi_position_to_element(struct ccb
> void scsi_read_element_status(struct ccb_scsiio *csio, u_int32_t retries,
> 			      void (*cbfcnp)(struct cam_periph *, union ccb *),
> 			      u_int8_t tag_action, int voltag, u_int32_t sea,
> +			      int curdata, int dvcid,
> 			      u_int32_t count, u_int8_t *data_ptr,
> 			      u_int32_t dxfer_len, u_int8_t sense_len,
> 			      u_int32_t timeout);
> 
> Modified: head/sys/sys/chio.h
> ==============================================================================
> --- head/sys/sys/chio.h	Fri Apr 19 19:45:00 2013	(r249657)
> +++ head/sys/sys/chio.h	Fri Apr 19 20:03:51 2013	(r249658)
> @@ -152,7 +152,8 @@ typedef enum {
> 	CES_INVERT	  = 0x040,	/* invert bit */
> 	CES_SOURCE_VALID  = 0x080,	/* source address (ces_source) valid */
> 	CES_SCSIID_VALID  = 0x100,	/* ces_scsi_id is valid */
> -	CES_LUN_VALID	  = 0x200	/* ces_scsi_lun is valid */
> +	CES_LUN_VALID	  = 0x200,	/* ces_scsi_lun is valid */
> +	CES_PIV		  = 0x400	/* ces_protocol_id is valid */
> } ces_status_flags;
> 
> struct changer_element_status {
> @@ -181,6 +182,55 @@ struct changer_element_status {
> 	changer_voltag_t	ces_avoltag;	  /* alternate volume tag */
> 	u_int8_t		ces_scsi_id;	  /* SCSI id of element */
> 	u_int8_t		ces_scsi_lun;	  /* SCSI lun of element */
> +
> +	/*
> +	 * Data members for SMC3 and later versions
> +	 */
> +	u_int8_t		ces_medium_type;
> +#define	CES_MEDIUM_TYPE_UNKNOWN		0	/* Medium type unspecified */
> +#define	CES_MEDIUM_TYPE_DATA		1	/* Data medium */
> +#define	CES_MEDIUM_TYPE_CLEANING	2	/* Cleaning medium */
> +#define	CES_MEDIUM_TYPE_DIAGNOSTIC	3	/* Diagnostic medium */
> +#define	CES_MEDIUM_TYPE_WORM		4	/* WORM medium */
> +#define	CES_MEDIUM_TYPE_MICROCODE	5	/* Microcode image medium */
> +
> +	u_int8_t		ces_protocol_id;
> +#define	CES_PROTOCOL_ID_FCP_4	0	/* Fiber channel */
> +#define	CES_PROTOCOL_ID_SPI_5	1	/* Parallel SCSI */
> +#define	CES_PROTOCOL_ID_SSA_S3P	2	/* SSA */
> +#define	CES_PROTOCOL_ID_SBP_3	3	/* IEEE 1394 */
> +#define	CES_PROTOCOL_ID_SRP	4	/* SCSI Remote DMA */
> +#define	CES_PROTOCOL_ID_ISCSI	5	/* iSCSI */
> +#define	CES_PROTOCOL_ID_SPL	6	/* SAS */
> +#define	CES_PROTOCOL_ID_ADT_2	7	/* Automation/Drive Interface */
> +#define	CES_PROTOCOL_ID_ACS_2	8	/* ATA */
> +
> +	u_int8_t		ces_assoc;
> +#define	CES_ASSOC_LOGICAL_UNIT	0
> +#define	CES_ASSOC_TARGET_PORT	1
> +#define	CES_ASSOC_TARGET_DEVICE	2
> +
> +	u_int8_t		ces_designator_type;
> +#define	CES_DESIGNATOR_TYPE_VENDOR_SPECIFIC	0
> +#define	CES_DESIGNATOR_TYPE_T10_VENDOR_ID	1
> +#define	CES_DESIGNATOR_TYPE_EUI_64		2
> +#define	CES_DESIGNATOR_TYPE_NAA			3
> +#define	CES_DESIGNATOR_TYPE_TARGET_PORT_ID	4
> +#define	CES_DESIGNATOR_TYPE_TARGET_PORT_GRP	5
> +#define	CES_DESIGNATOR_TYPE_LOGICAL_UNIT_GRP	6
> +#define	CES_DESIGNATOR_TYPE_MD5_LOGICAL_UNIT_ID	7
> +#define	CES_DESIGNATOR_TYPE_SCSI_NAME_STRING	8
> +
> +	u_int8_t		ces_code_set;
> +#define	CES_CODE_SET_RESERVED	0
> +#define	CES_CODE_SET_BINARY	1
> +#define	CES_CODE_SET_ASCII	2
> +#define	CES_CODE_SET_UTF_8	3
> +
> +	u_int8_t		ces_designator_length;
> +
> +#define	CES_MAX_DESIGNATOR_LENGTH (1 << 8)
> +	u_int8_t		ces_designator[CES_MAX_DESIGNATOR_LENGTH + 1];
> };
> 
> struct changer_element_status_request {
> @@ -189,7 +239,7 @@ struct changer_element_status_request {
> 	u_int16_t			cesr_element_count;
> 
> 	u_int16_t			cesr_flags;
> -#define CESR_VOLTAGS	0x01
> +#define	CESR_VOLTAGS	0x01
> 
> 	struct changer_element_status	*cesr_element_status;
> };
> @@ -200,28 +250,29 @@ struct changer_set_voltag_request {
> 	u_int16_t		csvr_addr;
> 
> 	u_int16_t		csvr_flags;
> -#define CSVR_MODE_MASK		0x0f	/* mode mask, acceptable modes below: */
> +#define	CSVR_MODE_MASK		0x0f	/* mode mask, acceptable modes below: */
> #define	CSVR_MODE_SET		0x00	/* set volume tag if not set */
> -#define CSVR_MODE_REPLACE	0x01	/* unconditionally replace volume tag */
> -#define CSVR_MODE_CLEAR		0x02	/* clear volume tag */
> +#define	CSVR_MODE_REPLACE	0x01	/* unconditionally replace volume tag */
> +#define	CSVR_MODE_CLEAR		0x02	/* clear volume tag */
> 
> -#define CSVR_ALTERNATE		0x10	/* set to work with alternate voltag */
> +#define	CSVR_ALTERNATE		0x10	/* set to work with alternate voltag */
> 
> 	changer_voltag_t     	csvr_voltag;
> };
> 
> 
> -#define CESTATUS_BITS	\
> +#define	CESTATUS_BITS	\
> 	"\20\6INEAB\5EXENAB\4ACCESS\3EXCEPT\2IMPEXP\1FULL"
> 
> -#define CHIOMOVE	_IOW('c', 0x01, struct changer_move)
> -#define CHIOEXCHANGE	_IOW('c', 0x02, struct changer_exchange)
> -#define CHIOPOSITION	_IOW('c', 0x03, struct changer_position)
> -#define CHIOGPICKER	_IOR('c', 0x04, int)
> -#define CHIOSPICKER	_IOW('c', 0x05, int)
> -#define CHIOGPARAMS	_IOR('c', 0x06, struct changer_params)
> -#define CHIOIELEM	_IOW('c', 0x07, u_int32_t)
> -#define CHIOGSTATUS	_IOW('c', 0x08, struct changer_element_status_request)
> -#define CHIOSETVOLTAG	_IOW('c', 0x09, struct changer_set_voltag_request)
> +#define	CHIOMOVE	_IOW('c', 0x01, struct changer_move)
> +#define	CHIOEXCHANGE	_IOW('c', 0x02, struct changer_exchange)
> +#define	CHIOPOSITION	_IOW('c', 0x03, struct changer_position)
> +#define	CHIOGPICKER	_IOR('c', 0x04, int)
> +#define	CHIOSPICKER	_IOW('c', 0x05, int)
> +#define	CHIOGPARAMS	_IOR('c', 0x06, struct changer_params)
> +#define	CHIOIELEM	_IOW('c', 0x07, u_int32_t)
> +#define	OCHIOGSTATUS	_IOW('c', 0x08, struct changer_element_status_request)
> +#define	CHIOSETVOLTAG	_IOW('c', 0x09, struct changer_set_voltag_request)
> +#define	CHIOGSTATUS	_IOW('c', 0x0A, struct changer_element_status_request)
> 
> #endif /* !_SYS_CHIO_H_ */



More information about the svn-src-all mailing list