Date: Wed, 6 Oct 2004 03:49:04 -0700 From: Bruce M Simpson <bms@spc.org> To: freebsd-current@FreeBSD.org Subject: Re: camcontrol(8) and MODE_[SENSE|SELECT]_10 Message-ID: <20041006104904.GB1794@empiric.icir.org> In-Reply-To: <20041006095121.GA1794@empiric.icir.org> References: <20041006095121.GA1794@empiric.icir.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--n+lFg1Zro7sl44OB Content-Type: multipart/mixed; boundary="YToU2i3Vx8H2dn7O" Content-Disposition: inline --YToU2i3Vx8H2dn7O Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 --YToU2i3Vx8H2dn7O 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 10:44:30 -0000 @@ -65,9 +65,12 @@ int verbose =3D 0; =20 =20 /* 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) =20 +#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) =20 @@ -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); =20 =20 @@ -527,42 +531,53 @@ 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. */ - 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; =20 STAILQ_INIT(&editlist); =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); - mode_pars =3D MODE_PAGE_DATA(mph); + if (force10bytes) { + mh10 =3D (struct scsi_mode_header_10 *)data; + mph =3D MODE_PAGE_HEADER_10(mh10); + mode_pars =3D MODE_PAGE_DATA(mph); + data_length =3D scsi_2btoul(mh10->data_length); + } else { + mh6 =3D (struct scsi_mode_header_6 *)data; + mph =3D MODE_PAGE_HEADER_6(mh6); + mode_pars =3D MODE_PAGE_DATA(mph); + data_length =3D mh6->data_length; + } =20 /* 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); =20 /* 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); } =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. */ - 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; =20 /* 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); =20 /* Initial headers & offsets. */ - mh =3D (struct scsi_mode_header_6 *)data; - mph =3D MODE_PAGE_HEADER(mh); + mh6 =3D (struct scsi_mode_header_6 *)data; + mh10 =3D (struct scsi_mode_header_10 *)data; + if (force10bytes) { + mh_size =3D sizeof(*mh10); + mph =3D MODE_PAGE_HEADER_10(mh10); + data_length =3D scsi_2btoul(mh10->data_length); + } else { + mh_size =3D sizeof(*mh6); + mph =3D MODE_PAGE_HEADER_6(mh6); + data_length =3D mh6->data_length; + } + mode_pars =3D MODE_PAGE_DATA(mph); =20 /* 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); =20 /* Eliminate block descriptors. */ - bcopy(mph, ((u_int8_t *)mh) + sizeof(*mh), + bcopy(mph, ((u_int8_t *)data) + mh_size, sizeof(*mph) + mph->page_length); =20 /* Recalculate headers & offsets. */ - mh->blk_desc_len =3D 0; /* No block descriptors. */ - mh->dev_spec =3D 0; /* Clear device-specific parameters. */ - mph =3D MODE_PAGE_HEADER(mh); + /* Clear device-specific parameters. */ + if (force10bytes) { + scsi_ulto2b(0, mh10->blk_desc_len); + mh10->dev_spec =3D 0; + scsi_ulto2b(0, mh10->data_length); + mph =3D MODE_PAGE_HEADER_10(mh10); + mh_blk_desc_len =3D scsi_2btoul(&mh6->blk_desc_len); + } else { + mh6->blk_desc_len =3D 0; + mh6->dev_spec =3D 0; + mh6->data_length =3D 0; + mph =3D MODE_PAGE_HEADER_6(mh6); + mh_blk_desc_len =3D mh6->blk_desc_len; + } mode_pars =3D MODE_PAGE_DATA(mph); =20 - mph->page_code &=3D SMS_PAGE_CODE;/* Isolate just the page code. */ - mh->data_length =3D 0; /* Reserved for MODE SELECT command. */ + /* Isolate just the page code. */ + mph->page_code &=3D SMS_PAGE_CODE; =20 /* * 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 =3D=3D 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); } =20 static int @@ -777,19 +814,26 @@ 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. */ - 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. */ =20 mode_sense(device, page, page_control, dbd, retries, timeout, data, - sizeof(data)); + sizeof(data), force10bytes); + + mh6 =3D (struct scsi_mode_header_6 *)data; + mh10 =3D (struct scsi_mode_header_10 *)data; + + if (force10bytes) + mph =3D MODE_PAGE_HEADER_10(mh10); + else + mph =3D MODE_PAGE_HEADER_6(mh6); =20 - mh =3D (struct scsi_mode_header_6 *)data; - mph =3D MODE_PAGE_HEADER(mh); mode_pars =3D MODE_PAGE_DATA(mph); =20 /* Print the raw mode page data with newlines each 8 bytes. */ @@ -812,7 +856,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 +887,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 +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 =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 +930,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. */ --YToU2i3Vx8H2dn7O-- --n+lFg1Zro7sl44OB Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Comment: '' iD8DBQFBY82fueUpAYYNtTsRAsKkAKCUVQj3Y0UmZBVXOXepiPpFDBLyVACgnJ7S 2kxVDXJip/n6MeXeW/w4tzE= =jurb -----END PGP SIGNATURE----- --n+lFg1Zro7sl44OB--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20041006104904.GB1794>