Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Oct 2004 02:51:21 -0700
From:      Bruce M Simpson <bms@spc.org>
To:        freebsd-current@FreeBSD.org
Subject:   camcontrol(8) and MODE_[SENSE|SELECT]_10
Message-ID:  <20041006095121.GA1794@empiric.icir.org>

next in thread | raw e-mail | index | archive | help

--BwCQnh7xodEAoBMC
Content-Type: multipart/mixed; boundary="LQksG6bCIzRHxTLp"
Content-Disposition: inline


--LQksG6bCIzRHxTLp
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

I need some advice regarding the handling of 10-byte MODE SENSE/SELECT.

Apologies if this is more appropriate for freebsd-scsi@ to which I am
not currently subscribed.

Here is the patch I used to hack camcontrol to force the use of
MODE_SENSE_10 and MODE_SELECT_10 for UFI (umass) devices, i.e.
USB floppy drives.

This is probably not the cleanest way but it avoids using a global flag
for such a thing, which might be cleaner.

Note however that the mode page layouts in src/share/misc/scsi_modes
only seem to be correct for the 6-byte MODE_SENSE and MODE_SELECT
which are not supported for such devices; for 10-byte forms the
mode page layout seems to be subtly different.

Could someone more knowledgeable about the inner workings of CAM and
SCSI in FreeBSD than I advise how we could go about teaching camcontrol(8)
to fetch and display mode pages in a human-readable manner?
(i.e. without necessarily implementing a new utility right away)

This is necessary in order to extract the geometry for a USB floppy
drive in order that track-by-track format may be implemented; the
FORMAT UNIT command for USB floppy drives requires such behaviour
as per the UFI Specification (usbmass-ufi10.pdf).

Regards,
BMS

--LQksG6bCIzRHxTLp
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="camcontrol-modesense10.diff"
Content-Transfer-Encoding: quoted-printable

Index: src/sbin/camcontrol/camcontrol.8
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sbin/camcontrol/camcontrol.8,v
retrieving revision 1.38
diff -u -p -r1.38 camcontrol.8
--- src/sbin/camcontrol/camcontrol.8	3 Jul 2004 00:13:43 -0000	1.38
+++ src/sbin/camcontrol/camcontrol.8	6 Oct 2004 09:17:37 -0000
@@ -95,6 +95,7 @@
 .Op Fl P Ar pgctl
 .Op Fl b | Fl e
 .Op Fl d
+.Op Fl s
 .Nm
 .Ic cmd
 .Op device id
@@ -376,6 +377,9 @@ and/or edit.
 This argument is mandatory unless
 .Fl l
 is specified.
+.It Fl s
+This forces the use of a 10-byte MODE SENSE or MODE SELECT command, which =
is
+necessary for certain kinds of devices.
 .It Fl P Ar pgctl
 This allows the user to specify the page control field.
 Possible values are:
Index: src/sbin/camcontrol/camcontrol.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sbin/camcontrol/camcontrol.c,v
retrieving revision 1.52
diff -u -p -r1.52 camcontrol.c
--- src/sbin/camcontrol/camcontrol.c	3 Mar 2004 01:51:24 -0000	1.52
+++ src/sbin/camcontrol/camcontrol.c	6 Oct 2004 09:13:52 -0000
@@ -139,7 +139,7 @@ struct camcontrol_opts option_table[] =3D=20
 	{"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL},
 #ifndef MINIMALISTIC
 	{"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL},
-	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"},
+	{"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:sP:"},
 	{"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},
@@ -1586,7 +1586,8 @@ reassignblocks(struct cam_device *device
 #ifndef MINIMALISTIC
 void
 mode_sense(struct cam_device *device, int mode_page, int page_control,
-	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen)
+	   int dbd, int retry_count, int timeout, u_int8_t *data, int datalen,
+	   int force10bytes)
 {
 	union ccb *ccb;
 	int retval;
@@ -1599,7 +1600,7 @@ mode_sense(struct cam_device *device, in
 	bzero(&(&ccb->ccb_h)[1],
 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
=20
-	scsi_mode_sense(&ccb->csio,
+	scsi_mode_sense_len(&ccb->csio,
 			/* retries */ retry_count,
 			/* cbfcnp */ NULL,
 			/* tag_action */ MSG_SIMPLE_Q_TAG,
@@ -1608,6 +1609,7 @@ mode_sense(struct cam_device *device, in
 			/* page */ mode_page,
 			/* param_buf */ data,
 			/* param_len */ datalen,
+			/* minimum_cmd_size */ force10bytes ? 10 : 0,
 			/* sense_len */ SSD_FULL_SIZE,
 			/* timeout */ timeout ? timeout : 5000);
=20
@@ -1636,7 +1638,7 @@ mode_sense(struct cam_device *device, in
=20
 void
 mode_select(struct cam_device *device, int save_pages, int retry_count,
-	   int timeout, u_int8_t *data, int datalen)
+	   int timeout, u_int8_t *data, int datalen, int force10bytes)
 {
 	union ccb *ccb;
 	int retval;
@@ -1649,7 +1651,7 @@ mode_select(struct cam_device *device, i
 	bzero(&(&ccb->ccb_h)[1],
 	      sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
=20
-	scsi_mode_select(&ccb->csio,
+	scsi_mode_select_len(&ccb->csio,
 			 /* retries */ retry_count,
 			 /* cbfcnp */ NULL,
 			 /* tag_action */ MSG_SIMPLE_Q_TAG,
@@ -1657,6 +1659,7 @@ mode_select(struct cam_device *device, i
 			 /* save_pages */ save_pages,
 			 /* param_buf */ data,
 			 /* param_len */ datalen,
+			 /* minimum_cmd_size */ force10bytes ? 10 : 0,
 			 /* sense_len */ SSD_FULL_SIZE,
 			 /* timeout */ timeout ? timeout : 5000);
=20
@@ -1690,7 +1693,7 @@ modepage(struct cam_device *device, int=20
 	 int retry_count, int timeout)
 {
 	int c, mode_page =3D -1, page_control =3D 0;
-	int binary =3D 0, list =3D 0;
+	int binary =3D 0, list =3D 0, force10bytes =3D 0;
=20
 	while ((c =3D getopt(argc, argv, combinedopt)) !=3D -1) {
 		switch(c) {
@@ -1711,6 +1714,9 @@ modepage(struct cam_device *device, int=20
 			if (mode_page < 0)
 				errx(1, "invalid mode page %d", mode_page);
 			break;
+		case 's':
+			force10bytes =3D 1;
+			break;
 		case 'P':
 			page_control =3D strtol(optarg, NULL, 0);
 			if ((page_control < 0) || (page_control > 3))
@@ -1728,11 +1734,11 @@ modepage(struct cam_device *device, int=20
=20
 	if (list) {
 		mode_list(device, page_control, arglist & CAM_ARG_DBD,
-		    retry_count, timeout);
+		    retry_count, timeout, force10bytes);
 	} else {
 		mode_edit(device, mode_page, page_control,
 		    arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
-		    retry_count, timeout);
+		    retry_count, timeout, force10bytes);
 	}
 }
=20
@@ -3166,7 +3172,7 @@ usage(int verbose)
 #ifndef MINIMALISTIC
 "        camcontrol defects    [dev_id][generic args] <-f format> [-P][-G]=
\n"
 "        camcontrol modepage   [dev_id][generic args] <-m page | -l>\n"
-"                              [-P pagectl][-e | -b][-d]\n"
+"                              [-P pagectl][-e | -b][-d][-s]\n"
 "        camcontrol cmd        [dev_id][generic args] <-c cmd [args]>\n"
 "                              [-i len fmt|-o len fmt [args]]\n"
 "        camcontrol debug      [-I][-P][-T][-S][-X][-c]\n"
Index: src/sbin/camcontrol/camcontrol.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sbin/camcontrol/camcontrol.h,v
retrieving revision 1.4
diff -u -p -r1.4 camcontrol.h
--- src/sbin/camcontrol/camcontrol.h	8 Aug 2000 06:24:15 -0000	1.4
+++ src/sbin/camcontrol/camcontrol.h	6 Oct 2004 09:14:03 -0000
@@ -42,13 +42,14 @@ struct get_hook
=20
 void mode_sense(struct cam_device *device, int mode_page, int page_control,
 		int dbd, int retry_count, int timeout, u_int8_t *data,
-		int datalen);
+		int datalen, int force10bytes);
 void mode_select(struct cam_device *device, int save_pages, int retry_coun=
t,
-		 int timeout, u_int8_t *data, int datalen);
+		 int timeout, u_int8_t *data, int datalen, int force10bytes);
 void mode_edit(struct cam_device *device, int page, int page_control, int =
dbd,
-	       int edit, int binary, int retry_count, int timeout);
+	       int edit, int binary, int retry_count, int timeout,
+	       int force10bytes);
 void mode_list(struct cam_device *device, int page_control, int dbd,
-	       int retry_count, int timeout);
+	       int retry_count, int timeout, int force10bytes);
 char *cget(void *hook, char *name);
 int iget(void *hook, char *name);
 void arg_put(void *hook, int letter, void *arg, int count, char *name);
Index: src/sbin/camcontrol/modeedit.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sbin/camcontrol/modeedit.c,v
retrieving revision 1.17
diff -u -p -r1.17 modeedit.c
--- src/sbin/camcontrol/modeedit.c	22 Jan 2004 07:23:35 -0000	1.17
+++ src/sbin/camcontrol/modeedit.c	6 Oct 2004 09:17:07 -0000
@@ -110,10 +110,11 @@ static int		 editentry_set(char *name, c
 				       int editonly);
 static void		 editlist_populate(struct cam_device *device,
 					   int modepage, int page_control,
-					   int dbd, int retries, int timeout);
+					   int dbd, int retries, int timeout,
+					   int force10bytes);
 static void		 editlist_save(struct cam_device *device, int modepage,
 				       int page_control, int dbd, int retries,
-				       int timeout);
+				       int timeout, int force10bytes);
 static void		 nameentry_create(int pagenum, char *name);
 static struct pagename	*nameentry_lookup(int pagenum);
 static int		 load_format(const char *pagedb_path, int page);
@@ -122,7 +123,7 @@ static int		 modepage_read(FILE *file);
 static void		 modepage_edit(void);
 static void		 modepage_dump(struct cam_device *device, int page,
 				       int page_control, int dbd, int retries,
-				       int timeout);
+				       int timeout, int force10bytes);
 static void		 cleanup_editfile(void);
=20
=20
@@ -527,7 +528,7 @@ load_format(const char *pagedb_path, int
=20
 static void
 editlist_populate(struct cam_device *device, int modepage, int page_contro=
l,
-		  int dbd, int retries, int timeout)
+		  int dbd, int retries, int timeout, int force10bytes)
 {
 	u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */
 	u_int8_t *mode_pars;		/* Pointer to modepage params. */
@@ -538,7 +539,7 @@ editlist_populate(struct cam_device *dev
=20
 	/* Fetch changeable values; use to build initial editlist. */
 	mode_sense(device, modepage, 1, dbd, retries, timeout, data,
-		   sizeof(data));
+		   sizeof(data), force10bytes);
=20
 	mh =3D (struct scsi_mode_header_6 *)data;
 	mph =3D MODE_PAGE_HEADER(mh);
@@ -550,14 +551,14 @@ editlist_populate(struct cam_device *dev
=20
 	/* Fetch the current/saved values; use to set editentry values. */
 	mode_sense(device, modepage, page_control, dbd, retries, timeout, data,
-		   sizeof(data));
+		   sizeof(data), force10bytes);
 	buff_decode_visit(mode_pars, mh->data_length, format,
 	    editentry_update, 0);
 }
=20
 static void
 editlist_save(struct cam_device *device, int modepage, int page_control,
-	      int dbd, int retries, int timeout)
+	      int dbd, int retries, int timeout, int force10bytes)
 {
 	u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */
 	u_int8_t *mode_pars;		/* Pointer to modepage params. */
@@ -575,7 +576,7 @@ editlist_save(struct cam_device *device,
 	 *     now, we need mode_sense to find out the page length.
 	 */
 	mode_sense(device, modepage, page_control, dbd, retries, timeout, data,
-		   sizeof(data));
+		   sizeof(data), force10bytes);
=20
 	/* Initial headers & offsets. */
 	mh =3D (struct scsi_mode_header_6 *)data;
@@ -607,7 +608,8 @@ editlist_save(struct cam_device *device,
 	mode_select(device,
 	    (page_control << PAGE_CTRL_SHIFT =3D=3D SMS_PAGE_CTRL_SAVED),
 	    retries, timeout, (u_int8_t *)mh,
-	    sizeof(*mh) + mh->blk_desc_len + sizeof(*mph) + mph->page_length);
+	    sizeof(*mh) + mh->blk_desc_len + sizeof(*mph) + mph->page_length,
+	    force10bytes);
 }
=20
 static int
@@ -777,7 +779,7 @@ modepage_edit(void)
=20
 static void
 modepage_dump(struct cam_device *device, int page, int page_control, int d=
bd,
-	      int retries, int timeout)
+	      int retries, int timeout, int force10bytes)
 {
 	u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */
 	u_int8_t *mode_pars;		/* Pointer to modepage params. */
@@ -786,7 +788,7 @@ modepage_dump(struct cam_device *device,
 	int indx;			/* Index for scanning mode params. */
=20
 	mode_sense(device, page, page_control, dbd, retries, timeout, data,
-		   sizeof(data));
+		   sizeof(data), force10bytes);
=20
 	mh =3D (struct scsi_mode_header_6 *)data;
 	mph =3D MODE_PAGE_HEADER(mh);
@@ -812,7 +814,8 @@ cleanup_editfile(void)
=20
 void
 mode_edit(struct cam_device *device, int page, int page_control, int dbd,
-	  int edit, int binary, int retry_count, int timeout)
+	  int edit, int binary, int retry_count, int timeout,
+	  int force10bytes)
 {
 	const char *pagedb_path;	/* Path to modepage database. */
=20
@@ -842,7 +845,7 @@ mode_edit(struct cam_device *device, int
 		}
=20
 		editlist_populate(device, page, page_control, dbd, retry_count,
-			timeout);
+			timeout, force10bytes);
 	}
=20
 	if (edit) {
@@ -852,11 +855,11 @@ mode_edit(struct cam_device *device, int
 			    "(current) or page 3 (saved values)");
 		modepage_edit();
 		editlist_save(device, page, page_control, dbd, retry_count,
-			timeout);
+			timeout, force10bytes);
 	} else if (binary || STAILQ_EMPTY(&editlist)) {
 		/* Display without formatting information. */
 		modepage_dump(device, page, page_control, dbd, retry_count,
-		    timeout);
+		    timeout, force10bytes);
 	} else {
 		/* Display with format. */
 		modepage_write(stdout, 0);
@@ -865,7 +868,7 @@ mode_edit(struct cam_device *device, int
=20
 void
 mode_list(struct cam_device *device, int page_control, int dbd,
-	  int retry_count, int timeout)
+	  int retry_count, int timeout, int force10bytes)
 {
 	u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */
 	u_int8_t *mode_pars;		/* Pointer to modepage params. */
@@ -885,7 +888,7 @@ mode_list(struct cam_device *device, int
=20
 	/* Build the list of all mode pages by querying the "all pages" page. */
 	mode_sense(device, SMS_ALL_PAGES_PAGE, page_control, dbd, retry_count,
-	    timeout, data, sizeof(data));
+	    timeout, data, sizeof(data), force10bytes);
=20
 	mh =3D (struct scsi_mode_header_6 *)data;
 	len =3D mh->blk_desc_len;		/* Skip block descriptors. */

--LQksG6bCIzRHxTLp--

--BwCQnh7xodEAoBMC
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Comment: ''

iD8DBQFBY8AYueUpAYYNtTsRAo6cAJoCjodbe2yLp4P7luW6Dkj3SDGf7wCePLlc
CBYFtvMTLqSlJJWyxgMgzyg=
=q4pe
-----END PGP SIGNATURE-----

--BwCQnh7xodEAoBMC--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20041006095121.GA1794>