camcontrol(8) and MODE_[SENSE|SELECT]_10
Bruce M Simpson
bms at spc.org
Wed Oct 6 03:49:13 PDT 2004
Hi all,
On Wed, Oct 06, 2004 at 02:51:21AM -0700, Bruce M Simpson wrote:
> 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.
El stupido. I didn't realize that the mode page headers were different
sizes. Considering I haven't hacked on SCSI proper in 3-5 years this is
no big surprise.
Here's a revised patch which correctly fetches and displays the Mode
Page 0x5 (Flexible Disk Page) from my USB floppy drive (a fairly
common-or-garden Y-E Data FlashBuster):
empiric# camcontrol modepage 2:0:0 -m 0x05 -s
Transfer rate: 500
Number of heads: 2
Sectors per track: 18
Data bytes per sector: 512
Number of cylinders: 80
Starting cylinder-write precompensation: 0
Starting cylinder-reduced write current: 0
Drive step rate: 0
Drive step pulse width: 0
Head settle delay: 0
Motor on delay: 5
Motor off delay: 30
TRDY: 0
SSN: 0
MO: 0
SPC: 0
Write Compensation: 0
Head load delay: 0
Head unload delay: 0
Pin 34: 0
Pin 2: 0
Pin 4: 0
Pin 1: 0
Medium rotation rate: 300
This geometry looks correct. Please let me know your thoughts.
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 10:44:30 -0000
@@ -65,9 +65,12 @@ int verbose = 0;
/* Macros for working with mode pages. */
-#define MODE_PAGE_HEADER(mh) \
+#define MODE_PAGE_HEADER_6(mh) \
(struct scsi_mode_page_header *)find_mode_page_6(mh)
+#define MODE_PAGE_HEADER_10(mh) \
+ (struct scsi_mode_page_header *)find_mode_page_10(mh)
+
#define MODE_PAGE_DATA(mph) \
(u_int8_t *)(mph) + sizeof(struct scsi_mode_page_header)
@@ -110,10 +113,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 +126,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,42 +531,53 @@ 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. */
- struct scsi_mode_header_6 *mh; /* Location of mode header. */
+ u_int32_t data_length;
+ struct scsi_mode_header_6 *mh6;
+ struct scsi_mode_header_10 *mh10;
struct scsi_mode_page_header *mph;
STAILQ_INIT(&editlist);
/* 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);
- mode_pars = MODE_PAGE_DATA(mph);
+ if (force10bytes) {
+ mh10 = (struct scsi_mode_header_10 *)data;
+ mph = MODE_PAGE_HEADER_10(mh10);
+ mode_pars = MODE_PAGE_DATA(mph);
+ data_length = scsi_2btoul(mh10->data_length);
+ } else {
+ mh6 = (struct scsi_mode_header_6 *)data;
+ mph = MODE_PAGE_HEADER_6(mh6);
+ mode_pars = MODE_PAGE_DATA(mph);
+ data_length = mh6->data_length;
+ }
/* Decode the value data, creating edit_entries for each value. */
- buff_decode_visit(mode_pars, mh->data_length, format,
+ buff_decode_visit(mode_pars, data_length, format,
editentry_create, 0);
/* Fetch the current/saved values; use to set editentry values. */
mode_sense(device, modepage, page_control, dbd, retries, timeout, data,
- sizeof(data));
- buff_decode_visit(mode_pars, mh->data_length, format,
- editentry_update, 0);
+ sizeof(data), force10bytes);
+ buff_decode_visit(mode_pars, 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. */
- struct scsi_mode_header_6 *mh; /* Location of mode header. */
+ struct scsi_mode_header_6 *mh6;
+ struct scsi_mode_header_10 *mh10;
struct scsi_mode_page_header *mph;
+ u_int32_t data_length, mh_size, mh_blk_desc_len;
/* Make sure that something changed before continuing. */
if (! editlist_changed)
@@ -575,29 +590,50 @@ 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;
- mph = MODE_PAGE_HEADER(mh);
+ mh6 = (struct scsi_mode_header_6 *)data;
+ mh10 = (struct scsi_mode_header_10 *)data;
+ if (force10bytes) {
+ mh_size = sizeof(*mh10);
+ mph = MODE_PAGE_HEADER_10(mh10);
+ data_length = scsi_2btoul(mh10->data_length);
+ } else {
+ mh_size = sizeof(*mh6);
+ mph = MODE_PAGE_HEADER_6(mh6);
+ data_length = mh6->data_length;
+ }
+
mode_pars = MODE_PAGE_DATA(mph);
/* Encode the value data to be passed back to the device. */
- buff_encode_visit(mode_pars, mh->data_length, format,
+ buff_encode_visit(mode_pars, data_length, format,
editentry_save, 0);
/* Eliminate block descriptors. */
- bcopy(mph, ((u_int8_t *)mh) + sizeof(*mh),
+ bcopy(mph, ((u_int8_t *)data) + mh_size,
sizeof(*mph) + mph->page_length);
/* Recalculate headers & offsets. */
- mh->blk_desc_len = 0; /* No block descriptors. */
- mh->dev_spec = 0; /* Clear device-specific parameters. */
- mph = MODE_PAGE_HEADER(mh);
+ /* Clear device-specific parameters. */
+ if (force10bytes) {
+ scsi_ulto2b(0, mh10->blk_desc_len);
+ mh10->dev_spec = 0;
+ scsi_ulto2b(0, mh10->data_length);
+ mph = MODE_PAGE_HEADER_10(mh10);
+ mh_blk_desc_len = scsi_2btoul(&mh6->blk_desc_len);
+ } else {
+ mh6->blk_desc_len = 0;
+ mh6->dev_spec = 0;
+ mh6->data_length = 0;
+ mph = MODE_PAGE_HEADER_6(mh6);
+ mh_blk_desc_len = mh6->blk_desc_len;
+ }
mode_pars = MODE_PAGE_DATA(mph);
- mph->page_code &= SMS_PAGE_CODE;/* Isolate just the page code. */
- mh->data_length = 0; /* Reserved for MODE SELECT command. */
+ /* Isolate just the page code. */
+ mph->page_code &= SMS_PAGE_CODE;
/*
* Write the changes back to the device. If the user editted control
@@ -606,8 +642,9 @@ 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);
+ retries, timeout, (u_int8_t *)data,
+ mh_size + mh_blk_desc_len + sizeof(*mph) + mph->page_length,
+ force10bytes);
}
static int
@@ -777,19 +814,26 @@ 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. */
- struct scsi_mode_header_6 *mh; /* Location of mode header. */
+ struct scsi_mode_header_6 *mh6;
+ struct scsi_mode_header_10 *mh10;
struct scsi_mode_page_header *mph;
int indx; /* Index for scanning mode params. */
mode_sense(device, page, page_control, dbd, retries, timeout, data,
- sizeof(data));
+ sizeof(data), force10bytes);
+
+ mh6 = (struct scsi_mode_header_6 *)data;
+ mh10 = (struct scsi_mode_header_10 *)data;
+
+ if (force10bytes)
+ mph = MODE_PAGE_HEADER_10(mh10);
+ else
+ mph = MODE_PAGE_HEADER_6(mh6);
- mh = (struct scsi_mode_header_6 *)data;
- mph = MODE_PAGE_HEADER(mh);
mode_pars = MODE_PAGE_DATA(mph);
/* Print the raw mode page data with newlines each 8 bytes. */
@@ -812,7 +856,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 +887,7 @@ mode_edit(struct cam_device *device, int
}
editlist_populate(device, page, page_control, dbd, retry_count,
- timeout);
+ timeout, force10bytes);
}
if (edit) {
@@ -852,11 +897,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 +910,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 +930,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/ef49579f/attachment-0001.bin
More information about the freebsd-current
mailing list