camcontrol(8) and MODE_[SENSE|SELECT]_10
Bruce M Simpson
bms at spc.org
Wed Oct 6 02:51:28 PDT 2004
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
-------------- next part --------------
Index: src/sbin/camcontrol/camcontrol.8
===================================================================
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
===================================================================
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[] =
{"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));
- 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);
@@ -1636,7 +1638,7 @@ mode_sense(struct cam_device *device, in
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));
- 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);
@@ -1690,7 +1693,7 @@ modepage(struct cam_device *device, int
int retry_count, int timeout)
{
int c, mode_page = -1, page_control = 0;
- int binary = 0, list = 0;
+ int binary = 0, list = 0, force10bytes = 0;
while ((c = getopt(argc, argv, combinedopt)) != -1) {
switch(c) {
@@ -1711,6 +1714,9 @@ modepage(struct cam_device *device, int
if (mode_page < 0)
errx(1, "invalid mode page %d", mode_page);
break;
+ case 's':
+ force10bytes = 1;
+ break;
case 'P':
page_control = strtol(optarg, NULL, 0);
if ((page_control < 0) || (page_control > 3))
@@ -1728,11 +1734,11 @@ modepage(struct cam_device *device, int
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);
}
}
@@ -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
===================================================================
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
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_count,
- 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
===================================================================
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);
@@ -527,7 +528,7 @@ load_format(const char *pagedb_path, int
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)
{
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
/* Fetch changeable values; use to build initial editlist. */
mode_sense(device, modepage, 1, dbd, retries, timeout, data,
- sizeof(data));
+ sizeof(data), force10bytes);
mh = (struct scsi_mode_header_6 *)data;
mph = MODE_PAGE_HEADER(mh);
@@ -550,14 +551,14 @@ editlist_populate(struct cam_device *dev
/* 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);
}
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);
/* Initial headers & offsets. */
mh = (struct scsi_mode_header_6 *)data;
@@ -607,7 +608,8 @@ editlist_save(struct cam_device *device,
mode_select(device,
(page_control << PAGE_CTRL_SHIFT == 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);
}
static int
@@ -777,7 +779,7 @@ modepage_edit(void)
static void
modepage_dump(struct cam_device *device, int page, int page_control, int dbd,
- 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. */
mode_sense(device, page, page_control, dbd, retries, timeout, data,
- sizeof(data));
+ sizeof(data), force10bytes);
mh = (struct scsi_mode_header_6 *)data;
mph = MODE_PAGE_HEADER(mh);
@@ -812,7 +814,8 @@ cleanup_editfile(void)
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. */
@@ -842,7 +845,7 @@ mode_edit(struct cam_device *device, int
}
editlist_populate(device, page, page_control, dbd, retry_count,
- timeout);
+ timeout, force10bytes);
}
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
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
/* 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);
mh = (struct scsi_mode_header_6 *)data;
len = mh->blk_desc_len; /* Skip block descriptors. */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 167 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-current/attachments/20041006/a13309f3/attachment.bin
More information about the freebsd-current
mailing list