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>