svn commit: r351582 - in stable/11: sbin/camcontrol sys/cam/scsi

Alexander Motin mav at FreeBSD.org
Wed Aug 28 20:23:10 UTC 2019


Author: mav
Date: Wed Aug 28 20:23:08 2019
New Revision: 351582
URL: https://svnweb.freebsd.org/changeset/base/351582

Log:
  MFC r350676: Make `camcontrol modepage` support block descriptors.
  
  It allows to read and write block descriptors alike to mode page parameters.
  It allows to change block size or short-stroke HDDs or overprovision SSDs.
  Depenting on -P parameter the change can be either persistent or till reset.
  In case of block size change device may need reformat after the setting.
  In case of SSD overprovisioning format or sanitize may be needed to really
  free the flash.
  
  During implementation appeared that csio_encode_visit() can not handle
  integers of more then 4 bytes, that makes 8-byte LBA handling awkward.
  I had to split it into two 4-byte halves now.
  
  Relnotes:	yes
  Sponsored by:	iXsystems, Inc.

Modified:
  stable/11/sbin/camcontrol/camcontrol.8
  stable/11/sbin/camcontrol/camcontrol.c
  stable/11/sbin/camcontrol/camcontrol.h
  stable/11/sbin/camcontrol/modeedit.c
  stable/11/sys/cam/scsi/scsi_all.c
  stable/11/sys/cam/scsi/scsi_all.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sbin/camcontrol/camcontrol.8
==============================================================================
--- stable/11/sbin/camcontrol/camcontrol.8	Wed Aug 28 20:22:14 2019	(r351581)
+++ stable/11/sbin/camcontrol/camcontrol.8	Wed Aug 28 20:23:08 2019	(r351582)
@@ -27,7 +27,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 30, 2019
+.Dd August 6, 2019
 .Dt CAMCONTROL 8
 .Os
 .Sh NAME
@@ -125,6 +125,8 @@
 .Op Fl 6
 .Aq Fl m Ar page[,subpage] | Fl l
 .Op Fl P Ar pgctl
+.Op Fl D
+.Op Fl L
 .Op Fl b | Fl e
 .Op Fl d
 .Nm
@@ -733,6 +735,11 @@ If not specified,
 starts with 10 byte commands and falls back to 6 byte on error.
 .It Fl d
 Disable block descriptors for mode sense.
+.It Fl D
+Display/edit block descriptors instead of mode page.
+.It Fl L
+Use long LBA block descriptors.
+Allows number of LBAs bigger then 2^^32.
 .It Fl b
 Displays mode page data in binary format.
 .It Fl e

Modified: stable/11/sbin/camcontrol/camcontrol.c
==============================================================================
--- stable/11/sbin/camcontrol/camcontrol.c	Wed Aug 28 20:22:14 2019	(r351581)
+++ stable/11/sbin/camcontrol/camcontrol.c	Wed Aug 28 20:23:08 2019	(r351582)
@@ -224,7 +224,7 @@ static struct camcontrol_opts option_table[] = {
 	{"devtype", CAM_CMD_DEVTYPE, CAM_ARG_NONE, ""},
 #ifndef MINIMALISTIC
 	{"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
-	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "6bdelm:P:"},
+	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "6bdelm:DLP:"},
 	{"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"},
 	{"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
 	{"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts},
@@ -4430,9 +4430,9 @@ reassignblocks(struct cam_device *device, u_int32_t *b
 
 #ifndef MINIMALISTIC
 void
-mode_sense(struct cam_device *device, int *cdb_len, int dbd, int pc, int page,
-    int subpage, int task_attr, int retry_count, int timeout, u_int8_t *data,
-    int datalen)
+mode_sense(struct cam_device *device, int *cdb_len, int dbd, int llbaa, int pc,
+    int page, int subpage, int task_attr, int retry_count, int timeout,
+    u_int8_t *data, int datalen)
 {
 	union ccb *ccb;
 	int error_code, sense_key, asc, ascq;
@@ -4464,6 +4464,11 @@ retry:
 			/* minimum_cmd_size */ *cdb_len,
 			/* sense_len */ SSD_FULL_SIZE,
 			/* timeout */ timeout ? timeout : 5000);
+	if (llbaa && ccb->csio.cdb_len == 10) {
+		struct scsi_mode_sense_10 *cdb =
+		    (struct scsi_mode_sense_10 *)ccb->csio.cdb_io.cdb_bytes;
+		cdb->byte2 |= SMS10_LLBAA;
+	}
 
 	/* Record what CDB size the above function really set. */
 	*cdb_len = ccb->csio.cdb_len;
@@ -4555,8 +4560,8 @@ modepage(struct cam_device *device, int argc, char **a
 	 int task_attr, int retry_count, int timeout)
 {
 	char *str_subpage;
-	int c, page = -1, subpage = -1, pc = 0;
-	int binary = 0, cdb_len = 10, dbd = 0, edit = 0, list = 0;
+	int c, page = -1, subpage = -1, pc = 0, llbaa = 0;
+	int binary = 0, cdb_len = 10, dbd = 0, desc = 0, edit = 0, list = 0;
 
 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
 		switch(c) {
@@ -4588,6 +4593,12 @@ modepage(struct cam_device *device, int argc, char **a
 			if (subpage < 0)
 				errx(1, "invalid mode subpage %d", subpage);
 			break;
+		case 'D':
+			desc = 1;
+			break;
+		case 'L':
+			llbaa = 1;
+			break;
 		case 'P':
 			pc = strtol(optarg, NULL, 0);
 			if ((pc < 0) || (pc > 3))
@@ -4598,15 +4609,21 @@ modepage(struct cam_device *device, int argc, char **a
 		}
 	}
 
-	if (page == -1 && list == 0)
+	if (page == -1 && desc == 0 && list == 0)
 		errx(1, "you must specify a mode page!");
 
+	if (dbd && desc)
+		errx(1, "-d and -D are incompatible!");
+
+	if (llbaa && cdb_len != 10)
+		errx(1, "LLBAA bit is not present in MODE SENSE(6)!");
+
 	if (list != 0) {
 		mode_list(device, cdb_len, dbd, pc, list > 1, task_attr,
 		    retry_count, timeout);
 	} else {
-		mode_edit(device, cdb_len, dbd, pc, page, subpage, edit,
-		    binary, task_attr, retry_count, timeout);
+		mode_edit(device, cdb_len, desc, dbd, llbaa, pc, page, subpage,
+		    edit, binary, task_attr, retry_count, timeout);
 	}
 }
 

Modified: stable/11/sbin/camcontrol/camcontrol.h
==============================================================================
--- stable/11/sbin/camcontrol/camcontrol.h	Wed Aug 28 20:22:14 2019	(r351581)
+++ stable/11/sbin/camcontrol/camcontrol.h	Wed Aug 28 20:23:08 2019	(r351582)
@@ -88,15 +88,15 @@ int epc(struct cam_device *device, int argc, char **ar
 int timestamp(struct cam_device *device, int argc, char **argv,
 	      char *combinedopt, int task_attr, int retry_count, int timeout,
 	      int verbosemode);
-void mode_sense(struct cam_device *device, int *cdb_len, int dbd, int pc,
-		int page, int subpage, int task_attr, int retry_count,
+void mode_sense(struct cam_device *device, int *cdb_len, int dbd, int llbaa,
+		int pc, int page, int subpage, int task_attr, int retry_count,
 		int timeout, uint8_t *data, int datalen);
 void mode_select(struct cam_device *device, int cdb_len, int save_pages,
 		 int task_attr, int retry_count, int timeout, u_int8_t *data,
 		 int datalen);
-void mode_edit(struct cam_device *device, int cdb_len, int dbd, int pc,
-	       int page, int subpage, int edit, int binary, int task_attr,
-	       int retry_count, int timeout);
+void mode_edit(struct cam_device *device, int cdb_len, int desc, int dbd,
+	       int llbaa, int pc, int page, int subpage, int edit, int binary,
+	       int task_attr, int retry_count, int timeout);
 void mode_list(struct cam_device *device, int cdb_len, int dbd, int pc,
 	       int subpages, int task_attr, int retry_count, int timeout);
 int scsidoinquiry(struct cam_device *device, int argc, char **argv,

Modified: stable/11/sbin/camcontrol/modeedit.c
==============================================================================
--- stable/11/sbin/camcontrol/modeedit.c	Wed Aug 28 20:22:14 2019	(r351581)
+++ stable/11/sbin/camcontrol/modeedit.c	Wed Aug 28 20:23:08 2019	(r351582)
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/queue.h>
 #include <sys/types.h>
+#include <sys/sbuf.h>
 
 #include <assert.h>
 #include <ctype.h>
@@ -96,6 +97,8 @@ static void		 editentry_create(void *hook, int letter,
 					  int count, char *name);
 static void		 editentry_update(void *hook, int letter, void *arg,
 					  int count, char *name);
+static void		 editentry_create_desc(void *hook, int letter, void *arg,
+					  int count, char *name);
 static int		 editentry_save(void *hook, char *name);
 static struct editentry	*editentry_lookup(char *name);
 static int		 editentry_set(char *name, char *newvalue,
@@ -103,9 +106,16 @@ static int		 editentry_set(char *name, char *newvalue,
 static void		 editlist_populate(struct cam_device *device,
 			    int cdb_len, int dbd, int pc, int page, int subpage,
 			    int task_attr, int retries, int timeout);
+static void		 editlist_populate_desc(struct cam_device *device,
+			    int cdb_len, int llbaa, int pc, int page,
+			    int subpage, int task_attr, int retries,
+			    int timeout);
 static void		 editlist_save(struct cam_device *device, int cdb_len,
 			    int dbd, int pc, int page, int subpage,
 			    int task_attr, int retries, int timeout);
+static void		 editlist_save_desc(struct cam_device *device, int cdb_len,
+			    int llbaa, int pc, int page, int subpage,
+			    int task_attr, int retries, int timeout);
 static void		 nameentry_create(int page, int subpage, char *name);
 static struct pagename	*nameentry_lookup(int page, int subpage);
 static int		 load_format(const char *pagedb_path, int lpage,
@@ -116,6 +126,10 @@ static void		 modepage_edit(void);
 static void		 modepage_dump(struct cam_device *device, int cdb_len,
 			    int dbd, int pc, int page, int subpage,
 			    int task_attr, int retries, int timeout);
+static void		 modepage_dump_desc(struct cam_device *device,
+			    int cdb_len, int llbaa, int pc, int page,
+			    int subpage, int task_attr, int retries,
+			    int timeout);
 static void		 cleanup_editfile(void);
 
 
@@ -182,6 +196,43 @@ editentry_update(void *hook __unused, int letter, void
 	}
 }
 
+static void
+editentry_create_desc(void *hook __unused, int letter, void *arg, int count,
+		 char *name)
+{
+	struct editentry *newentry;	/* Buffer to hold new entry. */
+
+	/* Allocate memory for the new entry and a copy of the entry name. */
+	if ((newentry = malloc(sizeof(struct editentry))) == NULL ||
+	    (newentry->name = strdup(name)) == NULL)
+		err(EX_OSERR, NULL);
+
+	/* Trim any trailing whitespace for the entry name. */
+	RTRIM(newentry->name);
+
+	newentry->editable = 1;
+	newentry->type = letter;
+	newentry->size = count;
+	newentry->value.svalue = NULL;
+
+	STAILQ_INSERT_TAIL(&editlist, newentry, link);
+
+	switch (letter) {
+	case 'i':			/* Byte-sized integral type. */
+	case 'b':			/* Bit-sized integral types. */
+	case 't':
+		newentry->value.ivalue = (intptr_t)arg;
+		break;
+
+	case 'c':			/* Character array. */
+	case 'z':			/* Null-padded string. */
+		editentry_set(name, (char *)arg, 0);
+		break;
+	default:
+		; /* NOTREACHED */
+	}
+}
+
 static int
 editentry_save(void *hook __unused, char *name)
 {
@@ -238,7 +289,7 @@ editentry_set(char *name, char *newvalue, int editonly
 	struct editentry *dest;	/* Modepage entry to update. */
 	char *cval;		/* Pointer to new string value. */
 	char *convertend;	/* End-of-conversion pointer. */
-	int ival;		/* New integral value. */
+	long long ival, newival; /* New integral value. */
 	int resolution;		/* Resolution in bits for integer conversion. */
 
 /*
@@ -248,7 +299,7 @@ editentry_set(char *name, char *newvalue, int editonly
  *     currently workaround it (even for int64's), so we have to kludge it.
  */
 #define	RESOLUTION_MAX(size) ((resolution * (size) == 32)? 		\
-	INT_MAX: (1 << (resolution * (size))) - 1)
+	UINT_MAX: (1 << (resolution * (size))) - 1)
 
 	assert(newvalue != NULL);
 	if (*newvalue == '\0')
@@ -265,13 +316,13 @@ editentry_set(char *name, char *newvalue, int editonly
 	case 't':
 		/* Convert the value string to an integer. */
 		resolution = (dest->type == 'i')? 8: 1;
-		ival = (int)strtol(newvalue, &convertend, 0);
+		ival = strtoll(newvalue, &convertend, 0);
 		if (*convertend != '\0')
 			returnerr(EINVAL);
 		if (ival > RESOLUTION_MAX(dest->size) || ival < 0) {
-			int newival = (ival < 0)? 0: RESOLUTION_MAX(dest->size);
-			warnx("value %d is out of range for entry %s; clipping "
-			    "to %d", ival, name, newival);
+			newival = (ival < 0) ? 0 : RESOLUTION_MAX(dest->size);
+			warnx("value %lld is out of range for entry %s; "
+			    "clipping to %lld", ival, name, newival);
 			ival = newival;
 		}
 		if (dest->value.ivalue != ival)
@@ -548,7 +599,7 @@ static void
 editlist_populate(struct cam_device *device, int cdb_len, int dbd, int pc,
     int page, int subpage, int task_attr, int retries, int timeout)
 {
-	u_int8_t data[MAX_DATA_SIZE];/* Buffer to hold sense data. */
+	u_int8_t data[MAX_DATA_SIZE];	/* Buffer to hold mode parameters. */
 	u_int8_t *mode_pars;		/* Pointer to modepage params. */
 	struct scsi_mode_page_header *mph;
 	struct scsi_mode_page_header_sp *mphsp;
@@ -557,8 +608,8 @@ editlist_populate(struct cam_device *device, int cdb_l
 	STAILQ_INIT(&editlist);
 
 	/* Fetch changeable values; use to build initial editlist. */
-	mode_sense(device, &cdb_len, dbd, 1, page, subpage, task_attr, retries,
-		   timeout, data, sizeof(data));
+	mode_sense(device, &cdb_len, dbd, 0, 1, page, subpage, task_attr,
+		   retries, timeout, data, sizeof(data));
 
 	if (cdb_len == 6) {
 		struct scsi_mode_header_6 *mh =
@@ -583,16 +634,77 @@ editlist_populate(struct cam_device *device, int cdb_l
 	buff_decode_visit(mode_pars, len, format, editentry_create, 0);
 
 	/* Fetch the current/saved values; use to set editentry values. */
-	mode_sense(device, &cdb_len, dbd, pc, page, subpage, task_attr,
+	mode_sense(device, &cdb_len, dbd, 0, pc, page, subpage, task_attr,
 	    retries, timeout, data, sizeof(data));
 	buff_decode_visit(mode_pars, len, format, editentry_update, 0);
 }
 
 static void
+editlist_populate_desc(struct cam_device *device, int cdb_len, int llbaa, int pc,
+    int page, int subpage, int task_attr, int retries, int timeout)
+{
+	uint8_t data[MAX_DATA_SIZE];	/* Buffer to hold mode parameters. */
+	uint8_t *desc;			/* Pointer to block descriptor. */
+	char num[8];
+	struct sbuf sb;
+	size_t len;
+	u_int longlba, dlen, i;
+
+	STAILQ_INIT(&editlist);
+
+	/* Fetch the current/saved values. */
+	mode_sense(device, &cdb_len, 0, llbaa, pc, page, subpage, task_attr,
+	    retries, timeout, data, sizeof(data));
+
+	if (cdb_len == 6) {
+		struct scsi_mode_header_6 *mh =
+		    (struct scsi_mode_header_6 *)data;
+		desc = (uint8_t *)(mh + 1);
+		len = mh->blk_desc_len;
+		longlba = 0;
+	} else {
+		struct scsi_mode_header_10 *mh =
+		    (struct scsi_mode_header_10 *)data;
+		desc = (uint8_t *)(mh + 1);
+		len = scsi_2btoul(mh->blk_desc_len);
+		longlba = (mh->flags & SMH_LONGLBA) != 0;
+	}
+	dlen = longlba ? 16 : 8;
+	len = MIN(len, sizeof(data) - (desc - data));
+
+	sbuf_new(&sb, format, sizeof(format), SBUF_FIXEDLEN);
+	num[0] = 0;
+	for (i = 0; i * dlen < len; i++) {
+		if (i > 0)
+			snprintf(num, sizeof(num), " %d", i + 1);
+		if (longlba) {
+			sbuf_printf(&sb, "{Number of Logical Blocks%s High} i4\n", num);
+			sbuf_printf(&sb, "{Number of Logical Blocks%s} i4\n", num);
+			sbuf_cat(&sb, "{Reserved} *i4\n");
+			sbuf_printf(&sb, "{Logical Block Length%s} i4\n", num);
+		} else if (device->pd_type == T_DIRECT) {
+			sbuf_printf(&sb, "{Number of Logical Blocks%s} i4\n", num);
+			sbuf_cat(&sb, "{Reserved} *i1\n");
+			sbuf_printf(&sb, "{Logical Block Length%s} i3\n", num);
+		} else {
+			sbuf_printf(&sb, "{Density Code%s} i1\n", num);
+			sbuf_printf(&sb, "{Number of Logical Blocks%s} i3\n", num);
+			sbuf_cat(&sb, "{Reserved} *i1\n");
+			sbuf_printf(&sb, "{Logical Block Length%s} i3\n", num);
+		}
+	}
+	sbuf_finish(&sb);
+	sbuf_delete(&sb);
+
+	/* Decode the value data, creating edit_entries for each value. */
+	buff_decode_visit(desc, len, format, editentry_create_desc, 0);
+}
+
+static void
 editlist_save(struct cam_device *device, int cdb_len, int dbd, int pc,
     int page, int subpage, int task_attr, int retries, int timeout)
 {
-	u_int8_t data[MAX_DATA_SIZE];/* Buffer to hold sense data. */
+	u_int8_t data[MAX_DATA_SIZE];	/* Buffer to hold mode parameters. */
 	u_int8_t *mode_pars;		/* Pointer to modepage params. */
 	struct scsi_mode_page_header *mph;
 	struct scsi_mode_page_header_sp *mphsp;
@@ -603,7 +715,7 @@ editlist_save(struct cam_device *device, int cdb_len, 
 		return;
 
 	/* Preload the CDB buffer with the current mode page data. */
-	mode_sense(device, &cdb_len, dbd, pc, page, subpage, task_attr,
+	mode_sense(device, &cdb_len, dbd, 0, pc, page, subpage, task_attr,
 	    retries, timeout, data, sizeof(data));
 
 	/* Initial headers & offsets. */
@@ -676,6 +788,56 @@ editlist_save(struct cam_device *device, int cdb_len, 
 	    task_attr, retries, timeout, data, hlen + mphlen + len);
 }
 
+static void
+editlist_save_desc(struct cam_device *device, int cdb_len, int llbaa, int pc,
+    int page, int subpage, int task_attr, int retries, int timeout)
+{
+	uint8_t data[MAX_DATA_SIZE];	/* Buffer to hold mode parameters. */
+	uint8_t *desc;			/* Pointer to block descriptor. */
+	size_t len, hlen;
+
+	/* Make sure that something changed before continuing. */
+	if (! editlist_changed)
+		return;
+
+	/* Preload the CDB buffer with the current mode page data. */
+	mode_sense(device, &cdb_len, 0, llbaa, pc, page, subpage, task_attr,
+	    retries, timeout, data, sizeof(data));
+
+	/* Initial headers & offsets. */
+	if (cdb_len == 6) {
+		struct scsi_mode_header_6 *mh =
+		    (struct scsi_mode_header_6 *)data;
+		hlen = sizeof(*mh);
+		desc = (uint8_t *)(mh + 1);
+		len = mh->blk_desc_len;
+		mh->data_length = 0;	/* Reserved for MODE SELECT command. */
+		if (device->pd_type != T_SEQUENTIAL)
+			mh->dev_spec = 0;	/* See comment above */
+	} else {
+		struct scsi_mode_header_10 *mh =
+		    (struct scsi_mode_header_10 *)data;
+		hlen = sizeof(*mh);
+		desc = (uint8_t *)(mh + 1);
+		len = scsi_2btoul(mh->blk_desc_len);
+		scsi_ulto2b(0, mh->data_length); /* Reserved for MODE SELECT. */
+		if (device->pd_type != T_SEQUENTIAL)
+			mh->dev_spec = 0;	/* See comment above */
+	}
+	len = MIN(len, sizeof(data) - (desc - data));
+
+	/* Encode the value data to be passed back to the device. */
+	buff_encode_visit(desc, len, format, editentry_save, 0);
+
+	/*
+	 * Write the changes back to the device. If the user editted control
+	 * page 3 (saved values) then request the changes be permanently
+	 * recorded.
+	 */
+	mode_select(device, cdb_len, (pc << PAGE_CTRL_SHIFT == SMS_PAGE_CTRL_SAVED),
+	    task_attr, retries, timeout, data, hlen + len);
+}
+
 static int
 modepage_write(FILE *file, int editonly)
 {
@@ -689,7 +851,7 @@ modepage_write(FILE *file, int editonly)
 				fprintf(file, "%s:  %s\n", scan->name,
 				    scan->value.svalue);
 			} else {
-				fprintf(file, "%s:  %d\n", scan->name,
+				fprintf(file, "%s:  %u\n", scan->name,
 				    scan->value.ivalue);
 			}
 		}
@@ -845,13 +1007,13 @@ static void
 modepage_dump(struct cam_device *device, int cdb_len, int dbd, int pc,
 	      int page, int subpage, int task_attr, int retries, int timeout)
 {
-	u_int8_t data[MAX_DATA_SIZE];/* Buffer to hold sense data. */
+	u_int8_t data[MAX_DATA_SIZE];	/* Buffer to hold mode parameters. */
 	u_int8_t *mode_pars;		/* Pointer to modepage params. */
 	struct scsi_mode_page_header *mph;
 	struct scsi_mode_page_header_sp *mphsp;
 	size_t indx, len;
 
-	mode_sense(device, &cdb_len, dbd, pc, page, subpage, task_attr,
+	mode_sense(device, &cdb_len, dbd, 0, pc, page, subpage, task_attr,
 	    retries, timeout, data, sizeof(data));
 
 	if (cdb_len == 6) {
@@ -880,7 +1042,38 @@ modepage_dump(struct cam_device *device, int cdb_len, 
 	}
 	putchar('\n');
 }
+static void
+modepage_dump_desc(struct cam_device *device, int cdb_len, int llbaa, int pc,
+	      int page, int subpage, int task_attr, int retries, int timeout)
+{
+	uint8_t data[MAX_DATA_SIZE];	/* Buffer to hold mode parameters. */
+	uint8_t *desc;			/* Pointer to block descriptor. */
+	size_t indx, len;
 
+	mode_sense(device, &cdb_len, 0, llbaa, pc, page, subpage, task_attr,
+	    retries, timeout, data, sizeof(data));
+
+	if (cdb_len == 6) {
+		struct scsi_mode_header_6 *mh =
+		    (struct scsi_mode_header_6 *)data;
+		desc = (uint8_t *)(mh + 1);
+		len = mh->blk_desc_len;
+	} else {
+		struct scsi_mode_header_10 *mh =
+		    (struct scsi_mode_header_10 *)data;
+		desc = (uint8_t *)(mh + 1);
+		len = scsi_2btoul(mh->blk_desc_len);
+	}
+	len = MIN(len, sizeof(data) - (desc - data));
+
+	/* Print the raw mode page data with newlines each 8 bytes. */
+	for (indx = 0; indx < len; indx++) {
+		printf("%02x%c", desc[indx],
+		    (((indx + 1) % 8) == 0) ? '\n' : ' ');
+	}
+	putchar('\n');
+}
+
 static void
 cleanup_editfile(void)
 {
@@ -892,16 +1085,19 @@ cleanup_editfile(void)
 }
 
 void
-mode_edit(struct cam_device *device, int cdb_len, int dbd, int pc, int page,
-	  int subpage, int edit, int binary, int task_attr, int retry_count,
-	  int timeout)
+mode_edit(struct cam_device *device, int cdb_len, int desc, int dbd, int llbaa,
+    int pc, int page, int subpage, int edit, int binary, int task_attr,
+    int retry_count, int timeout)
 {
 	const char *pagedb_path;	/* Path to modepage database. */
 
-	if (edit && binary)
-		errx(EX_USAGE, "cannot edit in binary mode.");
-
-	if (! binary) {
+	if (binary) {
+		if (edit)
+			errx(EX_USAGE, "cannot edit in binary mode.");
+	} else if (desc) {
+		editlist_populate_desc(device, cdb_len, llbaa, pc, page,
+		    subpage, task_attr, retry_count, timeout);
+	} else {
 		if ((pagedb_path = getenv("SCSI_MODES")) == NULL)
 			pagedb_path = DEFAULT_SCSI_MODE_DB;
 
@@ -935,12 +1131,22 @@ mode_edit(struct cam_device *device, int cdb_len, int 
 			errx(EX_USAGE, "it only makes sense to edit page 0 "
 			    "(current) or page 3 (saved values)");
 		modepage_edit();
-		editlist_save(device, cdb_len, dbd, pc, page, subpage,
-		    task_attr, retry_count, timeout);
+		if (desc) {
+			editlist_save_desc(device, cdb_len, llbaa, pc, page,
+			    subpage, task_attr, retry_count, timeout);
+		} else {
+			editlist_save(device, cdb_len, dbd, pc, page, subpage,
+			    task_attr, retry_count, timeout);
+		}
 	} else if (binary || STAILQ_EMPTY(&editlist)) {
 		/* Display without formatting information. */
-		modepage_dump(device, cdb_len, dbd, pc, page, subpage,
-		    task_attr, retry_count, timeout);
+		if (desc) {
+			modepage_dump_desc(device, cdb_len, llbaa, pc, page,
+			    subpage, task_attr, retry_count, timeout);
+		} else {
+			modepage_dump(device, cdb_len, dbd, pc, page, subpage,
+			    task_attr, retry_count, timeout);
+		}
 	} else {
 		/* Display with format. */
 		modepage_write(stdout, 0);
@@ -951,7 +1157,7 @@ void
 mode_list(struct cam_device *device, int cdb_len, int dbd, int pc, int subpages,
 	  int task_attr, int retry_count, int timeout)
 {
-	u_int8_t data[MAX_DATA_SIZE];/* Buffer to hold sense data. */
+	u_int8_t data[MAX_DATA_SIZE];	/* Buffer to hold mode parameters. */
 	struct scsi_mode_page_header *mph;
 	struct scsi_mode_page_header_sp *mphsp;
 	struct pagename *nameentry;
@@ -967,7 +1173,7 @@ mode_list(struct cam_device *device, int cdb_len, int 
 	}
 
 	/* Build the list of all mode pages by querying the "all pages" page. */
-	mode_sense(device, &cdb_len, dbd, pc, SMS_ALL_PAGES_PAGE,
+	mode_sense(device, &cdb_len, dbd, 0, pc, SMS_ALL_PAGES_PAGE,
 	    subpages ? SMS_SUBPAGE_ALL : 0,
 	    task_attr, retry_count, timeout, data, sizeof(data));
 

Modified: stable/11/sys/cam/scsi/scsi_all.c
==============================================================================
--- stable/11/sys/cam/scsi/scsi_all.c	Wed Aug 28 20:22:14 2019	(r351581)
+++ stable/11/sys/cam/scsi/scsi_all.c	Wed Aug 28 20:23:08 2019	(r351582)
@@ -2054,7 +2054,7 @@ static struct asc_table_entry asc_table[] = {
 	{ SST(0x30, 0x13, SS_RDEF,	/* XXX TBD */
 	    "Cleaning volume expired") },
 	/* DT  WRO   BK   */
-	{ SST(0x31, 0x00, SS_RDEF,
+	{ SST(0x31, 0x00, SS_FATAL | ENXIO,
 	    "Medium format corrupted") },
 	/* D L  RO   B    */
 	{ SST(0x31, 0x01, SS_RDEF,

Modified: stable/11/sys/cam/scsi/scsi_all.h
==============================================================================
--- stable/11/sys/cam/scsi/scsi_all.h	Wed Aug 28 20:22:14 2019	(r351581)
+++ stable/11/sys/cam/scsi/scsi_all.h	Wed Aug 28 20:23:08 2019	(r351582)
@@ -3574,7 +3574,9 @@ struct scsi_mode_header_10
 	u_int8_t data_length[2];/* Sense data length */
 	u_int8_t medium_type;
 	u_int8_t dev_spec;
-	u_int8_t unused[2];
+	u_int8_t flags;
+#define	SMH_LONGLBA	0x01
+	u_int8_t unused;
 	u_int8_t blk_desc_len[2];
 };
 


More information about the svn-src-all mailing list